🚀 AI 一键生成 ptrade 策略代码
立即体验
👉 AI 生成代码 👈

ptrade 平台回测策略如何无缝切换到模拟盘与实盘?

ptrade | 发布时间: 2026/6/1
以下内容由 EasyQuant 生成。

问题描述

那你知道低代码回测完怎么用到模拟盘吗?

解决方案

在 ptrade 平台中,将回测完成的策略(无论是低代码生成还是手写代码)应用到模拟盘或实盘,并不是简单的“一键运行”。实盘环境面临着服务器重启、网络延迟、数据缺失等复杂情况。以下是将策略从回测迁移到模拟盘/实盘的核心步骤和注意事项:

1. 变量持久化处理(至关重要)

实盘和模拟盘可能会遇到券商环境重启或升级。如果策略依赖历史状态(如持仓天数、分批建仓状态),必须进行持久化处理。

  • 框架自动持久化:ptrade 框架会在 before_trading_starthandle_dataafter_trading_end 后自动使用 pickle 保存全局变量 g 中的内容。
  • 重启恢复机制:环境重启后,框架会先执行 initialize,然后用持久化的信息覆盖 g 中的同名变量。
  • 私有变量与不可序列化对象:如果 g 中有不能被序列化的对象(如打开的文件、实例化的类),必须在 initialize 中以 __ 开头命名(如 g.__test_class),这样框架持久化时会跳过它。

2. 配置实盘防重复执行参数

在实盘/模拟盘中,服务器重启可能导致函数被重复调用,从而引发重复下单。必须在 initialize 中使用 set_parameters 进行防护:

def initialize(context):
    # not_restart_trade="1": 交易时间段若服务器重启,不自动执行重新拉起本交易
    # server_restart_not_do_before="1": 若服务器重启导致重拉交易,不重复执行 before_trading_start
    set_parameters(not_restart_trade="1", server_restart_not_do_before="1")

3. 增加异常处理机制

实盘中可能会遇到行情数据缺失或接口超时,必须使用 try...except 保护核心逻辑,防止策略因报错而直接终止。

try:
    # 尝试获取数据或下单
    current_price = data[security]['close']
except Exception as e:
    log.error("获取价格异常: %s" % e)

4. 注意委托价格的精度

实盘对价格精度要求严格,否则会导致废单:

  • 股票:小数点后 2 位
  • 可转债、ETF、LOF:小数点后 3 位
  • 股指期货:小数点后 1 位
    在调用 order()order_target() 传入 limit_price 时,务必使用 round(price, 2) 等方法处理精度。

5. 谨慎使用 order_target 系列函数

在模拟盘/实盘中,柜台返回持仓数据通常有延迟(如 6 秒左右)。如果在延迟期间连续调用 order_target,由于持仓未更新,会导致重复下单。建议:

  • 使用 order() 按绝对数量下单。
  • 或者在策略内部自行维护一个字典记录已委托数量,避免依赖柜台的实时持仓。

6. 启用主推事件(进阶)

为了更快地获取订单和成交状态,可以在策略中加入 on_order_responseon_trade_response 函数,这比轮询 get_orders() 效率更高。

模拟盘部署模板示例

import pickle
from collections import defaultdict

def initialize(context):
    g.security = '600570.SS'
    set_universe(g.security)
    
    # 1. 实盘防重启重复执行配置
    set_parameters(not_restart_trade="1", server_restart_not_do_before="1")
    
    # 2. 自定义持久化(可选,框架默认也会保存g变量)
    try:
        with open(get_research_path() + 'my_status.pkl', 'rb') as f:
            g.my_status = pickle.load(f)
    except:
        g.my_status = defaultdict(int)

def before_trading_start(context, data):
    # 盘前逻辑
    pass

def handle_data(context, data):
    try:
        current_price = data[g.security]['close']
        cash = context.portfolio.cash
        
        # 简单的买入逻辑
        if current_price > 30 and g.my_status[g.security] == 0:
            # 注意价格精度
            order(g.security, 100, limit_price=round(current_price * 1.01, 2))
            g.my_status[g.security] = 1
            
    except Exception as e:
        log.error("交易逻辑发生异常: %s" % e)

def after_trading_end(context, data):
    # 盘后保存自定义状态
    with open(get_research_path() + 'my_status.pkl', 'wb') as f:
        pickle.dump(g.my_status, f, -1)

总结:低代码生成的回测代码通常只包含最基础的 initializehandle_data。要上模拟盘,你需要将生成的代码复制到交易模块,并根据上述指南加入防重启配置、异常处理和精度控制,确保策略在真实环境下的健壮性。