🚀 AI 一键生成 ptrade 策略代码

PTrade 平台如何实现 R-Breaker 日内交易策略?(附源码)

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

问题描述

怎么写一个 R-Breaker 策略?

解决方案

R-Breaker 是一种经典的日内交易策略,结合了趋势跟随(Trend)和反转(Reversal)两种逻辑。它在量化交易中非常流行,尤其适用于期货市场,也可以用于波动较大的股票。

该策略的核心在于根据前一个交易日的最高价(High)、最低价(Low)和收盘价(Close)计算出 6 个关键价位(3 个阻力位和 3 个支撑位),并结合当日盘中的价格走势来触发交易信号。

以下是基于 PTrade 框架实现的 R-Breaker 策略代码及详细说明。

1. 策略原理与公式

基准价(Pivot):
$$Pivot = (High_{prev} + Low_{prev} + Close_{prev}) / 3$$

六个关键价位:

  1. 突破买入价(Bbreak / R3): $High_{prev} + 2 \times (Pivot - Low_{prev})$
  2. 观察卖出价(Ssetup / R1): $2 \times Pivot - Low_{prev}$
  3. 反转卖出价(Senter / R2): $Pivot + (High_{prev} - Low_{prev})$
  4. 反转买入价(Benter / S2): $Pivot - (High_{prev} - Low_{prev})$
  5. 观察买入价(Bsetup / S1): $2 \times Pivot - High_{prev}$
  6. 突破卖出价(Sbreak / S3): $Low_{prev} - 2 \times (High_{prev} - Pivot)$

交易逻辑:

  • 趋势策略(突破):
    • 若价格 > R3,开多仓(做多)。
    • 若价格 < S3,开空仓(做空)。
  • 反转策略:
    • 做空反转: 当日最高价 > R1(观察卖出价),且当前价格跌破 R2(反转卖出价)时,开空仓。
    • 做多反转: 当日最低价 < S1(观察买入价),且当前价格突破 S2(反转买入价)时,开多仓。
  • 日内平仓: 收盘前强制平仓。

2. PTrade 策略代码实现

以下代码可以直接复制到 PTrade 的策略编辑器中运行。为了演示方便,这里以股指期货(如 IF 主连)为例,因为 R-Breaker 需要做空机制才能发挥最大效用。如果是股票,只能做多和平仓。

import numpy as np

def initialize(context):
    """
    初始化函数,设置策略参数
    """
    # 设置标的:这里以沪深300股指期货主力合约为例
    # 如果是股票回测,请修改为具体股票代码,如 '600519.SS'
    g.security = 'IF2312.CCFX' 
    
    # 设置股票池
    set_universe([g.security])
    
    # 设置手续费(根据实际情况调整,期货通常按手或万分比)
    # set_commission(commission_ratio=0.0001, min_commission=5.0, type='FUTURE')
    
    # 策略参数
    g.open_position = 0  # 持仓状态:0空仓,1多仓,-1空仓
    
    # 每日盘前计算的关键价位
    g.R3 = 0 # 突破买入价
    g.R2 = 0 # 反转卖出价
    g.R1 = 0 # 观察卖出价
    g.S1 = 0 # 观察买入价
    g.S2 = 0 # 反转买入价
    g.S3 = 0 # 突破卖出价
    
    # 记录当日盘中的最高价和最低价
    g.high_today = 0
    g.low_today = 0
    
    # 设定每日收盘平仓时间
    run_daily(context, close_all_positions, time='14:55')

def before_trading_start(context, data):
    """
    盘前处理:获取昨日数据,计算 R-Breaker 的 6 个价位
    """
    # 获取过去 1 天的日线数据(不包含当天)
    # 注意:get_history 返回的是 DataFrame
    hist = get_history(1, frequency='1d', field=['high', 'low', 'close'], security_list=g.security, include=False)
    
    if len(hist) > 0:
        # 提取昨日数据
        # 注意:get_history 返回的 DataFrame 索引可能是时间,或者是多级索引,需根据 PTrade 版本处理
        # 这里假设返回的是标准 DataFrame,直接取最后一行
        high_prev = hist['high'].values[-1]
        low_prev = hist['low'].values[-1]
        close_prev = hist['close'].values[-1]
        
        # 计算 Pivot
        pivot = (high_prev + low_prev + close_prev) / 3.0
        
        # 计算 6 个关键价位
        g.R3 = high_prev + 2 * (pivot - low_prev)  # 突破买入
        g.S3 = low_prev - 2 * (high_prev - pivot)  # 突破卖出
        
        g.R1 = 2 * pivot - low_prev                # 观察卖出
        g.S1 = 2 * pivot - high_prev               # 观察买入
        
        g.R2 = pivot + (high_prev - low_prev)      # 反转卖出
        g.S2 = pivot - (high_prev - low_prev)      # 反转买入
        
        # 打印日志方便调试
        log.info("R-Breaker Levels for {}: R3={:.2f}, R2={:.2f}, R1={:.2f}, S1={:.2f}, S2={:.2f}, S3={:.2f}".format(
            g.security, g.R3, g.R2, g.R1, g.S1, g.S2, g.S3))
    
    # 重置当日最高最低价记录
    g.high_today = 0
    g.low_today = 1000000 # 设置一个极大值初始值

