问题描述
解决方案
在 PTrade 中实现基于 Tick 数据的高频策略,核心在于使用 tick_data 事件函数。与 handle_data(通常用于分钟或日线)不同,tick_data 专门用于处理高频快照数据(通常每 3 秒触发一次)。
以下是实现该策略的关键点和完整代码示例:
核心实现步骤
- 使用
tick_data(context, data):这是策略的主入口,系统会推送最新的 Tick 数据到data参数中。 - 解析盘口数据:
data[code]['tick']['bid_grp']:买盘档位(买一到买十)。data[code]['tick']['offer_grp']:卖盘档位(卖一到卖十)。- 数据结构通常为字典,Key 为档位(1 代表买一/卖一),Value 为列表
[价格, 数量, 笔数]。
- 使用
order_tick下单:这是专门配合 Tick 数据的下单接口,支持通过priceGear参数快速指定以“买一价”或“卖一价”下单,无需手动输入具体价格。
策略代码示例
这个示例策略会监控一只股票,当买一价低于某个值时买入,当卖一价高于某个值时卖出。
def initialize(context):
# 1. 设置要操作的标的
g.security = '600570.SS'
# 2. 设置股票池
set_universe(g.security)
# 设置一个简单的标志位,防止示例代码在回测中无限下单
g.bought = False
def tick_data(context, data):
"""
Tick级别行情推送函数,每3秒触发一次(取决于行情推送频率)
"""
symbol = g.security
# 1. 获取该标的的 tick 数据
# 注意:需确保 data 中包含该标的的数据
if symbol not in data:
return
tick = data[symbol]['tick']
# 2. 获取买一价和卖一价
# bid_grp: 买盘档位, offer_grp: 卖盘档位
# 结构: {1: [价格, 数量, 笔数], 2: [...], ...}
# 下标说明: [0]是价格, [1]是数量
# 获取买一价 (Bid Price 1)
if 1 in tick['bid_grp']:
bid_1_price = tick['bid_grp'][1][0]
bid_1_vol = tick['bid_grp'][1][1]
else:
return # 数据不完整则跳过
# 获取卖一价 (Ask/Offer Price 1)
if 1 in tick['offer_grp']:
ask_1_price = tick['offer_grp'][1][0]
ask_1_vol = tick['offer_grp'][1][1]
else:
return
# 获取最新成交价
last_price = tick['last_px']
# 打印日志方便调试 (生产环境请减少日志量)
# log.info("代码:%s, 买一:%s, 卖一:%s, 最新:%s" % (symbol, bid_1_price, ask_1_price, last_price))
# 3. 交易逻辑示例
# 示例逻辑:如果买一价低于 40.0 且尚未买入,则以卖一价(对手价)买入
if bid_1_price < 40.0 and not g.bought:
log.info("触发买入信号,当前买一价: %s" % bid_1_price)
# order_tick 下单函数
# 参数说明:
# amount: 正数买入,负数卖出
# priceGear: 价格档位。'-1'代表卖一价,'1'代表买一价。
# 这里我们想立即成交,所以买入时挂卖一价 ('-1')
order_tick(symbol, 100, priceGear='-1')
g.bought = True
# 示例逻辑:如果卖一价高于 42.0 且持有仓位,则以买一价(对手价)卖出
elif ask_1_price > 42.0 and g.bought:
# 检查持仓(可选)
position = get_position(symbol)
if position.enable_amount >= 100:
log.info("触发卖出信号,当前卖一价: %s" % ask_1_price)
# 卖出时,为了立即成交,通常挂买一价 ('1')
order_tick(symbol, -100, priceGear='1')
g.bought = False
def handle_data(context, data):
# 在Tick策略中,handle_data 可以留空,或者用于处理非Tick级别的定时任务
pass
关键参数说明
-
priceGear(盘口档位):
在order_tick函数中,priceGear是一个非常方便的参数:'1'~'5':对应 买一 到 买五。'-1'~'-5':对应 卖一 到 卖五。- 买入技巧:如果想快速成交(吃单),通常使用
priceGear='-1'(以卖一价买入)。如果想挂单排队,使用priceGear='1'(以买一价挂单)。 - 卖出技巧:如果想快速成交,通常使用
priceGear='1'(以买一价卖出)。
-
运行频率:
- PTrade 的
tick_data并不是毫秒级的,通常是 3秒 一次快照(Snapshot)。 - 如果需要处理逐笔委托(Order)或逐笔成交(Transaction)数据,需要开通 Level-2 行情权限,并在
tick_data的data参数中解析order和transcation字段。
- PTrade 的
-
回测注意事项:
- 在回测界面选择频率时,必须选择 Tick级别。
- Tick 回测数据量巨大,速度会比分钟级慢很多。
-
数据获取方式:
- 在
tick_data内部,直接使用data[security]['tick']获取数据是最快的。 - 不要在
tick_data里频繁调用get_snapshot(),因为data参数里已经包含了当前的快照信息。
- 在