🚀 AI 一键生成 ptrade 策略代码

PTrade 量化交易:如何实现经典的 Dual Thrust 日内策略?(附 Python 源码)

ptrade | 发布时间: 2025/12/16
以下内容由 EasyQuant 生成。

问题描述

请帮我用 Python 写一个 Dual Thrust(双重推力)日内交易策略

解决方案

这是一个基于 Dual Thrust (双重推力) 算法的日内交易策略实现。

策略原理

Dual Thrust 是一种经典的日内突破策略,由 Michael Chalek 开发。它的核心逻辑是根据前 N 天的最高价(High)、最低价(Low)和收盘价(Close)来确定一个震荡区间(Range),结合当天的开盘价(Open)计算出买入和卖出的触发轨。

计算公式:

  1. Range (震荡区间) = $Max(HH - LC, HC - LL)$
    • $HH$: 过去 N 日的最高价
    • $LC$: 过去 N 日的最低收盘价
    • $HC$: 过去 N 日的最高收盘价
    • $LL$: 过去 N 日的最低价
  2. 上轨 (Buy Line) = 当日开盘价 + $K1 \times Range$
  3. 下轨 (Sell Line) = 当日开盘价 - $K2 \times Range$

交易逻辑:

  • 当价格突破上轨时,做多(买入)。
  • 当价格跌破下轨时,平仓或做空(本代码示例为股票策略,故触及下轨时执行平仓操作)。
  • 日内策略:每日收盘前(如 14:55)强制平仓,不持仓过夜。

Python 策略代码 (PTrade)

# Dual Thrust 日内交易策略
# 适用频率:分钟级别 (建议 1m 或 5m)

import numpy as np

def initialize(context):
    """
    初始化函数,设置策略参数和全局变量
    """
    # 1. 设置标的股票 (例如:贵州茅台)
    g.security = '600519.SS'
    set_universe(g.security)
    
    # 2. 策略参数设置
    g.N = 5          # 回溯天数,用于计算 Range
    g.K1 = 0.2       # 上轨系数 (Buy Trigger)
    g.K2 = 0.2       # 下轨系数 (Sell Trigger)
    
    # 3. 全局变量初始化
    g.range = 0.0        # 震荡区间
    g.buy_line = 0.0     # 上轨
    g.sell_line = 0.0    # 下轨
    g.day_open = None    # 当日开盘价
    
    # 4. 设置定时任务:收盘前强制平仓 (日内策略)
    # 时间设置为 14:55,预留 5 分钟进行清仓
    run_daily(context, close_all_positions, time='14:55')

def before_trading_start(context, data):
    """
    盘前处理:计算前 N 天的 Range
    """
    # 重置当日开盘价状态
    g.day_open = None
    
    # 获取过去 N 天的历史数据 (不包含今天)
    # 字段:最高价 high, 最低价 low, 收盘价 close
    hist = get_history(g.N, '1d', ['high', 'low', 'close'], g.security, fq=None, include=False)
    
    # 如果数据不足 N 天,则不进行计算
    if len(hist) < g.N:
        log.info("历史数据不足,跳过 Range 计算")
        g.range = 0.0
        return

    # 计算 Dual Thrust 的核心参数
    # HH: N日最高价的最高值
    hh = hist['high'].max()
    # HC: N日收盘价的最高值
    hc = hist['close'].max()
    # LC: N日收盘价的最低值
    lc = hist['close'].min()
    # LL: N日最低价的最低值
    ll = hist['low'].min()
    
    # Range = Max(HH - LC, HC - LL)
    g.range = max(hh - lc, hc - ll)
    
    log.info("今日 Range 计算完成: %.2f" % g.range)

