class TraderPro(wrapper.EWrapper, client.EClient): """ @Description: Program designed as part of the requirement for MSF 597 at the Stuart School of Business. @Term: Spring 2020 @Student: Ariwoola Abdulroqeeb """ #tick_price_changed = QtCore.pyqtSignal(str) def __init__(self, window=None): wrapper.EWrapper.__init__(self) client.EClient.__init__(self, wrapper=self) #QtWidgets.QThread.__init__(self, None) self.reqMarketDataType( wrapper.MarketDataTypeEnum.DELAYED) #Use delayed data self.nextValidOrderId = 1 self.permId2ord = {} self.req_to_table_row = {} self.tracked_names = {} self.account_details = {} self.positions = {} self.open_orders = {} if window: self.window = window self.prices_history = Prices() self.portfolio_value_hist = {} self.req_to_strategy = {} self.strategies = {} def save_strategies(self): data = {} for key in self.strategies.keys(): print('Halting: ', type(self.strategies.get(key))) try: strat = self.strategies.get(key) if strat: strat.live = False strat.broker = None self.strategies[key] = strat # dat = {} # dat['symbol'] = strat.symbol # dat['short_window'] = strat.short_window # dat['long_window'] = strat.long_window # dat['position'] = strat.position # dat['pnl'] = strat.pnl # dat['cost'] = strat.cost # dat['trades'] = strat.trades # dat['order_size'] = strat.order_size # dat['live'] = strat.live # dat['name'] = strat.name # dat['strategy_type'] = strat.strategy_type # data[key] = dat except: pass with open('strategies.pk', 'wb') as file: print(type(data)) print('Saving: ', data) pickle.dump(self.strategies, file) self.prices_history.save_price_history() def load_strategies(self): try: with open('strategies.pk', 'rb') as file: self.strategies = pickle.load(file) for key, strategy in self.strategies.items(): strategy.live = True strategy.broker = self _thread = threading.Thread(target=strategy.run_strategy) _thread.start() self.strategies[key] = strategy self.window.update_live_strategies_view() print('Existing strategies loaded: ', self.strategies) except Exception as ex: print('Error loading existing strategies: ', ex) self.strategies = {} @utils.iswrapper # ! [nextvalidid] def nextValidId(self, orderId: int): super().nextValidId(orderId) logging.debug("setting nextValidOrderId: %d", orderId) self.nextValidOrderId = orderId print("NextValidId:", orderId) self.window.log("setting nextValidOrderId: {}".format(orderId)) self.getAccountDetails() self.reqManagedAccts() self.reqNewsProviders() self.register_news() def managedAccounts(self, accountsList: str): super().managedAccounts(accountsList) self.account = accountsList self.window.log("Account list:", accountsList) self.reqAccountUpdates(True, self.account) @utils.iswrapper # ! [updateaccountvalue] def updateAccountValue(self, key: str, val: str, currency: str, accountName: str): super().updateAccountValue(key, val, currency, accountName) self.window.log("{} | {} | {} | {}".format("UpdateAccountValue. Key:", key, "Value:", val, "Currency:", currency, "AccountName:", accountName)) if key in account_details_params: self.account_details[key] = val if key == 'NetLiquidation': self.portfolio_value_hist[datetime.datetime.now()] = val self.window.update_portfolio_hist_chart(self.portfolio_value_hist) #self.window.update_account_table(self.account_details) # ! [updateaccountvalue] @utils.iswrapper # ! [updateportfolio] def updatePortfolio(self, contract: wrapper.Contract, position: float, marketPrice: float, marketValue: float, averageCost: float, unrealizedPNL: float, realizedPNL: float, accountName: str): super().updatePortfolio(contract, position, marketPrice, marketValue, averageCost, unrealizedPNL, realizedPNL, accountName) self.window.log("UpdatePortfolio.", "Symbol:", contract.symbol, "SecType:", contract.secType, "Exchange:", contract.exchange, "Position:", position, "MarketPrice:", marketPrice, "MarketValue:", marketValue, "AverageCost:", averageCost, "UnrealizedPNL:", unrealizedPNL, "RealizedPNL:", realizedPNL, "AccountName:", accountName) self.positions[contract.symbol] = { "Symbol": contract.symbol, "SecType": contract.secType, "Position": position, "MarketValue": marketValue, "AverageCost": averageCost, "UnrealizedPNL": unrealizedPNL, "RealizedPNL:": realizedPNL } self.window.update_positions_table(self.positions) if contract.symbol not in self.tracked_names: self.streamPrice(contract.symbol) self.requestContractDetails(contract.symbol) # ! [updateportfolio] @utils.iswrapper # ! [updateaccounttime] def updateAccountTime(self, timeStamp: str): super().updateAccountTime(timeStamp) self.window.log("UpdateAccountTime. Time:", timeStamp) self.account_details['last_updated'] = timeStamp # ! [updateaccounttime] @utils.iswrapper # ! [accountdownloadend] def accountDownloadEnd(self, accountName: str): super().accountDownloadEnd(accountName) self.window.log("AccountDownloadEnd. Account:", accountName) print('Final account details: ', self.account_details) if self.window: self.window.update_account_table(self.account_details) self.window.update_positions_table(self.positions) print(self.portfolio_value_hist) # ! [accountdownloadend] @utils.iswrapper # ! [error] def error(self, reqId: wrapper.TickerId, errorCode: int, errorString: str): super().error(reqId, errorCode, errorString) print("Error occured on req: {}-{}. Message: {}".format( reqId, errorCode, errorString)) """ Implements API functionalities for fetching """ #Processing Contract Details @utils.iswrapper def contractDetails(self, reqId: int, contractDetails: wrapper.ContractDetails): super().contractDetails(reqId, contractDetails) #my_utils.printinstance(contractDetails) self.window.log(contractDetails.longName) self.window.update_tick_table(self.req_to_table_row.get(reqId), 1, contractDetails.longName, align_center=False) @utils.iswrapper def contractDetailsEnd(self, reqId: int): super().contractDetailsEnd(reqId) self.window.log("ContractDetailsEnd. ReqId: {}".format(reqId)) #Streaming data -- All Last @utils.iswrapper def tickByTickAllLast(self, reqId: int, tickType: int, time: int, price: float, size: int, tickAtrribLast: wrapper.TickAttribLast, exchange: str, specialConditions: str): super().tickByTickAllLast(reqId, tickType, time, price, size, tickAtrribLast, exchange, specialConditions) if tickType == 1: print("Last.", end='') else: print("AllLast.", end='') print( " ReqId:", reqId, "Time:", datetime.datetime.fromtimestamp(time).strftime("%Y%m%d %H:%M:%S"), "Price:", price, "Size:", size, "Exch:", exchange, "Spec Cond:", specialConditions, "PastLimit:", tickAtrribLast.pastLimit, "Unreported:", tickAtrribLast.unreported) @utils.iswrapper def realtimeBar(self, reqId: wrapper.TickerId, time: int, open_: float, high: float, low: float, close: float, volume: int, wap: float, count: int): self.window.log('Realtime bar called') super().realtimeBar(reqId, time, open_, high, low, close, volume, wap, count) #print("RealTimeBar. TickerId:", reqId, wrapper.RealTimeBar(time, -1, open_, high, low, close, volume, wap, count)) @utils.iswrapper def tickPrice(self, reqId: wrapper.TickerId, tickType: wrapper.TickType, price: float, attrib: wrapper.TickAttrib): super().tickPrice(reqId, tickType, price, attrib) _row = self.req_to_table_row.get(reqId) if (ticktypes.get(int(tickType))) == 'Bid': self.window.update_tick_table(_row, 2, str(price)) elif (ticktypes.get(int(tickType))) == 'Ask': self.window.update_tick_table(_row, 3, str(price)) elif (ticktypes.get(int(tickType))) == 'Last': self.window.update_tick_table(_row, 4, str(price)) _inv_names_key = {v: k for k, v in self.tracked_names.items()} self.prices_history.update_price_series(_inv_names_key.get(reqId), price) print(_inv_names_key) elif (ticktypes.get(int(tickType))) == 'High': self.window.update_tick_table(_row, 5, str(price)) elif (ticktypes.get(int(tickType))) == 'Low': self.window.update_tick_table(_row, 6, str(price)) else: print('Unknown tickType: {}'.format(tickType)) #self.window.update_ui() @utils.iswrapper def tickSize(self, reqId: wrapper.TickerId, tickType: wrapper.TickType, size: int): super().tickSize(reqId, tickType, size) if (ticktypes.get(int(tickType))) == 'Volume': self.window.update_tick_table(self.req_to_table_row.get(reqId), 7, str(size)) self.window.update_tick_table(self.req_to_table_row.get(reqId), 8, str('none')) @utils.iswrapper def tickString(self, reqId: wrapper.TickerId, tickType: wrapper.TickType, value: str): pass """ Placing Trades """ @utils.iswrapper def openOrder(self, orderId: wrapper.OrderId, contract: wrapper.Contract, order: wrapper.Order, orderState: wrapper.OrderState): super().openOrder(orderId, contract, order, orderState) self.open_orders[orderId] = { "ticker": contract.symbol, "action": order.action, "ordertype": order.orderType, "totalqty": order.totalQuantity, "lmtprice": order.lmtPrice, "status": orderState.status, "strategy": self.req_to_strategy.get(orderId) } order.contract = contract self.permId2ord[order.permId] = order print(self.open_orders) self.window.update_open_orders_table(self.open_orders) @utils.iswrapper def openOrderEnd(self): super().openOrderEnd() print("OpenOrderEnd") print(self.permId2ord) logging.debug("Received %d openOrders", len(self.permId2ord)) self.window.log(self.open_orders) #app.disconnect() @utils.iswrapper def orderStatus(self, orderId: wrapper.OrderId, status: str, filled: float, remaining: float, avgFillPrice: float, permId: int, parentId: int, lastFillPrice: float, clientId: int, whyHeld: str, mktCapPrice: float): super().orderStatus(orderId, status, filled, remaining, avgFillPrice, permId, parentId, lastFillPrice, clientId, whyHeld, mktCapPrice) print("OrderStatus. Id:", orderId, "Status:", status, "Filled:", filled, "Remaining:", remaining, "AvgFillPrice:", avgFillPrice, "PermId:", permId, "ParentId:", parentId, "LastFillPrice:", lastFillPrice, "ClientId:", clientId, "WhyHeld:", whyHeld, "MktCapPrice:", mktCapPrice) #app.disconnect() """ Account summary operations """ @utils.iswrapper def accountSummary(self, reqId: int, account: str, tag: str, value: str, currency: str): super().accountSummary(reqId, account, tag, value, currency) self.window.log("{} | {} | {} | {}".format( "AccountSummary. ReqId: {}".format(reqId), "Account: {}".format(account), "Tag: {}".format(tag), "Value: {}".format(value), "Currency: {}".format(currency))) @utils.iswrapper def accountSummaryEnd(self, reqId: int): super().accountSummaryEnd(reqId) self.window.log("AccountSummaryEnd. ReqId:", reqId) #app.disconnect() ''' News ''' def register_news(self): contract = wrapper.Contract() contract.symbol = "BRFG:BRFG_ALL" contract.secType = "NEWS" contract.exchange = "BRFG" self.reqMktData(1009, contract, "mdoff,292", False, False, []) @utils.iswrapper #! [tickNews] def tickNews(self, tickerId: int, timeStamp: int, providerCode: str, articleId: str, headline: str, extraData: str): print("TickNews. TickerId:", tickerId, "TimeStamp:", timeStamp, "ProviderCode:", providerCode, "ArticleId:", articleId, "Headline:", headline, "ExtraData:", extraData) #! [tickNews] @utils.iswrapper #! [newsProviders] def newsProviders(self, newsProviders: wrapper.ListOfNewsProviders): print("NewsProviders: ") for provider in newsProviders: print("NewsProvider.", provider) #! [newsProviders] @utils.iswrapper #! [newsArticle] def newsArticle(self, reqId: int, articleType: int, articleText: str): print("NewsArticle. ReqId:", reqId, "ArticleType:", articleType, "ArticleText:", articleText) #! [newsArticle] def streamPrice(self, ticker): if ticker not in self.tracked_names.keys(): #Logging and Setting Valid ID self.window.log('New ticker submitted', self.tracked_names) self.nextValidOrderId = self.nextValidOrderId + 1 self.tracked_names[ticker] = self.nextValidOrderId self.reqMarketDataType(wrapper.MarketDataTypeEnum.DELAYED) contract = my_utils.get_USD_stock_contract(ticker) self.reqMktData(self.nextValidOrderId, contract, "", False, False, []) _current_row = self.window.ui.tick_table.rowCount() self.window.ui.tick_table.insertRow(_current_row) self.req_to_table_row[self.nextValidOrderId] = _current_row self.window.ui.tick_table.setVerticalHeaderItem( _current_row, QtWidgets.QTableWidgetItem( str(self.req_to_table_row.get(self.nextValidOrderId)))) self.window.ui.tick_table.setItem( self.req_to_table_row.get(self.nextValidOrderId), 0, QtWidgets.QTableWidgetItem(contract.symbol)) else: self.window.ui.statusBar().showMessage( 'Stream Price: {} is already tracked'.format(ticker), 3000) def orderContract(self, ticker, quantity, action='BUY', order_type='MKT', lmt_price=0, strategy='Discretionary'): self.nextValidOrderId = self.nextValidOrderId + 1 contract = my_utils.get_USD_stock_contract(ticker) order = wrapper.Order() order.action = action order.orderType = order_type if order.orderType == 'LMT': order.lmtPrice = lmt_price order.totalQuantity = quantity self.placeOrder(self.nextValidOrderId, contract, order) self.req_to_strategy[self.nextValidOrderId] = strategy def getAccountDetails(self): self.nextValidOrderId = self.nextValidOrderId + 1 self.reqAccountSummary(self.nextValidOrderId, "All", AccountSummaryTags.AllTags) def requestContractDetails(self, ticker): ticker = ticker.upper() contract = my_utils.get_USD_stock_contract(ticker) self.reqContractDetails(self.nextValidOrderId, contract)