def handle_data(context, data):
    """
    盘中处理:每分钟运行一次,判断信号并交易
    """
    # 获取当前时间,如果是收盘平仓时间段则跳过逻辑
    current_hour = context.blotter.current_dt.hour
    current_minute = context.blotter.current_dt.minute
    if current_hour == 14 and current_minute >= 55:
        return

    security = g.security
    
    # 获取当前分钟的最新价、最高价、最低价
    # 注意:data[security] 获取的是当前分钟 Bar 的数据
    current_price = data[security]['close']
    current_high = data[security]['high']
    current_low = data[security]['low']
    
    # 更新当日盘中最高价和最低价
    # 如果是开盘第一分钟,直接赋值
    if g.high_today == 0:
        g.high_today = current_high
        g.low_today = current_low
    else:
        g.high_today = max(g.high_today, current_high)
        g.low_today = min(g.low_today, current_low)
        
    # 获取当前持仓数量
    position = get_position(security).amount
    
    # --- 交易逻辑 ---
    
    # 1. 趋势突破逻辑
    # 突破 R3,且空仓或持有空单 -> 做多
    if current_price > g.R3:
        if g.open_position <= 0:
            log.info("触发趋势买入信号:价格 {:.2f} > R3 {:.2f}".format(current_price, g.R3))
            order_target(security, 1) # 这里的 1 代表 1手,如果是股票代表 100股,需根据实际调整
            g.open_position = 1
            
    # 跌破 S3,且空仓或持有多单 -> 做空
    elif current_price < g.S3:
        if g.open_position >= 0:
            log.info("触发趋势卖出信号:价格 {:.2f} < S3 {:.2f}".format(current_price, g.S3))
            order_target(security, -1) # -1 代表持有空单 1手
            g.open_position = -1

    # 2. 反转逻辑
    # 做空反转:当日最高价超过 R1 (观察卖出价),且当前价格跌破 R2 (反转卖出价)
    elif g.high_today > g.R1 and current_price < g.R2:
        if g.open_position >= 0:
            log.info("触发反转卖出信号:最高价 {:.2f} > R1, 现价 {:.2f} < R2".format(g.high_today, current_price))
            order_target(security, -1)
            g.open_position = -1
            
    # 做多反转:当日最低价低于 S1 (观察买入价),且当前价格突破 S2 (反转买入价)
    elif g.low_today < g.S1 and current_price > g.S2:
        if g.open_position <= 0:
            log.info("触发反转买入信号:最低价 {:.2f} < S1, 现价 {:.2f} > S2".format(g.low_today, current_price))
            order_target(security, 1)
            g.open_position = 1

def close_all_positions(context):
    """
    收盘前强制平仓
    """
    security = g.security
    position = get_position(security).amount
    
    if position != 0:
        log.info("收盘前强制平仓")
        order_target(security, 0)
        g.open_position = 0

3. 代码关键点解析

  1. 数据获取 (get_history)

    • 我们在 before_trading_start 中调用 get_history 获取前一天的日线数据。
    • include=False 确保不包含当天的数据,避免未来函数。
  2. 盘中高低点追踪

    • R-Breaker 的反转逻辑依赖于“当日最高价是否触及观察线”。
    • 因此,我们在 handle_data 中使用 g.high_todayg.low_today 实时更新当日的最高和最低价。
  3. 交易执行 (order_target)

    • 使用 order_target(security, amount) 是最方便的调仓函数。
    • amount=1 表示目标持仓为多头 1 手(或 100 股)。
    • amount=-1 表示目标持仓为空头 1 手。
    • amount=0 表示平仓。
    • 注意:如果是股票交易,PTrade 不支持直接传入负数进行做空(除非开通融券并使用融券接口)。如果是股票策略,你需要修改逻辑为:买入信号买入,卖出信号仅平掉多头仓位。
  4. 日内平仓

    • R-Breaker 是典型的日内策略,不留隔夜仓以规避跳空风险。
    • 使用 run_daily14:55 触发 close_all_positions 函数清空仓位。

4. 常见问题与调整

  • 股票 vs 期货
    • 上述代码逻辑包含做空(order_target 设为负数)。如果你在做纯股票策略,请将所有涉及做空的代码(order_target(security, -1))改为 order_target(security, 0)(仅平仓),或者删除做空逻辑。
  • 参数优化
    • 标准的 R-Breaker 参数是固定的(系数为 2 和 1)。你可以尝试调整这些系数,或者根据波动率(ATR)来动态调整距离。
  • 回测频率
    • 请确保回测频率选择 “分钟” 级别,因为 handle_data 需要在盘中实时监控价格突破情况。

Q&A

Q: 为什么我的策略在股票回测中报错?
A: 股票通常不能直接做空。如果代码中执行了 order_target(security, -1) 而账户没有融券权限或回测不支持融券,会报错或忽略。请将做空逻辑改为平仓逻辑。

Q: 如何在实盘中使用?
A: 实盘中需要确保 g.security 是正确的合约代码(期货合约通常有月份后缀,如 IF2312.CCFX)。此外,实盘建议增加滑点控制和订单状态检查。

Q: 可以在 tick 级别运行吗?
A: 可以。PTrade 支持 tick_data 函数。你可以将 handle_data 中的逻辑迁移到 tick_data 中,以获得更快的响应速度(3秒一次),逻辑基本一致。