【TWS API 翻译系列】13、TWS API和IB中的历史数据
作者:yunjinqi   类别:    日期:2022-01-03 22:17:27    阅读:1594 次   消耗积分:0 分    

历史市场数据

从 API 接收历史数据与接收流式处理顶级实时数据实时市场数据具有相同的市场数据订阅要求。API历史数据功能从TWS图表或历史Time&Sales 窗口中提取某些类型的数据。因此,如果TWS图表中特定工具、数据类型或周期的数据不可用,则API也无法提供这些数据。与TWS不同,TWS可以为大多数工具创建"延迟图表",而无需任何市场数据订阅,其数据在当前时刻前10-15分钟之前;API 始终需要 Level 1流式处理实时数据来返回历史数据。

  • 通常,smart-routed历史数据请求将需要订阅工具交易的所有交易所

  • 例如,在ARCAEDGE上交易的粉红色(OTC)股票的历史数据请求除了常规订阅(例如"OTC Markets")外,还需要ARCAEDGE的"OTC Global Equities"或"Global OTC Equities and OTC Markets"。

  • 从TWS检索历史数据时,请注意历史数据限制

可用历史数据类型

查找仪器的最早日期历史数据

关于盈透证券历史数据的说明:

  • IB的历史数据针对NBBO以外的交易类型进行过滤,例如组合腿,大宗交易和衍生品交易。因此,来自(未过滤的)实时数据功能的每日交易量通常大于历史数据功能报告的(过滤的)历史交易量。此外,预计在其他领域(例如实时和历史数据馈送之间的 VWAP)也会存在差异。

历史数据限制

从API 同时请求的历史数据的最大数量为 50。在实践中,一次同时请求数量要少得多,可能会更有效率。

K线请求时间过快(30 秒一次或更短)

虽然盈透证券为我们的客户提供高质量的市场数据,但IB并不是一家专业的市场数据提供商,因此它被迫实施限制以限制与交易没有直接关系的流量。每当未遵守以下一项或多项限制时,就会发生Pacing Violation(频率冲突):

  • 在 15 秒内发出相同的历史数据请求。

  • 在两秒钟内为相同的合约,交易所和价格变动类型发出六个或更多历史数据请求。

  • 在任何十分钟内发出超过 60 个请求。

请注意,请求BID_ASK历史数据时,每个请求将计数两次。简而言之,上面的信息可以简单地表示为"不要太快地请求太多数据"。

**重要提示:**上述限制适用于我们所有的客户,并且无法克服它们。如果我们的市场数据服务无法满足您的交易策略的市场数据要求,请考虑联系专业提供商。

步长

步长定义为历史数据请求的持续时间与其粒度(即柱形大小)之间的比率。历史数据请求需要以这样的方式进行组合,即一次只返回几千根柱。下表举例说明了这一概念:

期间允许的K线的大小
60 秒1 秒 - 1 分钟
120 秒1 秒 - 2 分钟
1800 S (30 分钟)1 秒 - 30 分钟
3600 秒(1 小时)5 秒 - 1 小时
14400小号(4小时)10 秒 - 3 小时
28800 S (8 小时)30 秒 - 8 小时
1 D1分钟 - 1天
2 D2分钟 - 1天
1 W3分钟 - 1周
1 M30分钟 - 1个月
1 Y1 天 - 1 个月

不可用的历史数据

  • 加权移动平均线或布林带等研究和指标无法从 API 获得。VWAP 可用。

列出的其他历史数据限制是所有交易平台的一般限制:

  • 大于6 个月时大小为 30 秒或更短的条形图

  • 超过两年的过期期货数据,从期货的到期日期算起。

  • 到期期权、FOP、认股权证和结构性产品。

  • 期权、FOP、认股权证和结构性产品的日终(EOD)数据。

  • 过期期货点差数据

  • 不再交易的证券的数据。

  • 组合的本机历史数据。历史数据不会单独存储在IB数据库中进行组合;TWS或API中的组合历史数据是来自腿部的数据的总和。

  • 转移到新交易所的证券的历史数据在转移之前通常不可用。

注意:

