2

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:

  1. Create contract object
  2. Call reqMktData() to queue request, passing in contract object,
  3. Call app.run() to start the message loop
  4. Receive market data snapshot in a callback
  5. 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()
kmiklas
  • 13,085
  • 22
  • 67
  • 103
  • 1
    c., or d. depending on what you have in mind. Here is an example that uses c. method with d. (threading) commented out. https://stackoverflow.com/a/54423878/2855515 – brian Apr 29 '20 at 00:13
  • I did d in combination with https://gist.github.com/wrighter/4df9177849cfe9fd4465099f5e86461e – Mat90 Nov 14 '21 at 14:09

0 Answers0