小周期 K 线限频违规
小周期历史 K 线最容易触发限频。30 秒及以下的 bar 请求不要高频循环发送,否则 TWS 可能返回 pacing violation,并影响接下来一段时间的历史数据请求。
官方参考:Historical Data Limitations
常见限频规则
Section titled “常见限频规则”| 规则 | 中文解释 |
|---|---|
| 15 秒内不要发送完全相同的历史数据请求 | 相同合约、周期、时长和数据类型重复请求会被限制。 |
| 2 秒内不要对同一合约、交易所和 tick 类型发送 6 次或更多请求 | 高频批量请求会触发限制。 |
| 10 分钟内不要超过 60 次历史数据请求 | 批量回补时必须排队。 |
BID_ASK 请求按两次计数 | 买卖价历史数据消耗更快。 |
这些限制不能靠换 clientId 或多开脚本绕过。正确做法是排队、缓存和增量更新。
import time
def request_with_pacing(app, requests): for req in requests: app.reqHistoricalData(*req)
# 示例只演示基本间隔;批量程序还要统计 10 分钟窗口。 time.sleep(10)正式程序应做请求队列,记录过去 10 分钟请求数量,并避免重复请求同一个窗口。
适合缓存的 key
Section titled “适合缓存的 key”cache_key = ( contract.conId, endDateTime, durationStr, barSizeSetting, whatToShow, useRTH, formatDate,)如果同一个 cache_key 在 15 秒内已经请求过,应该使用缓存或等待,而不是再发一次。
请求队列字段
Section titled “请求队列字段”| 字段 | 用途 |
|---|---|
created_at | 记录请求加入队列时间。 |
sent_at | 记录实际发送时间。 |
contract_key | 合约唯一标识,优先使用 conId。 |
barSizeSetting | 判断是否属于小周期请求。 |
whatToShow | BID_ASK 要按更高成本计算。 |
status | pending、sent、finished、failed。 |
errorCode | 记录是否触发限频、权限或参数错误。 |
| 检查项 | 说明 |
|---|---|
| 最近 15 秒是否重复同一请求 | 重复请求最容易被忽略。 |
| 2 秒内是否对同一合约发送太多请求 | 多线程下载容易触发。 |
| 10 分钟内请求数是否过高 | 批量补数必须统计窗口。 |
是否请求 BID_ASK | 这类请求消耗更快。 |
| 是否把空结果当失败无限重试 | 空结果可能是数据不可用,不要立刻重试。 |
看到 pacing violation 时,先打印最近请求队列,再判断是否需要放慢节奏、合并窗口或读取缓存。