1. 目前,barSize = "1 分钟"或更长时间的历史数据限制已解除。但是,在请求大量历史数据或过于频繁地发送历史数据请求时,请谨慎操作。尽管 IB 已经解除了"硬"限制,但我们仍然实现了"软"慢速客户端请求与服务器响应之间的负载平衡。请求过多的历史数据可能会导致 API 客户端受到限制并最终断开连接。如果请求需要几分钟才能返回数据,则最好使用IBApi.EClient.cancelHistoricalData函数取消请求。

历史柱线数据

请求历史K线数据

历史数据通过IBApi.EClient.reqHistoricalData函数从 TWS 获取。每个请求都需要:

  • tickerId,一个唯一的标识符,用于识别传入的数据。

  • contract,您感兴趣的IBApi.contract

  • endDateTime,请求的结束日期和时间(空字符串表示当前时刻)。

  • DurationString,从请求的给定结束日期和时间返回的时间量(或有效持续时间字符串单位)。

  • barSizeSetting,数据的粒度或有效条形大小

  • ***whatToShow,***要检索的数据类型。查看历史数据类型

  • ***useRTH,***无论(1)与否(0)检索仅在常规交易时间(RTH)内生成的数据

  • formatDate,获取K线的日期应以该格式显示。请注意,对于日间柱,只有 yyyyMMdd 格式可用。

  • keepUpToDate,是否进行订阅以返回可用时未完成的实时柱的更新(True),还是一次性返回所有数据(False)。从 API v973.03+ 和 TWS v965+ 开始提供。如果为 True和 endDateTime,则无法指定。

例如,发出结束日期和时间为"20160127 23:59:59"、持续时间字符串为"3 D"且K线大小为"1 小时"的请求将返回三天值为 1 小时的柱数据,其中最近的柱线将最接近20160127 23:59:59。

queryTime = (datetime.datetime.today() - datetime.timedelta(days=180)).strftime("%Y%m%d %H:%M:%S")
self.reqHistoricalData(4102, ContractSamples.EurGbpFx(), queryTime,
                                "1 M", "1 day", "MIDPOINT", 1, 1, False, [])
self.reqHistoricalData(4103, ContractSamples.EuropeanStock(), queryTime,
                               "10 D", "1 min", "TRADES", 1, 1, False, [])
self.reqHistoricalData(4104, ContractSamples.EurGbpFx(), "",
                                "1 M", "1 day", "MIDPOINT", 1, 1, True, [])

日K线大小有几个独特的特征。这在TWS和API中都是如此:

  • 对于期货,日K线的收盘价可以是交易所提供的结算价。一般来说,官方结算价格在交易时段结束后几个小时才可用。周五结算价有时要到周六才能提供。

  • 日K线将指可能跨越日历日的交易时段。在这种情况下,K线的日期将对应于K线关闭的日期。

接收历史柱数据

历史数据将通过 IBApi::EWrapper::historicalData方法以K线的形式提供。返回的K线的时区是在登录屏幕上的TWS中选择的时区。如果 reqHistoricalData 是用***keepUpToDate = false*调用的,一旦收到所有蜡烛图,IBApi.EWrapper.historicalDataEnd 标记将被发送。 否则,最近部分五秒柱的更新将继续实时返回到 IBApi.EWrapper.historicalDataEnd 。keepUpToDate 功能只能用于条形图大小为 5 秒或更大,并且要求 endDate 设置为空字符串。此外,如果keepUpToDate = true,如果发生 bust 事件,则会向连接到 TWS 版本 981+ 的所有 API 客户端版本报告 bust 事件错误 (code=10225)。

  • 注意:IB的历史数据馈送针对某些类型的交易进行了过滤,这些交易通常发生在NBBO之外,例如组合,大宗交易和衍生品。因此,历史数据量将低于未经过滤的历史数据馈送。

  • IB不为组合保留单独的历史数据。为组合合约返回的历史数据将是来自各个分支的数据总和。

class TestWrapper(wrapper.EWrapper):#...
     def historicalData(self, reqId:int, bar: BarData):
         print("HistoricalData. ReqId:", reqId, "BarData.", bar)#...
     def historicalDataEnd(self, reqId: int, start: str, end: str):
         super().historicalDataEnd(reqId, start, end)
         print("HistoricalDataEnd. ReqId:", reqId, "from", start, "to", end)

     def historicalDataUpdate(self, reqId: int, bar: BarData):
         print("HistoricalDataUpdate. ReqId:", reqId, "BarData.", bar)

