跳转到内容

总览

市场指标不是普通股票,也不是账户统计字段。在 TWS API 中,NYSE 涨跌家数、NYSE 成交量指数、TRIN 和 TICK 这类数据通常按指数合约请求,接口仍然使用一档行情的 reqMktData()

这组页面只讲官方文档列出的 NYSE 市场指标。它们适合做市场宽度、短线情绪和盘中监控,不适合直接当作交易信号单独使用。

官方参考:Streaming Market Data

步骤接口 / 回调说明
1Contract()构造市场指标合约,secType 使用 IND
2reqMktData()请求实时一档行情。
3tickPrice() / tickSize()接收指标数值或相关数量更新。
4cancelMktData()不再需要时取消订阅。
5error()接收权限、合约、订阅状态等错误。
字段示例中文说明
symbolAD-NYSE指标代码。不同指标使用不同 symbol。
secTypeIND表示指数或指标类合约。
exchangeNYSE指标所属交易所。
currencyUSD美元计价。

本组页面使用的四个指标如下:

指标symbol用途
NYSE 涨跌家数AD-NYSE观察上涨股票数量和下跌股票数量的差异。
NYSE 成交量指数VOL-NYSE观察上涨成交量和下跌成交量的关系。
NYSE TRIN 指标TRIN-NYSE结合涨跌家数与涨跌成交量衡量市场结构强弱。
NYSE TICK 指标TICK-NYSE观察短时间内上涨跳动和下跌跳动的差异。
from ibapi.contract import Contract
def nyse_indicator(symbol: str) -> Contract:
"""构造 NYSE 市场指标合约。"""
contract = Contract()
contract.symbol = symbol
contract.secType = "IND"
contract.exchange = "NYSE"
contract.currency = "USD"
return contract
# 请求 NYSE TICK 指标。
app.reqMktData(
97504,
nyse_indicator("TICK-NYSE"),
"",
False,
False,
[],
)

reqMktData() 的参数含义和普通股票一致:

参数示例中文说明
tickerId97504本次行情请求编号,用来匹配回调。
contractnyse_indicator("TICK-NYSE")指标合约。
genericTickList""本组指标不需要额外 generic tick。
snapshotFalseFalse 表示订阅流式更新。
regulatorySnapshotFalse不请求监管快照。
mktDataOptions[]通常留空。

TWS API 可以连接,并且 TWS 能识别这四个指标合约,但账户没有对应市场数据订阅时,不会返回价格或数量回调:

CONNECTED=True
REQUESTED=97501:AD-NYSE,97502:VOL-NYSE,97503:TRIN-NYSE,97504:TICK-NYSE
PRICE_ROWS=0
SIZE_ROWS=0
CANCELLED=97501,97502,97503,97504

TWS 返回的主要错误是 354

ERROR=reqId=97501;symbol=AD-NYSE;code=354;msg=未订阅所请求的市场数据...:AD-NYSE NYSE ADVANCE DECLINE INDEX/TOP/ALL
ERROR=reqId=97502;symbol=VOL-NYSE;code=354;msg=未订阅所请求的市场数据...:VOL-NYSE NYSE VOLUME INDEX/TOP/ALL
ERROR=reqId=97503;symbol=TRIN-NYSE;code=354;msg=未订阅所请求的市场数据...:TRIN-NYSE NYSE TRIN (OR ARMS) INDEX/TOP/ALL
ERROR=reqId=97504;symbol=TICK-NYSE;code=354;msg=未订阅所请求的市场数据...:TICK-NYSE NYSE TICK INDEX/TOP/ALL

这说明代码路径和合约写法已经到达 TWS,但行情权限不足。开发时应把 354 当作权限或订阅问题处理,而不是把它误判成 Socket 连接失败。

如果前面的订阅已经被 354 拒绝,后续调用 cancelMktData() 时还可能出现 300。它通常只是取消未建立订阅时的附带结果,不是根因。

现象常见原因处理方式
收到 354未订阅对应市场数据检查账户市场数据订阅和 API 行情权限。
收到 200合约字段写错或运行环境找不到证券定义先检查 symbol/secType/exchange/currency
没有回调也没有错误等待时间太短或程序没有启动消息线程确认 app.run() 在线程中运行,并等待 nextValidId()
取消后收到 300订阅没有真正建立常见于前面已经因为权限错误被拒绝的请求。

市场指标页面的重点不是下单,而是把指标读出来并用于风控、过滤或盘中状态展示。新手可以先用 reqCurrentTime() 确认连接,再用普通股票的一档行情确认 reqMktData() 回调模型,最后再接入这些 NYSE 指标。