跳转到内容

总览

逐笔数据用于接收更细粒度的实时成交、买卖报价或中点价。它比普通一档行情更接近 TWS 里的 Time & Sales 窗口,但仍然受到 IBKR 行情订阅、数据行数、交易时段和产品类型限制。

TWS API 使用 reqTickByTickData() 请求逐笔数据,用 cancelTickByTickData() 取消订阅。

官方参考:Tick-by-Tick Data

步骤接口 / 回调说明
1Contract()构造具体合约,例如 AAPL 股票。
2reqTickByTickData()请求 LastAllLastBidAskMidPoint
3tickByTickAllLast()接收 Last / AllLast 成交类逐笔数据。
4tickByTickBidAsk()接收逐笔买卖报价。
5tickByTickMidPoint()接收逐笔中点价。
6cancelTickByTickData()取消逐笔订阅。

reqMktData() 不同,逐笔数据不是“最新报价状态”,而是连续事件流。程序通常需要把每一笔追加保存,再由策略自己决定是否聚合成 1 秒、1 分钟或成交量 K 线。

tickType典型回调中文说明
LasttickByTickAllLast()普通成交流,适合大多数成交明细展示。
AllLasttickByTickAllLast()更完整的成交流,可能包含组合、衍生品、平均价格等 Last 不包含的成交类型。
BidAsktickByTickBidAsk()逐笔买卖报价,适合观察报价变化。
MidPointtickByTickMidPoint()买卖价中点。

tickType 区分大小写,写成 lastbidaskMIDPOINT 都不等同于官方要求的值。

限制说明
版本要求逐笔实时数据需要较新的 TWS 与 API 版本。旧环境要先升级 TWS 和 API 包。
同合约重复请求同一个合约不要在 15 秒内反复请求逐笔数据。切换 LastBidAskMidPoint 也应按同一合约限制处理。
同时订阅数量逐笔订阅数量受账户市场数据额度影响,不适合一次订阅大量合约。
期权实时逐笔期权没有实时逐笔数据;期权逐笔只能走历史逐笔接口。
指数逐笔指数逐笔只覆盖官方支持的部分指数。
组合合约组合合约不支持逐笔数据。
产品类型差异不是所有产品都支持 LastAllLastBidAskMidPoint 四种类型。外汇等产品应按实际返回和官方支持范围处理。
历史补点numberOfTicks 大于 0 时,请求开始阶段会先补一段近期逐笔,再进入实时订阅;大量回补应使用历史逐笔接口。
from ibapi.contract import Contract
def aapl_stock() -> Contract:
"""AAPL 股票合约。逐笔数据也要先写清楚合约。"""
contract = Contract()
contract.symbol = "AAPL"
contract.secType = "STK"
contract.exchange = "SMART"
contract.currency = "USD"
contract.primaryExchange = "NASDAQ"
return contract

TWS 连接正常时,逐笔请求可以发送到 TWS:

CONNECTED=True
CONTRACT=AAPL STK SMART NASDAQ USD
REQUESTS=97901:Last:ignoreSize=False,97902:BidAsk:ignoreSize=True,97903:MidPoint:ignoreSize=False,97904:AllLast:ignoreSize=False

如果账户没有 AAPL 对应的 API 实时行情权限,三类回调都不会返回数据。本机样本中四个逐笔请求都被 10089 拦截,随后取消未建立的订阅返回 300

LAST_ROWS=0
BIDASK_ROWS=0
MIDPOINT_ROWS=0
ERROR=reqId=97901;type=Last;code=10089;msg=请求的市场数据对于API来说需要额外订阅。
ERROR=reqId=97902;type=BidAsk;code=10089;msg=请求的市场数据对于API来说需要额外订阅
ERROR=reqId=97903;type=MidPoint;code=10089;msg=请求的市场数据对于API来说需要额外订阅
ERROR=reqId=97904;type=AllLast;code=10089;msg=请求的市场数据对于API来说需要额外订阅

外汇等产品还可能表现为 10189。例如 EUR.USD 的 Last / AllLast 请求可能返回:

ERROR=reqId=97901;type=Last;code=10189;msg=请求跳动点数据失败。:No historical market data for EUR/CASH@FXSUBPIP Last 0
ERROR=reqId=97904;type=AllLast;code=10189;msg=请求跳动点数据失败。:No historical market data for EUR/CASH@FXSUBPIP AllLast 0

这不是 Python 代码错误,而是行情订阅、产品支持或逐笔类型不匹配问题。模拟账户如果没有共享真实账户的市场数据,也会遇到同样错误。

使用逐笔数据前,至少确认:

  • 真实账户或模拟账户已经有对应市场实时行情订阅。
  • 模拟账户已共享真实账户市场数据权限。
  • 没有另一台 TWS / IB Gateway 占用同一行情权限。
  • 在目标市场交易时段内测试,尤其是股票逐笔成交。

如果没有权限,程序通常只会进入 error() 回调,不会收到逐笔数据。