有效的持续时间的字符串单位

单位描述
S
D
W
M
Y

有效K线周期

大小






1 秒5 秒10 秒15 秒30 秒


1 分钟2 分钟3 分钟5 分钟10 分钟15 分钟20 分钟30 分钟
1 小时2 小时3 小时4 小时8 小时


1 天






1 周






1 个月






历史数据类型

(什么显示)

所有不同类型的历史数据都以蜡烛图的形式返回,因此返回值表示蜡烛图所覆盖期间的市场状态。

TypeOpenHighLowCloseVolume
TRADESFirst traded priceHighest traded priceLowest traded priceLast traded priceTotal traded volume
MIDPOINTStarting midpoint priceHighest midpoint priceLowest midpoint priceLast midpoint priceN/A
BIDStarting bid priceHighest bid priceLowest bid priceLast bid priceN/A
ASKStarting ask priceHighest ask priceLowest ask priceLast ask priceN/A
BID_ASKTime average bidMax AskMin BidTime average askN/A
ADJUSTED_LASTDividend-adjusted first traded priceDividend-adjusted high tradeDividend-adjusted low tradeDividend-adjusted last tradeTotal traded volume
HISTORICAL_VOLATILITYStarting volatilityHighest volatilityLowest volatilityLast volatilityN/A
OPTION_IMPLIED_VOLATILITYStarting implied volatilityHighest implied volatilityLowest implied volatilityLast implied volatilityN/A
REBATE_RATEStarting rebate rateHighest rebate rateLowest rebate rateLast rebate rateN/A
FEE_RATEStarting fee rateHighest fee rateLowest fee rateLast fee rateN/A
YIELD_BIDStarting bid yieldHighest bid yieldLowest bid yieldLast bid yieldN/A
YIELD_ASKStarting ask yieldHighest ask yieldLowest ask yieldLast ask yieldN/A
YIELD_BID_ASKTime average bid yieldHighest ask yieldLowest bid yieldTime average ask yieldN/A
YIELD_LASTStarting last yieldHighest last yieldLowest last yieldLast last yieldN/A
  • 交易数据根据分割进行调整,但不包括股息

  • ADJUSTED_LAST数据根据拆分和股息进行调整。需要 TWS 967+。

每个产品的可用数据

Product TypeTRADESMIDPOINTBIDASKBID_ASKHISTORICAL_VOLATILITYOPTION_IMPLIED_VOLATILITYYIELD_BIDYIELD_ASKYIELD_BID_ASKYIELD_LAST
StocksYYYYYYYNNNN
CommoditiesNYYYYNNNNNN
OptionsYYYYYNNNNNN
FuturesYYYYYNNNNNN
FOPsYYYYYNNNNNN
ETFsYYYYYYYNNNN
WarrantsYYYYYNNNNNN
Structured ProductsYYYYYNNNNNN
SSFsYYYYYNNNNNN
ForexNYYYYNNNNNN
MetalsYYYYYNNNNNN
IndicesYNNNNYYNNNN
Bonds*YYYYYNNYYYY
FundsNYYYYNNNNNN
CFDs*NYYYYNNNNNN
CryptocurrencyYYYYYNNNNNN

-收益率历史数据仅仅适用于公司债券

直方图

直方图数据需要 API v973.02+ 和 TWS 964+。直方图不像函数 IBApi::EClient::reqHistoricalData那样将返回的数据点作为时间的函数,而是将数据作为价格水平的函数返回,函数IBApi::EClient::reqHistogramData

def histogramData(self, reqId:int, items:HistogramDataList):
    print("HistogramData. ReqId:", reqId, "HistogramDataList:", "[%s]" % "; ".join(map(str, items)))

可以使用IBApi::EClient::cancelHistogramData取消未返回数据的活动直方图请求

历史时间和销售数据

高分辨率历史数据

IB数据库中历史数据的最高粒度可以使用API函数IBApi::EClient::reqHistoricalTicks检索。这对应于TWS历史时间和销售窗口。需要 TWS 内部版本968+和 API 版本973.04+。

  • 历史逐笔报价数据不适用于组合

  • 数据不会在单个请求中从多个交易时段返回;必须使用多个请求

  • 要完成整整一秒钟,返回的价格变动可能比请求的要多

  • 注意:Python API 中的历史 Time&Sales 功能从 API v973.06+ 开始提供。

