问题描述
/
解决方案
在 Ptrade 量化交易平台中,回测环境和实盘(交易)环境使用的是同一套 API 体系,但底层的数据源处理逻辑和时间基准存在显著差异。了解这些差异并掌握切换技巧,是保证策略从回测平稳过渡到实盘的关键。
一、 回测数据源与实盘数据源的不同点
1. 时间基准(Time Context)不同
- 回测数据源:时间是虚拟的、历史的。当你在回测中调用
get_history或get_price时,系统会根据当前回测进行到的虚拟时间(即context.blotter.current_dt)来返回该时间点之前的数据。它不会返回未来的数据(防止未来函数)。 - 实盘数据源:时间是真实的、当下的。在交易模块中调用相同的接口,系统会根据服务器当前的真实物理时间返回最新的行情数据。
2. 数据粒度与接口支持不同
- 回测环境:主要支持日线(1d)和分钟线(1m, 5m等)级别的历史 K 线数据。回测引擎通过
handle_data按设定的频率(日或分钟)推进。 - 实盘环境:除了支持 K 线数据外,还支持更精细的 Tick 级别数据和实时主推数据。例如,实盘中可以使用
tick_data函数获取每3秒一次的快照,使用get_snapshot获取实时盘口,以及使用on_order_response和on_trade_response接收实时的委托和成交主推。
3. 停牌与缺失数据处理
- Ptrade 在处理停牌时,时间轴均为二级市场交易日日历。停牌时使用停牌前的数据填充,成交量为0。这一点在回测和实盘的历史数据获取中是一致的,但在实盘中,你可以通过
get_snapshot的trade_status字段实时判断股票是否处于停牌状态(如返回 'HALT' 或 'SUSP')。
二、 如何在回测和实盘之间切换?
在 Ptrade 中,你不需要手动更改数据源的连接地址或配置。平台通过运行模块(回测模块 vs 交易模块)自动为你路由到正确的数据源。
为了让同一套策略代码能够同时兼容回测和实盘环境,Ptrade 提供了 is_trade() 函数。你可以利用这个函数在代码中进行逻辑分支处理。
使用 is_trade() 进行环境兼容
is_trade() 函数用于判断当前代码是否运行在交易(实盘/模拟盘)环境中。如果是,返回 True;如果在回测环境中,返回 False。
代码示例:
def initialize(context):
g.security = '600570.SS'
set_universe(g.security)
def handle_data(context, data):
# 获取历史数据,回测和实盘调用方式完全一样
# 回测时返回虚拟时间前的数据,实盘时返回真实当前时间前的数据
hist = get_history(5, '1d', 'close', g.security)
# 区分回测和实盘的特定逻辑
if is_trade():
log.info("当前运行场景:实盘交易")
# 实盘中可以获取实时快照
snapshot = get_snapshot(g.security)
if snapshot and snapshot.get(g.security):
current_price = snapshot[g.security]['last_px']
log.info(f"实盘最新价: {current_price}")
else:
log.info("当前运行场景:历史回测")
# 回测中通常直接使用 data 对象获取当前周期的价格
current_price = data[g.security]['close']
log.info(f"回测当前周期收盘价: {current_price}")
# 下单逻辑(API一致,底层自动路由)
if current_price > hist['close'].mean():
order(g.security, 100)
总结
- 数据源差异:核心在于时间基准(虚拟历史 vs 真实当下)和数据维度(K线 vs Tick/主推)。
- 切换方式:无需修改 API 接口,只需在 Ptrade 界面选择不同的运行模块。在代码内部,使用
is_trade()函数来处理回测和实盘中可能存在的逻辑差异(如实盘特有的快照查询或主推处理)。