问题描述
策略执行tick_data时出现延迟或丢失
解决方案
在PTrade量化平台中,编写Tick级别的交易策略(主要通过tick_data函数实现)对代码的执行效率要求极高。如果您在实盘或模拟中发现tick_data出现延迟、卡顿或数据丢失,通常是因为策略内部逻辑耗时过长,阻塞了引擎的事件循环。以下是处理Tick级别数据时必须注意的性能问题及优化方案:
1. 理解 tick_data 的运行机制
根据PTrade API文档,tick_data 函数每隔3秒执行一次。这意味着您在tick_data内部编写的所有逻辑(包括数据解析、指标计算、下单判断等)必须在远小于3秒的时间内完成。如果单次执行耗时超过3秒,就会导致下一次Tick事件被延迟甚至丢弃。
2. 核心性能优化建议
A. 开启字典模式(is_dict=True)以极速获取数据
在处理逐笔委托(get_individual_entrust)和逐笔成交(get_individual_transaction)时,默认返回的是DataFrame或Panel对象,这在底层构建时非常耗时。强烈建议将入参 is_dict 设置为 True。
文档原话:当策略入参
is_dict为True时返回的数据类型为dict,返回dict类型数据的速度比DataFrame/Panel类型数据有大幅提升。
B. 避免在 tick_data 中调用耗时接口
绝对不要在tick_data中调用如 get_history、get_price、get_fundamentals 等需要大量网络IO或数据库查询的接口。这些接口的耗时极易引发阻塞。
- 正确做法:在
before_trading_start或日线/分钟线的handle_data中预先获取历史数据并计算好关键指标(如均线、支撑阻力位),将其存入全局变量g中,tick_data仅负责读取g中的阈值进行极速比对。
C. 严格控制日志(Log)输出
在Tick级别高频触发的函数中,频繁调用 log.info() 会产生大量的磁盘IO操作,严重拖慢策略运行速度。建议仅在触发交易信号、发生异常或关键状态变更时才打印日志,日常Tick跳动不要打印。
D. 结合主推事件(回调函数)
如果您对订单状态的更新速度要求极高,不要在 tick_data 中循环调用 get_orders() 去查询状态。应使用PTrade提供的主推事件:
on_order_response(context, order_list):委托主推on_trade_response(context, trade_list):成交主推
这两个函数在底层由C++直接回调,比引擎轮询更新速度更快,非常适合高频策略的订单管理。
E. 专属下单接口 order_tick
在 tick_data 中,只能使用 order_tick 进行对应的下单操作,不能使用普通的 order 或 order_target。order_tick 支持直接按盘口档位(如买一、卖二)极速报单。
3. 优化后的 Tick 策略代码示例
def initialize(context):
g.security = '600570.SS'
set_universe(g.security)
# 预先计算好的交易阈值,避免在tick中计算
g.buy_threshold = 38.19
def tick_data(context, data):
security = g.security
# 1. 极速解析Tick数据(注意:需开通Level2行情)
try:
# 获取买一价
bid_grp_str = data[security]['tick']['bid_grp'][0]
current_price = eval(bid_grp_str)[1][0]
# 2. 极速逻辑判断
if current_price > g.buy_threshold:
# 3. 使用专属接口按买一档极速下单
order_tick(security, 100, '1')
# 仅在下单时打印日志
log.info(f"触发Tick买入,价格: {current_price}")
# 更新阈值防止重复下单
g.buy_threshold = 9999.0
except Exception as e:
# 异常处理防止策略崩溃
log.error(f"Tick解析异常: {e}")
def handle_data(context, data):
# 在分钟线或日线级别处理非高频逻辑
pass
总结
解决PTrade中 tick_data 延迟的核心在于**“减负”**:将重度计算和历史数据查询转移到低频事件(如 handle_data)中,在 tick_data 中仅保留最核心的“价格比对”与“order_tick下单”逻辑,并充分利用 is_dict=True 和主推事件来压榨性能极限。