self.reqHistoricalTicks(18001, ContractSamples.USStockAtSmart(),
                                 "20170712 21:39:33", "", 10, "TRADES", 1, True, [])self.reqHistoricalTicks(18002, ContractSamples.USStockAtSmart(),
                                "20170712 21:39:33", "", 10, "BID_ASK", 1, True, [])self.reqHistoricalTicks(18003, ContractSamples.USStockAtSmart(),
                                 "20170712 21:39:33", "", 10, "MIDPOINT", 1, True, [])
  • requestId, 请求的 ID

  • contract, 作为查询主体的合约。

  • startDateTime, i.e. “20170701 12:01:00”. 使用登录时指定的 TWS 时区。

  • endDateTime, i.e. “20170701 13:01:00”. TWS 时区. 必须定义 startDateTime 或 endDateTime 中的一个。

  • numberOfTicks,不同数据点的数量。每个请求的最大值为 1000。

  • whatToShow, (Bid_Ask, Midpoint, or Trades) 请求的数据类型。

  • useRth, 来自常规交易时间(1)或所有可用时间(0)的数据。

  • ignoreSize, 省略仅反映大小变化而不反映价格变化的更新。适用于Bid_Ask数据请求。

  • miscOptions 应定义为;保留供内部使用。

数据将返回到函数IBApi.EWrapper.historicalTicks (for whatToShow=MIDPOINT)、IBApi.EWrapper.historicalTicksBidAsk (for whatToShow=BID_ASK) 和IBApi.EWrapper.historicalTicksLast for (for whatToShow=TRADES),具体取决于请求的数据类型。

def historicalTicks(self, reqId: int, ticks: ListOfHistoricalTick, done: bool):
    for tick in ticks:
        print("HistoricalTick. ReqId:", reqId, tick)# ...def historicalTicksBidAsk(self, reqId: int, ticks: ListOfHistoricalTickBidAsk,
                               done: bool):
    for tick in ticks:
        print("HistoricalTickBidAsk. ReqId:", reqId, tick)# ...def historicalTicksLast(self, reqId: int, ticks: ListOfHistoricalTickLast,
                            done: bool):
    for tick in ticks:
        print("HistoricalTickLast. ReqId:", reqId, tick)

最早可用的数据

要查找给定品种和数据类型的最早可用数据点,函数位于从TWS/IBG的v973.02和v963开始的API中,IBApi::EClient::reqHeadTimestamp

self.reqHeadTimeStamp(4101, ContractSamples.USStockAtSmart(), "TRADES", 0, 1)

生成的head时间戳将返回到函数IBApi.EWrapper.head时间戳

class TestWrapper(wrapper.EWrapper):# ...
    def headTimestamp(self, reqId:int, headTimestamp:str):
        print("HeadTimestamp. ReqId:", reqId, "HeadTimeStamp:", headTimestamp)

可以使用IBApi.EClient.cancelHeadTimeStamp请求取消

self.cancelHeadTimeStamp(4101)


TWS API相关的教程

【TWS API使用教程1】—如何在自己创建的client和TWS之间创建一个连接,并请求当前的时间
【TWS API使用教程2】—如何使用 TWS API在ubuntu和windows上分别设置contract、获取contract详细信息、设置order、下单、获取持仓信息、获取账户信息
【TWS API使用教程3】—如何使用TWS API从盈透证券中设置contract及获取contract的信息?
【TWS API使用教程4】—如何使用TWS API在盈透证券中设置order?
【TWS API使用教程5】—如何使用TWS API在盈透证券中下单(place order)、获取订单信息、获取持仓、获取账户汇总信息?
【TWS API使用教程6】—如何使用TWS API在盈透证券中获取数据?
【TWS API 使用教程7】如何使用TWS API 从盈透证券中筛选满足一定条件的contract?
【TWS API 使用教程8】一个基于TWS API的简单的程序化策略


版权所有,转载本站文章请注明出处:云子量化, http://www.woniunote.com/article/79
上一篇:【TWS API 翻译系列】12、TWS API和IB中的订单管理
下一篇:【TWS API 翻译系列】14、TWS API和IB中的账户和投资组合数据