行情需要额外订阅
当 TWS API 返回“请求的市场数据对于 API 来说需要额外订阅”时,通常说明合约可以识别,但账户没有这类 API 行情权限。
模拟账户请求 AAPL 顶层行情时返回:
ERROR=reqId=99102;code=10089;msg=请求的市场数据对于API来说需要额外订阅。点击“市场数据连接”对话框中的链接获取更多详情。:AAPL NASDAQ.NMS/TOP/ALL这个错误和合约定义错误不同。合约定义错误通常是 200,说明 TWS 找不到证券定义;10089 更偏向权限或行情订阅问题。
from ibapi.contract import Contract
def aapl_contract(): contract = Contract() contract.symbol = "AAPL" contract.secType = "STK" contract.exchange = "SMART" contract.currency = "USD" contract.primaryExchange = "NASDAQ" return contract
app.reqMarketDataType(1) # 请求实时行情类型app.reqMktData(99102, aapl_contract(), "", False, False, [])如果账户没有对应 API 行情权限,就可能收到 10089。这时不是 Python 代码写错,也不是 TWS 没连上。
同一类行情权限问题也可能出现相关代码:
| 代码 | 常见含义 | 处理方式 |
|---|---|---|
10089 | API 行情需要额外订阅,消息里可能提示延迟行情可用 | 检查行情订阅,或显式请求延迟行情。 |
10167 | 实时行情不可用,当前显示延迟市场数据 | 标记数据为延迟,不要当作实时行情。 |
10168 | 行情未订阅,延迟市场数据未启用 | 尝试 reqMarketDataType(3),或检查是否有可用延迟行情权限。 |
| 步骤 | 目的 |
|---|---|
先用 reqContractDetails() 验证合约 | 确认不是合约字段错误。 |
查看错误码是否为 10089 | 判断是否为行情订阅问题。 |
| 查看 TWS 中该标的是否显示实时或延迟行情 | 对照账户实际权限。 |
| 尝试延迟行情类型 | 用于判断是否能获取延迟数据。 |
| 检查 IBKR 行情订阅 | API 行情可能需要对应市场数据权限。 |
取消订阅时的连带错误
Section titled “取消订阅时的连带错误”样本中,行情订阅因权限错误没有成功建立,随后调用 cancelMktData(99102) 又返回:
ERROR=reqId=99102;code=300;msg=无法使用tickerId找到EId::99102这表示 TWS 找不到这个有效行情订阅。它不是新的合约问题,而是前一个订阅失败后的连带结果。
代码处理建议
Section titled “代码处理建议”active_market_data_req_ids = set()
def start_market_data(app, req_id, contract): app.reqMktData(req_id, contract, "", False, False, []) active_market_data_req_ids.add(req_id)
def stop_market_data(app, req_id): if req_id in active_market_data_req_ids: app.cancelMktData(req_id) active_market_data_req_ids.remove(req_id)正式系统里还应根据 error() 回调把失败订阅从活跃集合中移除,避免重复取消无效 reqId。