How can new reqMktData()
requests be queued after app.run()
has been invoked, and the message loop is spinning?
A little background, snapshot market data requests from the TWS API follow this pattern:
- Create contract object
- Call
reqMktData()
to queue request, passing in contract object, - Call
app.run()
to start the message loop - Receive market data snapshot in a callback
- Message loop spinning... but nothing new coming, because requests were for a snapshot.
...is there and accepted idiom for how new requests can be queued to a spinning message loop? How can this be accomplished? My ideas were:
a. Hack into app.run
method (in client.py
), add an expiration timer, and re-invoke app.run()
for each new request. Meh.
b. Spawn a separate thread for the purpose of queuing new requests
c. Queue new requests in the callback function (here, tickprice
)
d. Invoke app.run()
in a separate thread, and reqMktData()
new requests in the main thread.
Tyvm, Keith :^)
Minimal, Verifiable, and Complete Example
import ...
class Goose(EWrapper, EClient):
def __init__(self):
EClient.__init__(self, self)
def error(self, reqId, errorCode, errorString):
print("Error: ", reqId, " ", errorCode, " ", errorString)
@iswrapper
# ! [tickprice]
def tickPrice(self, reqId: TickerId, tickType: TickType, price: float,
attrib: TickAttrib):
super().tickPrice(reqId, tickType, price, attrib)
print(f"~~> {reqId}, {tickType}, {price}")
def main():
app = Goose()
app.connect("127.0.0.1", 7496, 0)
print("serverVersion:%s connectionTime:%s" % (app.serverVersion(), app.twsConnectionTime()))
a = Contract()
a.symbol = "AAPL"
a.secType = "STK"
a.exchange = "SMART"
a.currency = "USD"
a.primaryExchange = "NASDAQ"
# Queue request. Note "True" setting for MD snapshot (not streaming)
app.reqMktData(1000, a, "", True, False, [])
# Enter event loop
app.run()
# Sleep 3 seconds, then make a request for MSFT data.
# NEVER EXECUTES - Main thread with app.run() event loop spinning.
time.sleep(3)
m = Contract()
m.symbol = "AAPL"
m.secType = "STK"
m.exchange = "SMART"
m.currency = "USD"
m.primaryExchange = "NASDAQ"
app.reqMktData(1001, m, "", True, False, [])
if __name__ == "__main__":
main()