My trading app written with Python and using the IB TWS API is multithreaded and I'm looking to solve once and for all the issues of corrupt prints and duplicate order ids, both of which can happen once multiple threads are running at the same time.
For the purpose of this question I've put together a simple script that has for goal nothing other than providing a support for solving it. What I'm hoping for is to see how someone more experienced would implement queues in order to make the script do 2 things:
- print 'safely' in a non corrupt way
- each order should execute without the 'duplicate order id' error code popping up
I know that I need to use queues but I'm just starting to read up on the topic and since the IB TWS API is fairly specific, I'm not sure how to implement. Thank you.
from ibapi.wrapper import EWrapper
from ibapi.client import EClient
from ibapi.order import Order
from ibapi.contract import Contract
import threading
import time
buyOrder1Id = 0
buyOrder2Id = 0
buyOrder3Id = 0
buyOrder4Id = 0
buyOrder5Id = 0
buyOrder6Id = 0
buyOrder7Id = 0
buyOrder8Id = 0
buyOrder9Id = 0
buyOrder10Id = 0
class TradingApp(EWrapper, EClient):
def __init__(self):
self.BidPrice = 0
self.AskPrice = 0
self.LastPrice = 0
EClient.__init__(self,self)
def error(self, reqId, errorCode, errorString):
print("Error. Id: ", reqId, " Code: ", errorCode, " Msg: ", errorString)
def nextValidId(self, orderId):
super().nextValidId(orderId)
self.nextValidOrderId = orderId
def websocket_con():
app.run()
Underlying = Contract()
Underlying.localSymbol = "ESU2"
Underlying.secType = "FUT"
Underlying.currency = "USD"
Underlying.exchange = "GLOBEX"
BuyOrder1 = Order()
BuyOrder1.action = "BUY"
BuyOrder1.totalQuantity = 1
BuyOrder1.orderType = "MKT"
BuyOrder1.account = "DU2312534"
BuyOrder1.tif = "GTC"
app = TradingApp()
app.connect("127.0.0.1", 7497, 2000)
time.sleep(1)
# starting a separate daemon thread to execute the websocket connection
con_thread = threading.Thread(target=websocket_con, daemon=True)
con_thread.start()
time.sleep(1)# some latency added to ensure that the connection is established
def Level1():
while True:
app.reqIds(1)
time.sleep(1)
buyOrder1Id = app.nextValidOrderId
print("buyOrder1Id: ",buyOrder1Id)
app.placeOrder(buyOrder1Id,Underlying,BuyOrder1)
time.sleep(3)
def Level2():
while True:
app.reqIds(1)
time.sleep(1)
buyOrder2Id = app.nextValidOrderId
print("buyOrder2Id: ",buyOrder2Id)
app.placeOrder(buyOrder2Id,Underlying,BuyOrder1)
time.sleep(3)
def Level3():
while True:
app.reqIds(1)
time.sleep(1)
buyOrder3Id = app.nextValidOrderId
print("buyOrder3Id: ",buyOrder3Id)
app.placeOrder(buyOrder3Id,Underlying,BuyOrder1)
time.sleep(3)
def Level4():
while True:
app.reqIds(1)
time.sleep(1)
buyOrder4Id = app.nextValidOrderId
print("buyOrder4Id: ",buyOrder4Id)
app.placeOrder(buyOrder4Id,Underlying,BuyOrder1)
time.sleep(3)
def Level5():
while True:
app.reqIds(1)
time.sleep(1)
buyOrder5Id = app.nextValidOrderId
print("buyOrder5Id: ",buyOrder5Id)
app.placeOrder(buyOrder5Id,Underlying,BuyOrder1)
time.sleep(3)
def Level6():
while True:
app.reqIds(1)
time.sleep(1)
buyOrder6Id = app.nextValidOrderId
print("buyOrder6Id: ",buyOrder6Id)
app.placeOrder(buyOrder6Id,Underlying,BuyOrder1)
time.sleep(3)
def Level7():
while True:
app.reqIds(1)
time.sleep(1)
buyOrder7Id = app.nextValidOrderId
print("buyOrder7Id: ",buyOrder7Id)
app.placeOrder(buyOrder7Id,Underlying,BuyOrder1)
time.sleep(3)
def Level8():
while True:
app.reqIds(1)
time.sleep(1)
buyOrder8Id = app.nextValidOrderId
print("buyOrder8Id: ",buyOrder8Id)
app.placeOrder(buyOrder8Id,Underlying,BuyOrder1)
time.sleep(3)
def Level9():
while True:
app.reqIds(1)
time.sleep(1)
buyOrder9Id = app.nextValidOrderId
print("buyOrder9Id: ",buyOrder9Id)
app.placeOrder(buyOrder9Id,Underlying,BuyOrder1)
time.sleep(3)
def Level10():
while True:
app.reqIds(1)
time.sleep(1)
buyOrder10Id = app.nextValidOrderId
print("buyOrder10Id: ",buyOrder10Id)
app.placeOrder(buyOrder10Id,Underlying,BuyOrder1)
time.sleep(3)
level1_thread = threading.Thread(target=Level1)
level1_thread.start()
level2_thread = threading.Thread(target=Level2)
level2_thread.start()
time.sleep(1)
level3_thread = threading.Thread(target=Level3)
level3_thread.start()
time.sleep(1)
level4_thread = threading.Thread(target=Level4)
level4_thread.start()
time.sleep(1)
level5_thread = threading.Thread(target=Level5)
level5_thread.start()
time.sleep(1)
level6_thread = threading.Thread(target=Level6)
level6_thread.start()
time.sleep(1)
level7_thread = threading.Thread(target=Level7)
level7_thread.start()
time.sleep(1)
level8_thread = threading.Thread(target=Level8)
level8_thread.start()
time.sleep(1)
level9_thread = threading.Thread(target=Level9)
level9_thread.start()
time.sleep(1)
level10_thread = threading.Thread(target=Level10)
level10_thread.start()
time.sleep(1)