You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Interactive Brokers TWS API创建实时K线图遇504错误求调试

调试Interactive Brokers TWS API实时K线图连接问题

我尝试用Interactive Brokers TWS API创建实时蜡烛图,但运行Python代码时收到504 Not connected错误,且返回空DataFrame。

运行代码

from ibapi.client import EClient
from ibapi.wrapper import EWrapper
from ibapi.contract import Contract
import matplotlib.pyplot as plt
import pandas as pd
import threading
import time


class IBapi(EWrapper, EClient):
    def __init__(self):
        EClient.__init__(self, self)
        self.data = [] #Initialize variable to store candle

    def historicalData(self, reqId, bar):
        print(f'Time: {bar.date} Open: {bar.open} High: {bar.high} Low: {bar.low} Close: {bar.close}')
        self.data.append([bar.date, bar.open, bar.high, bar.low, bar.close])
        
    def realtimeBar(self, reqId, bar):
        print(f'Time: {bar.date} Open: {bar.open} High: {bar.high} Low: {bar.low} Close: {bar.close}')
        self.data.append([bar.date, bar.open, bar.high, bar.low, bar.close])

def run_loop():
    app.run()

app = IBapi()
app.connect('127.0.0.1', 7497, 123)

#Start the socket in a thread
api_thread = threading.Thread(target=run_loop, daemon=True)
api_thread.start()

time.sleep(1) #Sleep interval to allow time for connection to server

#Create contract object
contract = Contract()
contract.symbol = 'AAPL'
contract.secType = 'STK'
contract.exchange = 'SMART'
contract.currency = 'USD'

#Request historical candles
app.reqHistoricalData(1, contract, '', '2 D', '1 hour', 'BID', 0, 2, False, [])
    
#Create a dataframe from the historical data 
df = pd.DataFrame(app.data,columns=["date","open","high","low","close"])

data = pd.DataFrame()
data["date"] = df["date"]
data["open"] = df["open"]
data["high"] = df["high"]
data["low"] = df["low"]
data["close"] = df["close"]

#Plot the candlestick chart 
plt.style.use('bmh')
plt.figure(figsize=(15,8))
plt.title('AAPL Stock Price')
plt.xlabel('date')
plt.ylabel('price')
plt.plot(df.index, df['open'], label='open')
plt.plot(df.index, df['high'], label='high')
plt.plot(df.index, df['low'], label='low')
plt.plot(df.index, df['close'], label='close')
plt.legend()
plt.show()

#Request Live Data Type
app.reqMarketDataType(4)
#Requesting the Live Market Data
app.reqRealTimeBars(1, contract, 1, "MIDPOINT", True, [])

#Create a dataframe from the real-time data 
df2 = pd.DataFrame(app.data,columns=["date","open","high","low","close"])

#Add the real-time data to the historical data 
if not df2.empty:
    df = df.append(df2)

print(df)

#Plot the live candlestick chart 
plt.style.use('bmh')
plt.figure(figsize=(15,8))
plt.title('AAPL Stock Price')
plt.xlabel('date')
plt.ylabel('price')
plt.plot(df.index, df['open'], label='open')
plt.plot(df.index, df['high'], label='high')
plt.plot(df.index, df['low'], label='low')
plt.plot(df.index, df['close'], label='close')
plt.legend()
plt.show()

错误信息

Reloaded modules: ibapi, ibapi.message, ibapi.enum_implem, ibapi.object_implem, ibapi.common, ibapi.utils, ibapi.contract, ibapi.softdollartier, ibapi.order, ibapi.order_state, ibapi.execution, ibapi.ticktype, ibapi.commission_report, ibapi.wrapper, ibapi.server_versions, ibapi.tag_value, ibapi.scanner, ibapi.errors, ibapi.comm, ibapi.order_condition, ibapi.orderdecoder, ibapi.decoder, ibapi.reader, ibapi.connection, ibapi.client
ERROR 1 504 Not connected
ERROR -1 504 Not connected
ERROR -1 504 Not connected
Empty DataFrame
Columns: [date, open, high, low, close]
Index: []

