🚀 AI 一键生成 ptrade 策略代码

如何在 PTrade 中实现开盘区间突破(ORB)日内交易策略?

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

问题描述

帮我写一个开盘区间突破的日内交易策略,比如以前30分钟的高低点作为突破信号。

解决方案

这是一个基于**开盘区间突破(Opening Range Breakout, ORB)**的日内交易策略。

策略逻辑说明

  1. 确定区间:记录开盘后前30分钟(09:30 - 10:00)内的最高价和最低价,作为当日的“波动区间”。
  2. 突破买入:当时间超过10:00后,如果价格突破区间最高价,则视为多头信号,全仓买入。
  3. 止损/反转:如果持仓期间价格跌破区间最低价,则视为趋势反转或假突破,立即平仓止损。
  4. 尾盘平仓:由于是日内策略,无论盈亏,在收盘前(例如 14:55)强制平仓,不持仓过夜。

注意事项(重要)

  • T+1 限制:中国A股市场实行 T+1 交易制度(当日买入的股票当日不能卖出)。因此,此策略在普通股票实盘中无法实现当日买入当日卖出。
  • 适用场景
    1. 期货/期权:支持 T+0。
    2. ETF/LOF 基金:部分支持 T+0。
    3. 底仓做 T:如果您账户里已有该股票的底仓,可以通过买入和卖出底仓来实现变相的 T+0。
    4. 回测研究:用于验证策略有效性。

以下代码以股票/ETF为例编写,假设环境支持 T+0 或用于回测研究。

策略代码

def initialize(context):
    """
    初始化函数,设置股票池和全局变量
    """
    # 设置要操作的标的,这里以 510300.SS (沪深300ETF) 为例
    # 如果是股票,请注意 T+1 限制
    g.security = '510300.SS'
    set_universe(g.security)
    
    # 策略参数设置
    g.setup_end_time = '10:00'  # 区间建立结束时间
    g.exit_time = '14:55'       # 尾盘强制平仓时间
    
    # 设置回测频率为分钟级,因为需要判断分钟K线突破
    # 注意:在回测界面请选择“分钟”频率

def before_trading_start(context, data):
    """
    盘前处理,每天开盘前重置当日变量
    """
    # 初始化当日的最高价和最低价
    g.day_high = 0
    g.day_low = 99999
    
    # 标记是否已经记录完区间
    g.range_recorded = False
    
    # 标记当日是否已经开仓,避免重复开仓
    g.has_traded = False

def handle_data(context, data):
    """
    盘中运行函数,每分钟执行一次
    """
    # 获取当前时间字符串,格式如 '09:31', '14:00'
    current_time = context.blotter.current_dt.strftime('%H:%M')
    
    # 获取标的当前价格
    security = g.security
    # 检查标的是否停牌或数据不存在
    if security not in data:
        return
        
    current_price = data[security]['close']
    
    # -------------------------------------------------------
    # 第一阶段:09:30 - 10:00 建立开盘区间
    # -------------------------------------------------------
    if current_time <= g.setup_end_time:
        # 更新区间最高价
        if current_price > g.day_high:
            g.day_high = current_price
        # 更新区间最低价
        if current_price < g.day_low:
            g.day_low = current_price
            
        # 如果正好是 10:00,打印一下确定的区间
        if current_time == g.setup_end_time:
            g.range_recorded = True
            log.info("区间建立完成: High=%.2f, Low=%.2f" % (g.day_high, g.day_low))
            
    # -------------------------------------------------------
    # 第二阶段:10:00 - 14:55 交易判断
    # -------------------------------------------------------
    elif current_time < g.exit_time:
        # 确保区间已建立
        if not g.range_recorded:
            return

        # 获取当前持仓数量
        position = get_position(security).amount
        
        # 1. 开仓逻辑:价格突破区间高点,且当前无持仓,且当日未交易过
        # (g.has_traded 限制每天只做一次突破,防止震荡市反复止损)
        if current_price > g.day_high and position == 0 and not g.has_traded:
            # 获取可用资金
            cash = context.portfolio.cash
            if cash > 0:
                # 全仓买入
                order_value(security, cash)
                g.has_traded = True
                log.info("向上突破买入: Price=%.2f > RangeHigh=%.2f" % (current_price, g.day_high))
        
        # 2. 止损逻辑:价格跌破区间低点,且当前有持仓
        elif current_price < g.day_low and position > 0:
            # 卖出所有持仓
            order_target(security, 0)
            log.info("跌破区间止损: Price=%.2f < RangeLow=%.2f" % (current_price, g.day_low))

    # -------------------------------------------------------
    # 第三阶段:14:55 尾盘强制平仓
    # -------------------------------------------------------
    elif current_time >= g.exit_time:
        position = get_position(security).amount
        if position > 0:
            order_target(security, 0)
            log.info("尾盘强制平仓: Time=%s" % current_time)

代码关键点解析

  1. 时间控制

    • 使用 context.blotter.current_dt.strftime('%H:%M') 获取当前分钟的时间字符串,用于区分“区间建立期”、“交易期”和“尾盘平仓期”。
  2. 区间记录

    • 09:3010:00 之间,不断比较 current_priceg.day_high / g.day_low,从而动态锁定前30分钟的极值。
  3. 交易信号

    • 买入current_price > g.day_high。这里加了 not g.has_traded 限制,意味着每天只博弈一次突破,避免在震荡行情中反复开仓止损造成巨额亏损。
    • 止损current_price < g.day_low。如果突破失败掉头向下,跌破了起涨区间的下沿,立即离场。
  4. 资金管理

    • 使用 order_value(security, cash) 进行全仓买入。
    • 使用 order_target(security, 0) 进行清仓卖出。

Q&A

Q1: 如果我想做期货(可以做空),代码怎么改?
A1: 期货需要使用 buy_open (多开), sell_close (多平), sell_open (空开), buy_close (空平)。
逻辑上:

  • 价格 < g.day_lowsell_open (做空)。
  • 做空止损:价格 > g.day_high 时平空。

Q2: 为什么回测时没有成交?
A2:

  1. 请检查回测频率是否设置为**“分钟”**级别。日线级别无法获取 10:00 的价格。
  2. 请检查标的是否在 10:00 之后真的突破了前30分钟的高点。
  3. 如果是股票回测,请确认资金是否足够买入一手(100股)。

Q3: 如何修改区间时间?
A3: 修改 initialize 函数中的 g.setup_end_time 变量,例如改为 '09:45' 即为前15分钟突破策略。