1

我正在尝试打印 SPY 的开盘价(因此刻度为 14),类似于以美元打印账户余额。在添加尝试打印 SPY 价格的代码之前打印帐户余额有效。但是,我现在收到“ERROR 508 322 Error processing request.-'bW':cause - Duplicate ticker id”。我不明白为什么,因为我的代码中似乎没有重复的股票代码 ID,并且我已经重新启动了 TWS 和 PyCharm。

from ibapi.client import EClient  # handles outgoing requests
from ibapi.wrapper import EWrapper  # handles incoming messages
from ibapi.contract import Contract
import threading
import time

class IBapi(EWrapper, EClient):
    def __init__(self):
        EClient.__init__(self, self)
        self.contract_details = {}
        self.bardata = {}  # initialise directory to store bar data
        self.USD_cash_balance = 0
        self.spyprice = 0

    def tickPrice(self, reqId, tickType, price, attrib):  # this function prints the price
        if tickType == 2 and reqId == 1:  # tickType 2 is ask price: lowest price offer on the contract
            print(price)
        if tickType == 14 and reqId == 508:
            self.spyprice = price

    def nextValidId(self, orderId: int):
        super().nextValidId(orderId)
        self.nextorderId = orderId
        print('The next valid order id is: ', self.nextorderId)

    def accountSummary(self, reqId: int, account: str, tag: str, value: str,
                       currency: str):
        if tag == "CashBalance" and reqId == 131:
            self.USD_cash_balance = value

def run_loop():
    app.run()  # starts communication with TWS


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

# Start the socket in a thread
api_thread = threading.Thread(target=run_loop, daemon=True)  # Algo doesn't have "daemon=True"
api_thread.start()

# Check if the API is connected via orderid
while True:
    if isinstance(app.nextorderId,
                  int):  # the IB API sends out the next available order ID as soon as connection is made
        # The isinstance() function returns True if the specified object is of the specified type, otherwise False.
        print('connected')
        break
    else:
        print('waiting for connection')
        time.sleep(2)

# getting strike prices
spystock_contract = Contract()
spystock_contract.symbol = "SPY"
spystock_contract.secType = "STK"
spystock_contract.exchange = "SMART"
spystock_contract.currency = "USD"

while not getattr(app, 'spyprice', None):
    app.reqMktData(508, spystock_contract, "", False, False, [])
    time.sleep(0.5)

print("The opening price of SPY is $" + str(app.spyprice))

while not getattr(app, 'USD_cash_balance', None):
    app.reqAccountSummary(131, "All", "$LEDGER:USD")
    time.sleep(0.5)

print("My account balance in USD is: " + str(app.USD_cash_balance))

time.sleep(3)
print("Disconnecting.")
app.disconnect()
4

1 回答 1

1

您只能调用app.reqMktData(508, spystock_contract, "", False, False, [])一次,而不是每 0.5 秒调用一次。将其放入nextVaildId方法中,使其仅被调用一次,并在连接后调用。

不需要睡眠,只需以异步方式执行操作,就像 API 打算使用的那样。一种方法是在 API 调用 nextValidId 之后执行操作。

def nextValidId(self, orderId: int):
    super().nextValidId(orderId)
    self.nextorderId = orderId
    print('The next valid order id is: ', self.nextorderId)
    spystock_contract = Contract()
    spystock_contract.symbol = "SPY"
    spystock_contract.secType = "STK"
    spystock_contract.exchange = "SMART"
    spystock_contract.currency = "USD"
    app.reqMktData(508, spystock_contract, "", False, False, [])
于 2021-12-06T19:05:09.103 回答