跳转到内容

实时成交量

RTVolume 是实时成交量相关字段,需要在 genericTickList 中请求 233。它常通过 tickString() 返回,返回值通常是用分号分隔的字符串。

官方说明中,RTVolume 对应 TWS 的 Time & Sales 窗口,但它不是逐笔接口的完整替代。需要更细粒度逐笔成交时,应使用 reqTickByTickData()

官方参考:Available Tick Types

app.reqMktData(
97802,
aapl_stock(),
"233",
False,
False,
[],
)
def tickString(self, reqId, tickType, value):
if reqId == 97802:
data = parse_rt_volume(value)
print("RTVolume", data)

开发时应先记录原始字符串,再解析字段。不要在没确认格式前直接取固定下标用于交易。

genericTickList233,回调中常见 tickType48。因此解析时不要把 233 当作回调字段编号。

官方示例形态如下:

701.28;1;1348075471534;67854;701.46918464;true

常见分段含义:

位置中文含义
1最近成交价格。
2最近成交数量。
3最近成交时间,Unix 毫秒时间戳。
4当日累计成交量。
5VWAP,成交量加权价格。
6是否单一做市商成交标记。
def parse_rt_volume(value: str) -> dict[str, str]:
"""解析 RTVolume 原始字符串。字段为空时保留空字符串,便于排查。"""
last_price, last_size, last_time_ms, total_volume, vwap, single_mm = (
value.split(";") + ["", "", "", "", "", ""]
)[:6]
return {
"last_price": last_price,
"last_size": last_size,
"last_time_ms": last_time_ms,
"total_volume": total_volume,
"vwap": vwap,
"single_market_maker": single_mm,
}

不同市场、权限和版本下,字段可用性可能不同。最稳妥的做法是日志中同时保存:

  • reqId
  • tickType
  • 原始 value
  • 合约信息
  • 接收时间

AAPL 233 请求到达 TWS,但没有返回字符串字段:

TICK_REQ_PARAMS=reqId=97802;name=rt_volume_233;minTick=0.01;bboExchange=EMPTY;snapshotPermissions=0
STRING_ROWS=0
ERROR=reqId=97802;name=rt_volume_233;code=10089;msg=请求的市场数据对于API来说需要额外订阅
ERROR=reqId=97802;name=rt_volume_233;code=300;msg=无法使用tickerId找到EId::97802

这说明账户缺少对应 API 行情订阅。没有权限时,RTVolume 不会因为写了 233 就自动返回。

RTVolume 适合行情展示和成交量监控,但不要把它当作逐笔成交的完整替代。如果需要逐笔成交明细,应使用逐笔数据接口。