前言

PTrade 作为国内主流的量化交易平台,其核心优势之一在于事件驱动的业务流程框架—— 通过预设的各类事件函数,按交易日时间轴自动触发策略逻辑,适配从日线级中长线到 tick 级高频交易的全场景需求。

本文将详细拆解 PTrade 的代码业务流程,包括核心事件框架、必选 / 可选函数的作用、执行时机及实操用法,帮助量化开发者快速搭建策略结构,避免因流程不清晰导致的代码报错或逻辑失效。

一、PTrade 核心业务流程框架(事件驱动模型)

PTrade 量化引擎的核心是按交易日时间节点触发事件,整体流程分为 6 大模块:初始化、盘前准备、盘中交易、主推回报、盘后处理、定时任务。其中部分事件为必选(策略运行的基础),部分为可选(按需扩展功能)。

量化小白必看!手把手教你安装Python环境(下)

1. 流程框架总览表

执行阶段 事件 / 函数名称 支持级别 默认执行时机 核心作用 是否必选
初始化 initialize 全局 策略启动时(仅执行 1 次) 定义全局变量、加载历史数据、初始化参数 ✅ 必选
盘前准备 before_trading_start 日线 每日 9:10 当日参数初始化、股票池更新、盘前选股 ❌ 可选
盘中交易(常规) handle_data 日线 / 分钟级 日线:14:50;分钟级:9:30 起每 1 分钟 核心交易逻辑(信号判断、委托下单) ✅ 必选
盘中交易(高频) tick_data tick 级 每 3 秒执行 1 次 tick 级行情处理、高频交易信号捕捉 ❌ 可选
盘中交易(高频) run_interval tick 级 自定义间隔(最小 3 秒) 灵活控制高频执行节奏,适配复杂 tick 策略 ❌ 可选
主推回报 on_order_response 实时 委托状态变更时 跟踪委托进度(如拒单、部分成交) ❌ 可选
主推回报 on_trade_response 实时 成交发生时 成交后回调(如触发止损、补仓逻辑) ❌ 可选
定时任务 run_daily 自定义 任意交易时段时间 固定时间执行操作(如定时调仓、数据备份) ❌ 可选
盘后处理 after_trading_end 日线 每日 15:30 收益统计、交易日志生成、回测结果分析 ❌ 可选

2. 流程执行顺序示意图

plaintext

策略启动 → initialize(1次初始化)→ 每日循环:
  before_trading_start(9:10 盘前准备)→ 盘中交易:
    分钟级:handle_data(每1分钟执行) / tick级:tick_data/run_interval(高频执行)
    同步触发:on_order_response(委托回调)/ on_trade_response(成交回调)
    自定义触发:run_daily(指定时间执行)
  → after_trading_end(15:30 盘后处理)→ 次日重复

二、核心函数详细解析(用法 + 场景 + 示例)

1. 必选函数(策略基础骨架,缺一不可)

(1)initialize():策略初始化入口
  • 功能说明:仅在策略启动时(回测开始 / 实盘启动)执行 1 次,用于完成全局初始化操作,后续交易日不再重复执行。
  • 典型用法
    • 定义全局变量(如最大仓位、止损比例、股票池容器);
    • 加载静态数据(如行业分类、历史财务数据);
    • 初始化技术指标参数(如 MACD、RSI 的周期设置)。
  • 代码示例
def initialize(context):
    # 全局变量:最大单只股票仓位50%
    context.max_position = 0.5
    # 全局变量:止损比例8%
    context.stop_loss_ratio = 0.08
    # 初始化股票池(示例:沪深300成分股)
    context.stock_pool = get_index_stocks('000300.SH')
    # 初始化技术指标参数:MACD(12,26,9)
    context.macd_fast = 12
    context.macd_slow = 26
    context.macd_signal = 9
  • 注意事项:避免在该函数中定义每日变动的动态数据(如当日开盘价),否则数据不会实时更新。
(2)handle_data(context, data):核心交易逻辑载体
  • 功能说明:盘中按指定周期执行,是实现买卖信号判断、委托下单的核心函数,支持日线和分钟级两种周期(策略保存时配置)。
  • 周期差异说明
    • 日线级:默认 14:50 执行(临近收盘,减少日内波动干扰),适合中长线选股策略;
    • 分钟级:默认 9:30 起每 1 分钟执行 1 次,适合短线波段策略(如 5 分钟 K 线突破)。
  • 代码示例(日线级选股)
def handle_data(context, data):
    # 获取当前持仓
    positions = context.portfolio.positions
    # 遍历股票池,判断MACD金叉信号
    for stock in context.stock_pool:
        # 获取股票近30日收盘价
        close_price = data.history(stock, 'close', 30, '1d')
        # 计算MACD指标
        macd, signal, hist = talib.MACD(close_price, fastperiod=context.macd_fast, 
                                        slowperiod=context.macd_slow, signalperiod=context.macd_signal)
        # 金叉信号(MACD上穿信号线)且未持仓
        if macd[-1] > signal[-1] and macd[-2] < signal[-2] and stock not in positions:
            # 买入:仓位不超过max_position
            order_target_percent(stock, context.max_position)
        # 死叉信号(MACD下穿信号线)且已持仓
        elif macd[-1] < signal[-1] and macd[-2] > signal[-2] and stock in positions:
            # 卖出:清仓该股票
            order_target(stock, 0)
  • 注意事项:函数参数 context 存储全局上下文(如持仓、资金),data 用于获取行情数据,不可省略。

