问题描述
解决方案
在 PTrade 中,解析 Tick 数据主要是在 tick_data 函数中进行的。该函数仅在交易模块(实盘或模拟盘)中可用,且需要开通 Level-2 行情权限才能获取逐笔成交数据。
以下是具体的解析逻辑和代码示例:
解析逻辑说明
-
数据源 (
data):
tick_data(context, data)中的data是一个字典。
结构为:data['股票代码']包含tick(快照)、order(逐笔委托)、transcation(逐笔成交,注意 PTrade 文档中拼写通常为transcation而非transaction)。 -
买一价 (
bid_grp):- 位于
data[security]['tick']['bid_grp']。 - 数据通常以字符串形式存储,需要使用
eval()函数转换为字典。 - 字典结构为
{档位: [价格, 数量, 笔数]}。 - 买一价即为字典中 Key 为
1的 Value 的第0个元素。
- 位于
-
卖一量 (
offer_grp):- 位于
data[security]['tick']['offer_grp']。 - 处理方式同上。
- 卖一量即为字典中 Key 为
1的 Value 的第1个元素。
- 位于
-
最近一笔逐笔成交价 (
transcation):- 位于
data[security]['transcation']。 - 这是一个 DataFrame 对象。
- 价格字段为
hq_px,取第0个元素即为最新一笔。
- 位于
策略代码示例
def initialize(context):
# 设置关注的股票,这里以恒生电子为例
g.security = '600570.SS'
set_universe(g.security)
def tick_data(context, data):
security = g.security
# 1. 获取 Tick 快照数据
tick_info = data[security]['tick']
# ---------------------------------------------------
# 解析买一价
# bid_grp 格式示例: "{1:[42.71,200,0], 2:[...], ...}"
# 需要使用 eval 将字符串转为字典
# ---------------------------------------------------
if 'bid_grp' in tick_info and len(tick_info['bid_grp']) > 0:
# 获取买档数据字符串并转为字典
bid_grp_dict = eval(tick_info['bid_grp'][0])
# 获取买一档数据 list: [价格, 数量, 笔数]
bid_1_info = bid_grp_dict.get(1)
if bid_1_info:
buy_1_price = bid_1_info[0] # 索引0为价格
else:
buy_1_price = 0.0
else:
buy_1_price = 0.0
# ---------------------------------------------------
# 解析卖一量
# offer_grp 格式同上
# ---------------------------------------------------
if 'offer_grp' in tick_info and len(tick_info['offer_grp']) > 0:
offer_grp_dict = eval(tick_info['offer_grp'][0])
# 获取卖一档数据
offer_1_info = offer_grp_dict.get(1)
if offer_1_info:
sell_1_vol = offer_1_info[1] # 索引1为数量
else:
sell_1_vol = 0
else:
sell_1_vol = 0
# ---------------------------------------------------
# 解析最近一笔逐笔成交价格
# 注意:需开通 Level-2 行情才有此数据,否则返回 None
# PTrade 中字段名为 'transcation' (注意拼写)
# ---------------------------------------------------
transaction_df = data[security]['transcation']
last_transaction_price = 0.0
if transaction_df is not None and len(transaction_df) > 0:
# 获取最近一笔成交的价格 'hq_px'
last_transaction_price = transaction_df['hq_px'][0]
# ---------------------------------------------------
# 打印结果
# ---------------------------------------------------
log.info("股票: %s" % security)
log.info("买一价: %s" % buy_1_price)
log.info("卖一量: %s" % sell_1_vol)
log.info("最近逐笔成交价: %s" % last_transaction_price)
def handle_data(context, data):
pass
注意事项
- 运行环境:
tick_data函数仅在交易模块(实盘或仿真交易)中生效,普通的回测(日线/分钟线)不会触发此函数。 - Level-2 权限:
data[security]['transcation']中的逐笔成交数据需要券商端开通 Level-2 行情权限,否则该字段可能返回None。 - 数据类型:
bid_grp和offer_grp返回的是字符串形式的字典,必须使用eval()进行转换才能通过 Key 获取具体的档位数据。 - 字段拼写:请务必注意 PTrade API 中逐笔成交的键名为
transcation(包含拼写错误),而非标准的transaction。
Q&A
Q: 为什么在回测中 tick_data 没有打印日志?
A: tick_data 函数仅在交易模块(实盘/仿真)中运行,普通回测通常只支持 handle_data(日线/分钟线)。如果需要测试 Tick 逻辑,需使用特定的 Tick 级别回测环境(如果券商支持)或在仿真交易中测试。
Q: bid_grp 中的 [42.71, 200, 0] 分别代表什么?
A: 列表中的三个元素依次代表:[委托价格, 委托数量, 委托笔数]。
Q: 如果没有 Level-2 行情,如何获取最新价格?
A: 如果没有 L2 权限无法获取逐笔成交,可以使用 data[security]['tick']['last_px'][0] 来获取该 Tick 快照时的最新成交价。