行情类型行为
reqMarketDataType() 用来设置接下来 reqMktData() 行情请求希望使用的行情类型。它改变的是请求模式,不是账户权限。
官方参考:
开发时要分清三件事:
| 问题 | 看哪里 |
|---|---|
| 程序请求哪种行情 | reqMarketDataType(type) 的参数。 |
| TWS 实际返回哪种行情 | marketDataType(reqId, marketDataType) 回调。 |
| 有没有价格或数量 | tickPrice()、tickSize()、tickString() 等回调。 |
四种行情类型
Section titled “四种行情类型”| 类型值 | 英文名称 | 中文含义 | 典型用途 |
|---|---|---|---|
1 | Real-time | 实时行情 | 已具备对应市场数据订阅时使用。 |
2 | Frozen | 冻结行情 | 市场关闭后,请求最后记录的行情。 |
3 | Delayed | 延迟行情 | 没有实时行情订阅时,尝试请求延迟行情。 |
4 | Delayed Frozen | 延迟冻结行情 | 请求延迟行情的冻结版本。 |
如果账户有实时行情权限,TWS 可能仍然返回实时行情;如果没有实时行情权限,延迟行情是否可用还要看产品、交易所、账户类型、交易时段和 IBKR 的权限规则。
连接 TWS -> reqMarketDataType(3) -> reqMktData(reqId, contract, genericTickList, snapshot, regulatorySnapshot, mktDataOptions) -> marketDataType / tickPrice / tickSize / tickSnapshotEnd / error 回调reqMarketDataType() 本身不会返回价格。它只是设置后续行情请求的偏好;真正的数据来自 reqMktData()。
AAPL 股票合约同时请求实时、冻结、延迟、延迟冻结和延迟快照:
REQUEST_SENT=reqId=95221;name=real_time_stream;requestedMarketDataType=1;snapshot=FalseREQUEST_SENT=reqId=95222;name=frozen_snapshot;requestedMarketDataType=2;snapshot=TrueREQUEST_SENT=reqId=95223;name=delayed_stream;requestedMarketDataType=3;snapshot=FalseREQUEST_SENT=reqId=95224;name=delayed_frozen_snapshot;requestedMarketDataType=4;snapshot=TrueREQUEST_SENT=reqId=95253;name=delayed_snapshot;requestedMarketDataType=3;snapshot=TrueCONNECTED=TrueCONTRACT=AAPL STK SMART NASDAQ USDSNAPSHOT_ENDS=95224,95253MARKET_DATA_TYPE=reqId=95223;name=delayed_stream;marketDataType=3MARKET_DATA_TYPE=reqId=95224;name=delayed_frozen_snapshot;marketDataType=3MARKET_DATA_TYPE=reqId=95253;name=delayed_snapshot;marketDataType=3PRICE_ROWS=18SIZE_ROWS=10ERROR=reqId=95221;name=real_time_stream;code=10089;msg=请求的市场数据对于API来说需要额外订阅。ERROR=reqId=95224;name=delayed_frozen_snapshot;code=10167;msg=请求的市场数据没有订阅。显示延迟市场数据。这个结果可以这样理解:
| 现象 | 解释 |
|---|---|
marketDataType=3 | TWS 实际使用延迟行情。 |
marketDataType=4 | TWS 可能在延迟冻结请求中返回该类型;本机这次样本只返回了 3,所以程序不能硬编码必须出现 4。 |
tickPrice() 有数据 | 有价格字段返回。 |
tickSize() 有数据 | 有数量字段返回。 |
10089 | 对应市场数据需要额外订阅或授权。 |
10167 | TWS 提示没有实时订阅,正在显示延迟行情。 |
同一个 reqId 有时会先后收到多个 marketDataType() 回调。延迟冻结快照也可能只返回延迟类型。程序不要假设只会收到一次回调,也不要把 PRICE_ROWS、SIZE_ROWS 的数量写成固定断言。
延迟行情常见 tick 类型
Section titled “延迟行情常见 tick 类型”| tickType | 中文含义 | 回调 |
|---|---|---|
66 | 延迟买价 | tickPrice() |
67 | 延迟卖价 | tickPrice() |
68 | 延迟最新价 | tickPrice() |
69 | 延迟买量 | tickSize() |
70 | 延迟卖量 | tickSize() |
71 | 延迟最新成交量 | tickSize() |
72 | 延迟最高价 | tickPrice() |
73 | 延迟最低价 | tickPrice() |
74 | 延迟成交量 | tickSize() |
75 | 延迟收盘价 | tickPrice() |
76 | 延迟开盘价 | tickPrice(),部分场景可能不可用。 |
-1 价格或非常大的 size 值通常表示该字段在这一刻不可用,不能当成真实价格或真实数量使用。
| 结果 | 优先判断 |
|---|---|
收到 marketDataType(reqId, 1) | 该订阅使用实时行情。 |
收到 marketDataType(reqId, 2) | 该订阅使用冻结行情。 |
收到 marketDataType(reqId, 3) | 该订阅使用延迟行情。 |
收到 marketDataType(reqId, 4) | 该订阅使用延迟冻结行情。 |
收到 tickPrice() / tickSize() | 有价格或数量字段返回,再按 tickType 解析。 |
收到 10089 | 优先检查行情订阅权限。 |
收到 10167 | 没有实时订阅,但延迟行情可能正在返回。 |
收到 200 | 合约无法识别,先修 Contract。 |
收到 300 | 常见于请求失败后又取消订阅,TWS 找不到对应 tickerId。 |
完整排查要同时看合约详情、行情权限、市场状态和所有回调,不能只看 reqMarketDataType() 有没有调用。