问题描述
解决方案
根据 PTrade API 文档的说明,get_snapshot 返回的 total_bid_turnover(委买金额)为 0 通常是由于数据推送机制的限制或调用时机导致的。
以下是具体原因分析及解决方案:
1. 数据推送机制限制(最主要原因)
根据 API 文档中 get_snapshot 接口的字段备注说明:
“total_bid_turnover/total_offer_turnover,委买金额/委卖金额主推数据(tick数据中)不支持(值为0),仅在线请求中支持。”
解释:
在 PTrade 的策略运行环境中,行情数据通常是通过“主推(Push)”模式更新的(即 Tick 数据推送)。在这种模式下,柜台或行情源为了减少数据包大小和延迟,往往不包含经过计算的“委买金额”和“委卖金额”字段,因此系统将其默认填充为 0。
2. 调用时机问题
文档中还提到关于盘前阶段的注意事项:
“在盘前阶段(before_trading_start)使用该函数 get_snapshot,返回数据里大部分数据是0,比如成交量,当前价格,换手率等。”
解释:
如果您是在 before_trading_start 函数中调用 get_snapshot,由于此时集合竞价尚未完成或刚开始,快照数据可能尚未生成完整的统计字段,导致返回 0。
解决方案:手动计算委买金额
既然直接获取的字段为 0,您可以通过快照中的**买盘档位信息(bid_grp)**自行计算委买金额。
bid_grp 包含了买一到买十(或买五)的价格和挂单量,公式为:
$$ \text{委买金额} = \sum (\text{档位价格} \times \text{档位委托数量}) $$
代码实现示例
以下代码展示了如何通过遍历 bid_grp 来手动计算委买总金额:
def handle_data(context, data):
# 假设我们要获取 600570.SS 的快照
security = '600570.SS'
snapshot = get_snapshot(security)
if snapshot and security in snapshot:
tick_info = snapshot[security]
# 获取直接返回的委买金额(通常为0)
api_bid_turnover = tick_info.get('total_bid_turnover', 0)
log.info("API返回的委买金额: %s" % api_bid_turnover)
# --- 手动计算委买金额 ---
calc_bid_turnover = 0.0
bid_grp = tick_info.get('bid_grp', {})
# 遍历买盘档位 (通常 L2 行情有 10 档,L1 有 5 档)
# bid_grp 的结构是 {档位(int): [价格(float), 数量(int), 笔数(int), ...]}
for level in bid_grp:
try:
price = bid_grp[level][0] # 价格
volume = bid_grp[level][1] # 数量
# 过滤掉价格或数量为0的无效档位
if price > 0 and volume > 0:
calc_bid_turnover += price * volume
except Exception as e:
continue
log.info("手动计算的委买金额: %.2f" % calc_bid_turnover)
总结
- 现象正常:
total_bid_turnover为 0 是符合 PTrade 文档描述的预期行为(Tick 推送不支持)。 - 替代方案:请使用
bid_grp中的价格和数量进行累加计算来获取该指标。
Q&A
Q: 为什么我在 PTrade 客户端界面上能看到委买金额,但 API 里取不到?
A: 客户端界面可能使用的是“在线请求”模式或者客户端本地进行了计算,而策略引擎为了保证高频交易的速度,使用的是精简后的“主推数据”包,因此该字段为空。
Q: get_snapshot 函数可以在回测中使用吗?
A: 不可以。根据文档说明,get_snapshot 仅在交易模块可用。在回测模式下调用该函数会报错或无法获取实时快照数据。回测中应使用 data[security] 对象获取当根 K 线或 Tick 的信息。
Q: 手动计算的委买金额和真实的委买金额完全一致吗?
A: 手动计算的是可见档位(如买一到买十)的总金额。如果市场上有超过第十档的挂单(L2行情外),手动计算的值会小于所有挂单的总和,但在策略分析中,前十档的委买金额通常已经具备足够的参考价值。