2. 可选函数(功能扩展,按需添加)

(1)盘前 / 盘后辅助函数
before_trading_start(context)
  • 功能:每日开盘前(默认 9:10)执行 1 次,用于处理当日动态初始化逻辑。
  • 典型场景
    • 更新股票池(如剔除 ST 股、停牌股);
    • 获取当日资金可用额度;
    • 加载当日行业景气度数据。
  • 代码示例
def before_trading_start(context):
    # 过滤股票池:剔除ST股、停牌股
    filtered_pool = []
    for stock in context.stock_pool:
        # 判断是否ST股
        is_st = get_securities_info(stock).display_name.find('ST') != -1
        # 判断是否停牌
        is_suspended = data.is_suspended(stock)
        if not is_st and not is_suspended:
            filtered_pool.append(stock)
    # 更新全局股票池
    context.stock_pool = filtered_pool
after_trading_end(context)
  • 功能:每日收盘后(默认 15:30)执行 1 次,用于盘后数据处理。
  • 典型场景
    • 统计当日盈亏情况;
    • 生成交易日志;
    • 回测时输出策略绩效指标(收益率、最大回撤)。
  • 代码示例
def after_trading_end(context):
    # 获取当日收益
    daily_return = context.portfolio.daily_return
    # 获取当前总资产
    total_asset = context.portfolio.total_value
    # 打印日志
    log.info(f"当日收益率:{daily_return:.2%},当前总资产:{total_asset:.2f}元")
    # 保存日志到文件(需提前配置文件路径)
    with open('/data/trade_log.txt', 'a') as f:
        f.write(f"{context.current_dt.strftime('%Y-%m-%d')}, {daily_return:.2%}, {total_asset:.2f}\n")
(2)tick 级高频交易函数
tick_data(context, data)
  • 功能:tick 级策略专用,固定每 3 秒执行 1 次,无需手动设置间隔。
  • 典型场景:盘口数据捕捉(如买一卖一挂单量变化)、瞬时价格突破交易。
  • 代码示例
def tick_data(context, data):
    # 跟踪目标股票:贵州茅台
    stock = '600519.SH'
    # 获取当前盘口数据(买一价、卖一价、买一量、卖一量)
    bid_price = data.current(stock, 'bid_price_1')
    ask_price = data.current(stock, 'ask_price_1')
    bid_volume = data.current(stock, 'bid_volume_1')
    ask_volume = data.current(stock, 'ask_volume_1')
    
    # 策略逻辑:买一量突然放大(≥500手)且未持仓,买入
    if bid_volume >= 50000 and stock not in context.portfolio.positions:
        order(stock, 100, style=LimitOrderStyle(ask_price))  # 以卖一价限价买入
    # 策略逻辑:卖一量突然放大(≥500手)且已持仓,卖出
    elif ask_volume >= 50000 and stock in context.portfolio.positions:
        order(stock, -100, style=LimitOrderStyle(bid_price))  # 以买一价限价卖出
run_interval(context, data, interval=5)
  • 功能:灵活控制 tick 级执行间隔,最小支持 3 秒,适配复杂高频策略。
  • 参数说明interval 为执行间隔(单位:秒),需≥3。
  • 代码示例(每 5 秒执行 1 次):
# 注册定时执行:每5秒执行1次
run_interval(interval=5)
def run_interval(context, data):
    # 逻辑同tick_data,可根据间隔灵活调整
    stock = '600519.SH'
    current_price = data.current(stock, 'close')
    # 简单策略:价格突破当日均价,买入
    daily_avg = data.history(stock, 'close', 240, '1m').mean()  # 当日分钟级均价
    if current_price > daily_avg and stock not in context.portfolio.positions:
        order_target_percent(stock, 0.1)
(3)委托 / 成交回调函数
on_order_response(context, order)
  • 功能:委托状态变更时(如委托提交、拒单、部分成交、撤单)触发,用于跟踪委托进度。
  • 代码示例
def on_order_response(context, order):
    # 获取委托信息
    order_id = order.order_id
    stock = order.symbol
    order_type = '买入' if order.side == 1 else '卖出'
    status = order.status  # 委托状态:0=未提交,1=已提交,2=部分成交,3=全部成交,4=拒单,5=撤单
    
    # 打印委托日志
    log.info(f"委托ID:{order_id},{order_type}{stock},状态:{status},委托数量:{order.amount},委托价格:{order.price}")
    
    # 拒单处理:资金不足时,减少买入数量重新委托
    if status == 4 and order.side == 1:
        available_cash = context.portfolio.cash
        new_amount = int(available_cash / order.price / 100) * 100  # 按100股整数倍调整
        if new_amount > 0:
            order(stock, new_amount, style=LimitOrderStyle(order.price))
            log.info(f"资金不足,调整买入数量为{new_amount}股,重新委托")
