跳转到内容

请求二档行情

reqMktDepth() 用来订阅某个合约的市场深度。它是持续订阅接口,请求成功后会不断通过 updateMktDepth()updateMktDepthL2() 推送盘口变化。

官方参考:Market Depth - Requesting

app.reqMktDepth(
reqId,
contract,
numRows,
isSmartDepth,
mktDepthOptions,
)
import threading
import time
from ibapi.client import EClient
from ibapi.contract import Contract
from ibapi.wrapper import EWrapper
class DepthApp(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
self.ready = threading.Event()
self.errors = []
def nextValidId(self, orderId: int):
# 收到 nextValidId 说明 API 连接已经完成握手,可以开始发送请求。
self.ready.set()
def updateMktDepth(self, reqId, position, operation, side, price, size):
# 普通二档盘口更新。真实项目里不要只 print,要维护盘口快照。
print("DEPTH", reqId, position, operation, side, price, size)
def updateMktDepthL2(self, reqId, position, marketMaker, operation, side, price, size, isSmartDepth):
# L2 盘口更新,多了 marketMaker 或交易所标识。
print("DEPTH_L2", reqId, position, marketMaker, operation, side, price, size, isSmartDepth)
def error(self, reqId, *args):
# 不同 TWS API 版本的 error 回调参数可能略有差异。
# 这里统一取出错误码和错误消息,便于排查 2152 等权限问题。
if len(args) >= 3 and isinstance(args[0], int) and args[0] > 1_000_000_000_000:
error_code = int(args[1])
error_message = str(args[2])
elif len(args) >= 2:
error_code = int(args[0])
error_message = str(args[1])
else:
error_code = -1
error_message = str(args)
self.errors.append((reqId, error_code, error_message))
print("ERROR", reqId, error_code, error_message)
def stock_contract(symbol: str) -> Contract:
"""创建美股股票合约。"""
contract = Contract()
contract.symbol = symbol
contract.secType = "STK"
contract.exchange = "SMART"
contract.currency = "USD"
return contract
app = DepthApp()
app.connect("127.0.0.1", 7497, clientId=974)
threading.Thread(target=app.run, daemon=True).start()
if not app.ready.wait(10):
raise RuntimeError("TWS API 连接超时,请检查 TWS API 设置和端口")
contract = stock_contract("AAPL")
app.reqMktDepth(
97401, # reqId:请求编号
contract, # contract:合约对象
5, # numRows:请求盘口档位数量
True, # isSmartDepth:是否请求 SMART 深度
[], # mktDepthOptions:普通请求传空列表
)
time.sleep(8)
app.cancelMktDepth(97401, True)
app.disconnect()
参数中文解释注意事项
reqId请求编号回调和取消都用它关联
contract合约对象必须能被 TWS 唯一识别;股票建议先用合约详情确认 conId 和交易所
numRows盘口档位数量请求的档位数;如果市场深度小于该值,TWS 只会返回可用档位
isSmartDepth是否使用 SMART 深度True 请求 SMART 聚合深度;False 请求合约交易所对应深度
mktDepthOptions额外选项普通请求传空列表

reqId 必须在同一个 API 客户端连接里保持唯一。后续的 updateMktDepth()updateMktDepthL2()cancelMktDepth() 都靠这个编号关联同一次订阅。

contract 建议不要只写 symbol。如果交易所或证券类型可能有歧义,先用 reqContractDetails() 查清楚,再请求二档行情。

numRows 不是“保证返回这么多档”,而是“最多请求这么多档”。实际返回数量取决于交易所、产品、行情权限和当时盘口。

isSmartDepth=True 适合美股 SMART 聚合深度;False 更接近指定交易所深度。如果收到权限错误,可以结合 reqMktDepthExchanges() 返回的 exchangesecTypeserviceDataType 判断该订阅是否支持。

mktDepthOptionsTagValue 列表,普通 Python 示例传 []。如果官方针对某些交易所提供特殊选项,再按对应说明填写。

请求 AAPL SMART 深度行情的参考结果:

CONNECTED=True
DEPTH_ROWS=0
DEPTH_L2_ROWS=0
CANCEL_SENT=True
ERROR=reqId=97401;code=2152;msg=交易所 - 顶端: IBEOS; OVERNIGHT; 需要其它市场数据许可 - 深度: NASDAQ; BATS; ARCA; BEX; NYSE; IEX; ...

错误信息列出了多个顶端行情和深度行情交易所,说明这不是 Python 代码格式错误,而是账户缺少相关市场数据许可。

先用 reqMktDepthExchanges() 看交易所能力,再用 reqContractDetails() 确认合约,最后再订阅二档行情。收到 2152 时,优先处理行情权限,而不是修改 clientId、端口或重装 API。