调试方案

1. 修正连接流程顺序

原代码先调用app.connect再启动API循环线程,正确顺序是先启动线程,再执行连接,确保API循环在连接前运行:

app = IBapi()
# 先启动API循环线程
api_thread = threading.Thread(target=run_loop, daemon=True)
api_thread.start()
# 再执行连接
app.connect('127.0.0.1', 7497, 123)

2. 替换固定sleep,等待连接确认

固定time.sleep(1)不可靠,在IBapi类中添加连接回调标记连接状态,主线程等待连接完成后再发起请求:

class IBapi(EWrapper, EClient):
    def __init__(self):
        EClient.__init__(self, self)
        self.data = []
        self.is_connected = False  # 新增连接状态标记

    def connectAck(self):
        self.is_connected = True
        print("已成功连接到TWS/IB Gateway")

# 主线程中等待连接确认
while not app.is_connected:
    time.sleep(0.1)

3. 处理异步数据接收延迟

历史数据和实时数据是异步返回的,原代码请求后立刻创建DataFrame时数据尚未接收,需监听数据接收完成的回调:

class IBapi(EWrapper, EClient):
    # ... 原有代码 ...
    def historicalDataEnd(self, reqId, start, end):
        print(f"历史数据接收完成,请求ID: {reqId}")
        self.historical_data_ready = True  # 新增标记

# 发起历史数据请求后等待接收完成
app.historical_data_ready = False
app.reqHistoricalData(1, contract, '', '2 D', '1 hour', 'BID', 0, 2, False, [])
while not app.historical_data_ready:
    time.sleep(0.1)
# 此时再创建DataFrame
df = pd.DataFrame(app.data,columns=["date","open","high","low","close"])

4. TWS/IB Gateway配置检查

  • 确认TWS/IB Gateway已启动,端口匹配(模拟环境TWS默认7497,IB Gateway默认4002;实盘TWS默认7496,IB Gateway默认4001)
  • 开启API权限:Edit > Global Configuration > API > Settings,勾选"Enable Active X and Socket Clients"
  • 取消"Read-Only API"勾选(如需实时数据权限)
  • 确认"Allow connections from localhost only"符合运行环境(本地运行则勾选)

5. 避免Request ID冲突

历史数据和实时数据请求使用了相同的Request ID=1,会导致冲突,改为不同ID:

# 历史数据用ID 1
app.reqHistoricalData(1, contract, '', '2 D', '1 hour', 'BID', 0, 2, False, [])
# 实时数据用ID 2
app.reqRealTimeBars(2, contract, 1, "MIDPOINT", True, [])

6. 实现实时数据动态更新

原代码无法持续获取实时推送的数据,使用matplotlib的FuncAnimation实现图表动态更新:

import matplotlib.animation as animation

# 初始化图表
fig, ax = plt.subplots(figsize=(15,8))
lines = []
lines.append(ax.plot(df.index, df['open'], label='open')[0])
lines.append(ax.plot(df.index, df['high'], label='high')[0])
lines.append(ax.plot(df.index, df['low'], label='low')[0])
lines.append(ax.plot(df.index, df['close'], label='close')[0])
ax.set_title('AAPL Stock Price')
ax.set_xlabel('date')
ax.set_ylabel('price')
ax.legend()

def update(frame):
    # 每次更新获取最新数据
    df_live = pd.DataFrame(app.data,columns=["date","open","high","low","close"])
    lines[0].set_data(df_live.index, df_live['open'])
    lines[1].set_data(df_live.index, df_live['high'])
    lines[2].set_data(df_live.index, df_live['low'])
    lines[3].set_data(df_live.index, df_live['close'])
    ax.relim()
    ax.autoscale_view()
    return lines

# 每1秒更新一次图表
ani = animation.FuncAnimation(fig, update, interval=1000)
plt.show()

内容的提问来源于stack exchange,提问作者Scieoner

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 15:45:07