on_trade_response(context, trade)
  • 功能:成交发生时触发,可用于执行成交后的后续逻辑(如设置止损、调整仓位)。
  • 代码示例
def on_trade_response(context, trade):
    # 获取成交信息
    stock = trade.symbol
    trade_type = '买入成交' if trade.side == 1 else '卖出成交'
    trade_amount = trade.amount
    trade_price = trade.price
    trade_time = trade.time.strftime('%H:%M:%S')
    
    # 打印成交日志
    log.info(f"{trade_time},{trade_type}{stock},数量:{trade_amount}股,价格:{trade_price}元")
    
    # 买入成交后,设置动态止损(跌破成交价8%止损)
    if trade.side == 1:
        stop_loss_price = trade_price * (1 - context.stop_loss_ratio)
        # 提交止损条件单
        order_condition(stock, 'STOP_LOSS', stop_loss_price, trade_amount)
        log.info(f"已为{stock}设置止损条件单,止损价:{stop_loss_price:.2f}元")
(4)定时任务函数 run_daily(context, data, time='10:00')
  • 功能:在指定交易时段时间执行自定义逻辑,不受周期限制。
  • 参数说明time 为执行时间(格式:HH:MM),需在 9:30-11:30 或 13:00-15:00 内。
  • 代码示例(每日 10:00 调仓):
# 注册定时任务:每日10:00执行
run_daily(time='10:00')
def run_daily(context, data):
    # 每日10:00 重新筛选股票池(示例:选择当日涨幅前5的沪深300成分股)
    current_stocks = context.stock_pool
    # 获取当日涨幅
   涨幅_dict = {}
    for stock in current_stocks:
        open_price = data.history(stock, 'open', 1, '1d')[0]
        current_price = data.current(stock, 'close')
        涨幅 = (current_price - open_price) / open_price
        涨幅_dict[stock] = 涨幅
    # 排序:取涨幅前5的股票
    target_stocks = sorted(涨幅_dict.items(), key=lambda x: x[1], reverse=True)[:5]
    target_stocks = [stock for stock, _ in target_stocks]
    
    # 调仓:卖出不在目标池的股票,买入目标池股票(均配20%仓位)
    for stock in context.portfolio.positions:
        if stock not in target_stocks:
            order_target(stock, 0)
    for stock in target_stocks:
        order_target_percent(stock, 0.2)

三、不同策略场景的函数组合推荐

策略类型 推荐函数组合 核心优势
日线级中长线选股 initialize + handle_data(日线) 结构简单,无需盯盘,适配中长线逻辑
分钟级短线波段 initialize + before_trading_start + handle_data(分钟) 盘前筛选股票,盘中实时跟踪信号
tick 级高频交易 initialize + tick_data + on_trade_response 高频捕捉行情,成交后快速回调
定时调仓策略 initialize + run_daily + after_trading_end 固定时间执行,适合纪律性调仓
复杂多逻辑策略 initialize + before_trading_start + handle_data + on_order_response + after_trading_end 全流程覆盖,适配复杂交易需求

四、实操注意事项(避坑指南)

  1. 必选函数不可省略:任何策略都必须包含 initializehandle_data,否则会报 “策略结构不完整” 错误;
  2. 周期与函数匹配:日线级 handle_data 中无法获取 tick 级数据(如盘口挂单),需根据策略周期选择对应函数;
  3. 全局变量慎用initialize 中定义的变量为全局静态变量,若需每日更新,需在 before_trading_start 中重写;
  4. tick 级策略性能优化tick_datarun_interval 中逻辑需简洁,避免嵌套过多循环(否则会导致执行延迟,错过行情);
  5. 时间参数合规性before_trading_startafter_trading_endrun_daily 的执行时间需在交易所规定的交易时段内,否则无法触发;
  6. 委托 / 成交回调的依赖on_order_responseon_trade_response 需配合 order 类函数使用,单独定义不会触发。

五、结语

PTrade 的事件驱动框架设计,既保证了策略的灵活性(按需组合函数),又降低了开发门槛(固定流程无需关注底层实现)。新手开发者可先通过 initialize + handle_data 搭建基础策略,再逐步添加盘前 / 盘后函数、tick 级函数丰富功能;高频交易开发者则可重点利用 tick_datarun_interval 及委托 / 成交回调函数,实现低延迟、高响应的交易逻辑。

如果需要获取 PTrade 官方函数 API 文档或更多复杂场景的代码示例(如多因子策略、套利策略),可留言交流!

参考资料:PTrade 量化交易平台官方开发文档(需要可提供)

Logo

魔乐社区(Modelers.cn) 是一个中立、公益的人工智能社区,提供人工智能工具、模型、数据的托管、展示与应用协同服务,为人工智能开发及爱好者搭建开放的学习交流平台。社区通过理事会方式运作,由全产业链共同建设、共同运营、共同享有,推动国产AI生态繁荣发展。

更多推荐