def handle_data(context, data):
    """
    盘中运行:每分钟执行一次,判断突破逻辑
    """
    # 如果 Range 未计算或为 0,直接返回
    if g.range == 0.0:
        return

    # 1. 获取当日开盘价
    # 注意:在分钟回测中,第一根 K 线的 open 即视为当日开盘价
    if g.day_open is None:
        current_open = data[g.security]['open']
        # 简单的过滤:确保开盘价有效
        if current_open > 0:
            g.day_open = current_open
            # 计算上下轨
            g.buy_line = g.day_open + g.K1 * g.range
            g.sell_line = g.day_open - g.K2 * g.range
            log.info("今日开盘价: %.2f, 上轨: %.2f, 下轨: %.2f" % (g.day_open, g.buy_line, g.sell_line))
        else:
            return # 等待有效开盘价

    # 2. 获取当前最新价格
    current_price = data[g.security]['close']
    
    # 获取当前持仓数量
    position = get_position(g.security).amount
    # 获取当前可用资金
    cash = context.portfolio.cash

    # 3. 交易逻辑
    
    # 情况 A: 价格突破上轨 -> 做多 (买入)
    if current_price > g.buy_line:
        # 如果当前空仓,则全仓买入
        if position == 0:
            log.info("价格突破上轨 (%.2f > %.2f),触发买入" % (current_price, g.buy_line))
            # 使用 order_value 按金额下单,这里示例为使用所有现金买入
            order_value(g.security, cash)
            
    # 情况 B: 价格跌破下轨 -> 平仓 (卖出)
    # 注意:如果是股票策略,通常只能平仓;如果是期货,这里可以反手做空
    elif current_price < g.sell_line:
        # 如果当前持有股票,则清仓卖出
        if position > 0:
            log.info("价格跌破下轨 (%.2f < %.2f),触发止损/平仓" % (current_price, g.sell_line))
            order_target(g.security, 0)

def close_all_positions(context):
    """
    收盘前强制平仓函数
    """
    position = get_position(g.security).amount
    if position > 0:
        log.info("日内策略收盘强制平仓")
        order_target(g.security, 0)

代码说明与 SEO Q&A

1. 核心函数解析

  • before_trading_start: 利用 get_history 获取过去 N 天的日线数据。这是 Dual Thrust 策略的关键,因为它依赖历史波动率来定义当天的震荡区间。
  • handle_data: 这是策略的执行引擎。
    • 它首先捕获当天的 Open (开盘价)。在 PTrade 分钟级别回测中,我们通常取当天的第一分钟 Open 作为当天的开盘价。
    • 计算出 buy_line (上轨) 和 sell_line (下轨)。
    • 实时监控价格,一旦突破上轨就买入,跌破下轨就卖出。
  • close_all_positions: 通过 run_daily 在 14:55 触发。这是日内策略的风控核心,确保不持仓过夜,规避隔夜跳空风险。

2. 参数调整建议

  • g.N (回溯天数): 默认为 5 天。如果希望策略对短期波动更敏感,可以减小 N;如果希望捕捉更长期的趋势,可以增大 N。
  • g.K1g.K2: 这是触发系数。
    • 如果 K 值较小,区间变窄,交易会更频繁,容易出现假突破。
    • 如果 K 值较大,区间变宽,信号更稳健,但可能错过部分行情。
    • 非对称设置: 在多头市场中,可以设置 $K1 < K2$ (更容易买入);在空头市场中,设置 $K1 > K2$ (更容易卖出)。

Q&A (常见问题)

Q1: 这个策略可以直接用于期货交易吗?
A: 代码逻辑通用,但需要微调。目前的 handle_data 逻辑是“跌破下轨平仓”。如果是期货交易,你可能希望在跌破下轨时开空单 (Short)。你需要将 order_target(g.security, 0) 修改为 order_target_value(g.security, -cash) 或使用 sell_open 等期货专用接口。

Q2: 为什么在 handle_data 里判断 g.day_open
A: PTrade 的 get_price 接口在回测模式下,获取当日数据有时会有延迟或不包含当日数据。最稳健的方法是在 handle_data 运行的第一时间(即开盘时)直接读取行情的 open 字段并存储在全局变量中,确保全天使用的基准开盘价一致。

Q3: 如何回测这个策略?
A: 在 PTrade 客户端中,新建一个策略,将上述代码粘贴进去。设置回测频率为 “分钟” (这一点很重要,因为是日内策略),选择一个起止时间,设置初始资金即可开始回测。