def process_ibkr_cycle(self): self.ibkrworker = IBKRWorker(self.settings) self.ibkrworker.stocks_data_from_server = self.stocks_data_from_server self.ibkrworker.positions_open_on_server = self.positions_open_on_server successfull_cycle = self.ibkrworker.run_full_cycle() if not successfull_cycle: restart_tws_and_trader() print("Worker finished reporting to the server........") self.report_to_server()
def __init__(self, settings): # mandatory QMainWindow.__init__(self) Ui_MainWindow.__init__(self) self.trading_session_state = "TBD" self.est = timezone('US/Eastern') self.settingsWindow = SettingsWindow() self.setupUi(self) self.settings = settings self.ibkrworker = IBKRWorker(self.settings) self.threadpool = QThreadPool() self.setWindowTitle("Algo Traider v 2.0") sys.stderr = open('LOG/errorLog.txt', 'w') self.create_open_positions_grid() # setting a timer for Worker self.uiTimer = QTimer() self.uiTimer.timeout.connect(self.update_ui) self.workerTimer = QTimer() self.workerTimer.timeout.connect(self.run_worker) self.server_timer = QTimer() self.server_timer.timeout.connect(self.report_to_server) self.server_timer.start(int(self.settings.INTERVALSERVER) * 1000) # connecting a buttons self.chbxProcess.stateChanged.connect(self.process_checked) self.btnSettings.pressed.connect(self.show_settings) self.statusbar.showMessage("Ready") stock_names = [o.ticker for o in self.settings.CANDIDATES] self.ibkrworker.stocks_data_from_server = get_market_data_from_server( self.settings, stock_names) self.update_console("Market data for " + str(len(stock_names)) + " Candidates received from Server") self.start_updating_candidates_and_connect() StyleSheet = ''' #lcdPNLgreen { border: 3px solid green; } #lcdPNLred { border: 3px solid red; } ''' self.setStyleSheet(StyleSheet)
def __init__(self, settings): # mandatory QMainWindow.__init__(self) Ui_MainWindow.__init__(self) self.settingsWindow = SettingsWindow() self.setupUi(self) self.settings = settings self.ibkrworker = IBKRWorker(self.settings) self.threadpool = QThreadPool() self.setWindowTitle("Algo Traider v 2.0") sys.stderr = open('LOG/errorLog.txt', 'w') self.create_open_positions_grid() # # redirecting Cosole to UI and Log # sys.stdout = OutLog(self.consoleOut, sys.stdout) # sys.stderr = OutLog(self.consoleOut, sys.stderr) # setting a timer for Worker self.uiTimer = QTimer() self.uiTimer.timeout.connect(self.update_ui) self.workerTimer = QTimer() self.workerTimer.timeout.connect(self.run_worker) # connecting a buttons self.chbxProcess.stateChanged.connect(self.process_checked) self.btnSettings.pressed.connect(self.show_settings) self.statusbar.showMessage("Ready") # self.update_session_state() # self.connect_to_ibkr() if not self.settings.UIDEBUG: self.connect_to_ibkr() else: self.btnSettings.setEnabled(True) StyleSheet = ''' #lcdPNLgreen { border: 3px solid green; } #lcdPNLred { border: 3px solid red; } ''' self.setStyleSheet(StyleSheet)
def restart_all(self): """ Restarts everything after Save """ self.threadpool.waitForDone() self.update_console("UI paused- for restart") self.uiTimer.stop() self.workerTimer.stop() self.update_console("Configuration changed - restarting everything") self.chbxProcess.setEnabled(False) self.chbxProcess.setChecked(False) self.btnSettings.setEnabled(False) self.ibkrworker.app.disconnect() while self.ibkrworker.app.isConnected(): print("waiting for disconnect") time.sleep(1) self.ibkrworker = None self.ibkrworker = IBKRWorker(self.settings) self.connect_to_ibkr() i = 4
def process_close_all_cycle(self): self.ibkrworker = IBKRWorker(self.settings) self.ibkrworker.close_all_positions_cycle() print("Worker finished reporting to the server........")
class Algotrader: def __init__(self): self.trading_session_state = "TBD" self.trading_time_zone = timezone('US/Eastern') self.settings = None self.stocks_data_from_server = None self.positions_open_on_server = None self.started_time = datetime.now() def get_settings(self): print('Connecting to server - to get settings.') self.settings = None try: self.settings = TraderSettings() except Exception as e: if hasattr(e, 'message'): print("Error in getting Settings: " + str(e.message)) else: print("Error in getting Settings: " + str(e)) print('Settings received.') if self.settings is not None: return True else: return False def start_processing(self): self.process_worker() threading.Timer(self.settings.INTERVALSERVER, self.start_processing).start() def process_worker(self): print("Requesting Command from server......") result = self.get_settings() # to not fall on server restarts while result == False: time.sleep(10) result = self.get_settings() if self.settings is not None: server_command = get_command_from_server(self.settings) self.process_server_command_response(server_command) def process_server_command_response(self, r): response = json.loads(r) self.stocks_data_from_server = response['candidates'] self.positions_open_on_server = response['open_positions'] self.settings.MARKETEMOTION = int(response['market_emotion']) command = response['command'] print('Received command : ' + command) if command == 'restart_worker': print( 'Restart command received- doing restart for Algotrader and TWS' ) restart_tws_and_trader() elif command == 'close_all_positions': print("Closing all open positions") self.process_close_all_cycle() self.get_settings() # to refresh a settings and cancell a BUY else: self.process_ibkr_cycle() def process_close_all_cycle(self): self.ibkrworker = IBKRWorker(self.settings) self.ibkrworker.close_all_positions_cycle() print("Worker finished reporting to the server........") def process_ibkr_cycle(self): self.ibkrworker = IBKRWorker(self.settings) self.ibkrworker.stocks_data_from_server = self.stocks_data_from_server self.ibkrworker.positions_open_on_server = self.positions_open_on_server successfull_cycle = self.ibkrworker.run_full_cycle() if not successfull_cycle: restart_tws_and_trader() print("Worker finished reporting to the server........") self.report_to_server() def report_to_server(self): net_liquidation = self.ibkrworker.app.netLiquidation if hasattr(self.ibkrworker.app, 'smaWithSafety'): remaining_sma_with_safety = self.ibkrworker.app.smaWithSafety else: remaining_sma_with_safety = self.ibkrworker.app.sMa excess_liquidity = self.ibkrworker.app.excessLiquidity remaining_trades = self.ibkrworker.app.tradesRemaining all_positions_value = 0 open_positions = self.ibkrworker.app.openPositions open_orders = self.ibkrworker.app.openOrders candidates_live = self.ibkrworker.app.candidatesLive dailyPnl = self.ibkrworker.app.dailyPnl tradinng_session_state = self.ibkrworker.trading_session_state worker_last_execution = self.ibkrworker.last_worker_execution_time api_connected = self.ibkrworker.api_connected market_data_error = self.ibkrworker.app.market_data_error data_for_report = [ self.settings, net_liquidation, remaining_sma_with_safety, remaining_trades, all_positions_value, open_positions, open_orders, candidates_live, dailyPnl, worker_last_execution, datetime.now(self.trading_time_zone), tradinng_session_state, excess_liquidity, self.started_time, api_connected, market_data_error, client_version ] report_snapshot_to_server(self.settings, data_for_report) self.ibkrworker.app.disconnect() def start_tws(self, settings): tws_running = checkIfProcessRunning('JavaApplicationStub') user = str(os.environ._data) if 'colakamornik' not in user and 'lilia' not in user: print('Starting TWS configured in INI file') cmd = settings.TWSSTARTCOMMAND os.system(cmd) while not checkIfProcessRunning('pxgsettings'): print('Waiting for login Screen') time.sleep(1) print("TWS process found starting login") login_tws_user(settings)
class MainWindow(QMainWindow, Ui_MainWindow): def __init__(self, settings): # mandatory QMainWindow.__init__(self) Ui_MainWindow.__init__(self) self.trading_session_state = "TBD" self.est = timezone('US/Eastern') self.settingsWindow = SettingsWindow() self.setupUi(self) self.settings = settings self.ibkrworker = IBKRWorker(self.settings) self.threadpool = QThreadPool() self.setWindowTitle("Algo Traider v 2.0") sys.stderr = open('LOG/errorLog.txt', 'w') self.create_open_positions_grid() # setting a timer for Worker self.uiTimer = QTimer() self.uiTimer.timeout.connect(self.update_ui) self.workerTimer = QTimer() self.workerTimer.timeout.connect(self.run_worker) self.server_timer = QTimer() self.server_timer.timeout.connect(self.report_to_server) self.server_timer.start(int(self.settings.INTERVALSERVER) * 1000) # connecting a buttons self.chbxProcess.stateChanged.connect(self.process_checked) self.btnSettings.pressed.connect(self.show_settings) self.statusbar.showMessage("Ready") stock_names = [o.ticker for o in self.settings.CANDIDATES] self.ibkrworker.stocks_data_from_server = get_market_data_from_server( self.settings, stock_names) self.update_console("Market data for " + str(len(stock_names)) + " Candidates received from Server") self.start_updating_candidates_and_connect() StyleSheet = ''' #lcdPNLgreen { border: 3px solid green; } #lcdPNLred { border: 3px solid red; } ''' self.setStyleSheet(StyleSheet) def update_candidates_info(self, status_callback, notification_callback): today_dt = date.today() for c in self.ibkrworker.stocks_data_from_server: updated_dt = c['tiprank_updated'].date() if today_dt != updated_dt: # yahoo notification_callback.emit('Update for ' + c['ticker'] + ' needed:') notification_callback.emit('Checking for Yahoo statisticks...') drop, change = get_yahoo_stats_for_candidate( c['ticker'], notification_callback) c['yahoo_avdropP'] = drop c['yahoo_avspreadP'] = change notification_callback.emit('Got ' + str(drop) + ' average daily drop and ' + str(change) + ' average daily change.') # tipranks notification_callback.emit('Checking for Tiprank...') rank = get_tiprank_rating_for_ticker( c['ticker'], self.settings.PATHTOWEBDRIVER) notification_callback.emit('Got rank of :' + str(rank)) c['tipranks'] = rank c['tiprank_updated'] = today_dt else: notification_callback.emit( 'Data for ' + c['ticker'] + ' is up to the date,no update needed') report_market_data_to_server(self.settings, self.ibkrworker.stocks_data_from_server) return 'done' def start_updating_candidates_and_connect(self): cand = Worker(self.update_candidates_info) cand.signals.result.connect(self.connect_to_ibkr) # connector.signals.status.connect(self.update_status) cand.signals.notification.connect(self.update_console) # Execute self.threadpool.start(cand) def connect_to_ibkr(self): """ Starts the connection to the IBKR terminal in separate thread """ self.update_console("Reporting connection to the server...") print("Reporting connection to the server...") result = report_login_to_server(self.settings) self.update_console(result) connector = Worker(self.ibkrworker.prepare_and_connect) connector.signals.result.connect(self.connection_done) connector.signals.status.connect(self.update_status) connector.signals.notification.connect(self.update_console) # Execute self.threadpool.start(connector) def process_checked(self): """ Starts the Timer with interval from Config file """ if self.chbxProcess.isChecked(): self.run_worker() self.workerTimer.start(int(self.settings.INTERVALWORKER) * 1000) else: self.workerTimer.stop() # noinspection PyUnresolvedReferences def run_worker(self): """ Executed the Worker in separate thread """ # exec(open('restarter.py').read()) # sys.exit() self.update_session_state() currentTime = QTime().currentTime() fromTime = QTime(int(self.settings.TECHFROMHOUR), int(self.settings.TECHFROMMIN)) toTime = QTime(int(self.settings.TECHTOHOUR), int(self.settings.TECHTOMIN)) sessionState = self.lblMarket.text() if fromTime < currentTime < toTime: print("Worker skept-Technical break : ", fromTime.toString("hh:mm"), " to ", toTime.toString("hh:mm")) self.update_console("Technical break untill " + toTime.toString("hh:mm")) else: self.update_console("Starting Worker- UI Paused") self.uiTimer.stop( ) # to not cause an errors when lists will be resetted worker = Worker( self.ibkrworker.process_positions_candidates ) # Any other args, kwargs are passed to the run function worker.signals.result.connect(self.update_ui) worker.signals.status.connect(self.update_status) worker.signals.notification.connect(self.update_console) # Execute self.threadpool.start(worker) def connection_done(self): # add processing self.update_ui() if self.settings.AUTOSTART: self.chbxProcess.setChecked(True) # # report market data to server # if self.settings.USESERVER: # print("Reporting market data to the server...") # result = report_market_data_to_server(self.settings, self.ibkrworker.app.candidatesLive) # self.update_console(result) def report_to_server(self): """ reports to the server """ if self.settings.USESERVER: net_liquidation = self.ibkrworker.app.netLiquidation if hasattr(self.ibkrworker.app, 'smaWithSafety'): remaining_sma_with_safety = self.ibkrworker.app.smaWithSafety else: remaining_sma_with_safety = self.ibkrworker.app.sMa excess_liquidity = self.ibkrworker.app.excessLiquidity remaining_trades = self.ibkrworker.app.tradesRemaining all_positions_value = 0 open_positions = self.ibkrworker.app.openPositions open_orders = self.ibkrworker.app.openOrders dailyPnl = self.ibkrworker.app.dailyPnl tradinng_session_state = self.trading_session_state data_for_report = [ self.settings, net_liquidation, remaining_sma_with_safety, remaining_trades, all_positions_value, open_positions, open_orders, dailyPnl, self.ibkrworker.last_worker_execution_time, datetime.now(self.est), self.trading_session_state, excess_liquidity ] worker = Worker(report_snapshot_to_server, self.settings, data_for_report) worker.signals.result.connect(self.process_server_response) # Execute self.threadpool.start(worker) def process_server_response(self, r): # trying to restart if '$restart$' in r: restart() self.update_console(r) def update_ui(self): """ Updates UI after connection/worker execution """ # main data self.lAcc.setText(self.settings.ACCOUNT) # self.lExcessLiquidity.setText(str(self.ibkrworker.app.excessLiquidity)) # self.lSma.setText(str(self.ibkrworker.app.sMa)) if hasattr(self.ibkrworker.app, 'smaWithSafety'): self.lSma.setText(str(round(self.ibkrworker.app.smaWithSafety, 1))) else: self.lSma.setText(str(round(self.ibkrworker.app.sMa, 1))) self.lMarketValue.setText(str(self.ibkrworker.app.netLiquidation)) self.lblAvailTrades.setText(str(self.ibkrworker.app.tradesRemaining)) self.lcdPNL.display(self.ibkrworker.app.dailyPnl) if self.ibkrworker.app.dailyPnl > 0: palette = self.lcdPNL.palette() palette.setColor(palette.WindowText, QtGui.QColor(51, 153, 51)) self.lcdPNL.setPalette(palette) elif self.ibkrworker.app.dailyPnl < 0: palette = self.lcdPNL.palette() palette.setColor(palette.WindowText, QtGui.QColor(255, 0, 0)) self.lcdPNL.setPalette(palette) total_positions_value = 0 for p in self.ibkrworker.app.openPositions.values(): if hasattr(p, 'Value'): total_positions_value += p["Value"] self.lPositionsTotalValue.setText(str(round(total_positions_value, 1))) self.update_open_positions() self.update_live_candidates() self.update_open_orders() # everything disabled for safety - is now enabled self.chbxProcess.setEnabled(True) self.btnSettings.setEnabled(True) self.update_session_state() if not self.uiTimer.isActive(): self.update_console("UI resumed.") self.uiTimer.start(int(self.settings.INTERVALUI) * 1000) # reset the ui timer def update_session_state(self): fmt = '%Y-%m-%d %H:%M:%S' self.est_dateTime = datetime.now(self.est) self.est_current_time = QTime(self.est_dateTime.hour, self.est_dateTime.minute, self.est_dateTime.second) self.lblTime.setText(self.est_current_time.toString()) dStart = QTime(4, 00) dEnd = QTime(20, 00) tStart = QTime(9, 30) tEnd = QTime(16, 0) self.ibkrworker.check_if_holiday() if not self.ibkrworker.trading_session_holiday: if self.est_current_time > dStart and self.est_current_time <= tStart: self.ibkrworker.trading_session_state = "Pre Market" self.lblMarket.setText("Pre Market") elif self.est_current_time > tStart and self.est_current_time <= tEnd: self.ibkrworker.trading_session_state = "Open" self.lblMarket.setText("Open") elif self.est_current_time > tEnd and self.est_current_time <= dEnd: self.ibkrworker.trading_session_state = "After Market" self.lblMarket.setText("After Market") else: self.ibkrworker.trading_session_state = "Closed" self.lblMarket.setText("Closed") else: self.ibkrworker.trading_session_state = "Holiday" self.lblMarket.setText("Holiday") self.trading_session_state = self.ibkrworker.trading_session_state def progress_fn(self, n): msgBox = QMessageBox() msgBox.setText(str(n)) retval = msgBox.exec_() def update_status(self, s): """ Updates StatusBar on event of Status :param s: """ self.statusbar.showMessage(s) def update_console(self, n): """ Adds Message to console- upon event :param n: """ self.consoleOut.append(n) self.log_message(n) def log_message(self, message): """ Adds message to the standard log :param message: """ with open(LOGFILE, "a") as f: currentDt = datetime.now().strftime("%d-%b-%Y (%H:%M:%S.%f)") message = "\n" + currentDt + '---' + message f.write(message) def update_live_candidates(self): """ Updates Candidates table """ liveCandidates = self.ibkrworker.app.candidatesLive try: line = 0 self.tCandidates.setRowCount(len(liveCandidates)) for k, v in liveCandidates.items(): self.tCandidates.setItem(line, 0, QTableWidgetItem(v['Stock'])) self.tCandidates.setItem(line, 1, QTableWidgetItem(str(v['Open']))) self.tCandidates.setItem(line, 2, QTableWidgetItem(str(v['Close']))) self.tCandidates.setItem(line, 3, QTableWidgetItem(str(v['Bid']))) self.tCandidates.setItem(line, 4, QTableWidgetItem(str(v['Ask']))) if v['Ask'] < v['target_price'] and v['Ask'] != -1: self.tCandidates.item(line, 4).setBackground( QtGui.QColor(0, 255, 0)) if v['target_price'] is float: self.tCandidates.setItem( line, 5, QTableWidgetItem(str(round(v['target_price'], 2)))) else: self.tCandidates.setItem( line, 5, QTableWidgetItem(str(v['target_price']))) self.tCandidates.setItem( line, 6, QTableWidgetItem(str(round(v['averagePriceDropP'], 2)))) if v['tipranksRank'] == '': v['tipranksRank'] = 0 self.tCandidates.setItem( line, 7, QTableWidgetItem(str(v['tipranksRank']))) if int(v['tipranksRank']) > 7: self.tCandidates.item(line, 7).setBackground( QtGui.QColor(0, 255, 0)) self.tCandidates.setItem( line, 8, QTableWidgetItem(str(v['LastUpdate']))) line += 1 except Exception as e: if hasattr(e, 'message'): self.update_console("Error in updating Candidates: " + str(e.message)) else: self.update_console("Error in updating Candidates: " + str(e)) def update_open_positions(self): """ Updates Positions grid """ open_positions = self.ibkrworker.app.openPositions allKeys = [*open_positions] lastUpdatedWidget = 0 try: for i in range(len(open_positions)): # Update positions Panels widget = self.gp.itemAt(i).widget() key = allKeys[i] values = open_positions[key] if 'stocks' in values.keys(): if values['stocks'] != 0: candidate = next((x for x in self.settings.CANDIDATES if x.ticker == key), None) reason_of_candidate = "Bought manually" if candidate is not None: reason_of_candidate = candidate.reason widget.update_view(key, values, reason_of_candidate) widget.show() lastUpdatedWidget = i else: widgetToRemove = self.gp.itemAt(i).widget() widgetToRemove.hide() else: print("value not yet received") for i in range(self.gp.count()): # Hide the rest of the panels if i > lastUpdatedWidget: widgetToRemove = self.gp.itemAt(i).widget() widgetToRemove.hide() except Exception as e: if hasattr(e, 'message'): self.update_console("Error in refreshing Positions: " + str(e.message)) else: self.update_console("Error in refreshing Positions: " + str(e)) def create_open_positions_grid(self): """ Creates Open positions grid with 99 Positions widgets """ counter = 0 col = 0 row = 0 for i in range(0, 99): if counter % 3 == 0: col = 0 row += 1 self.gp.addWidget(PositionPanel(), row, col) counter += 1 col += 1 def update_open_orders(self): """ Updates Positions table """ openOrders = self.ibkrworker.app.openOrders try: line = 0 self.tOrders.setRowCount(len(openOrders)) for k, v in openOrders.items(): self.tOrders.setItem(line, 0, QTableWidgetItem(k)) self.tOrders.setItem(line, 1, QTableWidgetItem(v['Action'])) self.tOrders.setItem(line, 2, QTableWidgetItem(v['Type'])) line += 1 except Exception as e: if hasattr(e, 'message'): self.update_console("Error in Updating open Orders : " + str(e.message)) else: self.update_console("Error in Updating open Orders : " + str(e)) def thread_complete(self): """ After threaded task finished """ print("TREAD COMPLETE (good or bad)!") def show_settings(self): # self.settingsWindow = SettingsWindowO(self.settings) # self.settingsWindow.show() # Показываем окно # # maybe not needed # self.settingsWindow.changedSettings = False self.settingsWindow.existingSettings = copy.deepcopy(self.settings) self.settingsWindow.changedSettings = False self.settingsWindow.ibkrClient = self.ibkrworker if self.settingsWindow.exec_(): self.settings = self.settingsWindow.existingSettings self.settings.write_config() self.restart_all() else: print("Settings window Canceled") self.settingsWindow = SettingsWindow() def restart_all(self): """ Restarts everything after Save """ self.threadpool.waitForDone() self.update_console("UI paused- for restart") self.uiTimer.stop() self.workerTimer.stop() self.update_console("Configuration changed - restarting everything") self.chbxProcess.setEnabled(False) self.chbxProcess.setChecked(False) self.btnSettings.setEnabled(False) self.ibkrworker.app.disconnect() while self.ibkrworker.app.isConnected(): print("waiting for disconnect") time.sleep(1) self.ibkrworker = None self.ibkrworker = IBKRWorker(self.settings) self.connect_to_ibkr() i = 4