def process_positions(self, notification_callback=None): """ Processes the positions to identify Profit/Loss """ notification_callback.emit("Processing profits") for s, p in self.app.openPositions.items(): if 'Value' in p.keys(): if p["Value"] != 0: notification_callback.emit("Processing " + s) profit = p["UnrealizedPnL"] / p["Value"] * 100 notification_callback.emit("The profit for " + s + " is " + str(profit) + " %") if profit > float(self.settings.PROFIT): orders = self.app.openOrders if s in orders: notification_callback.emit("Order for " + s + "already exist- skipping") elif int(p["stocks"]) < 0: notification_callback.emit( "The " + s + " is SHORT position number of stocks is negative: " + p["stocks"]) else: notification_callback.emit("Profit for: " + s + " is " + str(profit) + "Creating a trailing Stop Order to take a Profit") contract = createContract(s) order = createTrailingStopOrder(p["stocks"], self.settings.TRAIL) if self.app.tradesRemaining > 0 or self.app.tradesRemaining == -1: self.app.placeOrder(self.app.nextorderId, contract, order) self.app.nextorderId = self.app.nextorderId + 1 notification_callback.emit("Created a Trailing Stop order for " + s + " at level of " + str(self.settings.TRAIL) + "%") self.log_decision("LOG/profits.txt", "Created a Trailing Stop order for " + s + " at level of " + self.settings.TRAIL + "%"+" The profit was:"+str(profit)) else: notification_callback.emit( "NO TRADES remain -Skept creation of Trailing Stop order for " + s + " at level of " + str(self.settings.TRAIL) + "%") self.log_decision("LOG/missed.txt", " Skept :Created a Trailing Stop order for " + s + " at level of " + self.settings.TRAIL + "%") elif profit < float(self.settings.LOSS): orders = self.app.openOrders if s in orders: notification_callback.emit("Order for " + s + "already exist- skipping") else: notification_callback.emit("loss for: " + s + " is " + str(profit) + "Creating a Market Sell Order to minimize the Loss") contract = createContract(s) order = createMktSellOrder(p['stocks']) if self.app.tradesRemaining > 0 or self.app.tradesRemaining == -1: self.app.placeOrder(self.app.nextorderId, contract, order) self.app.nextorderId = self.app.nextorderId + 1 notification_callback.emit("Created a Market Sell order for " + s) self.log_decision("LOG/loses.txt", "Created a Market Sell order for " + s+" The profit was:"+str(profit)) else: notification_callback.emit( "NO TRADES remain -Skept:Created a Market Sell (Stoploss) order for " + s) self.log_decision("LOG/missed.txt", "Skept: Created a Market Sell order for " + s) else: notification_callback.emit("Position " + s + " skept its Value is 0") else: notification_callback.emit("Position " + s + " skept it has no Value")
def buy_the_stock(self, price, s, notification_callback=None): """ Creates order to buy a stock at specific price :param price: price to buy at limit :param s: Stocks to buy """ if self.settings.ALLOWBUY==True: contract = createContract(s) stocksToBuy = int(int(self.settings.BULCKAMOUNT) / price) if stocksToBuy > 0: # very important - check for available trades everywhere!!! order = create_limit_buy_order(stocksToBuy, price) self.app.placeOrder(self.app.nextorderId, contract, order) self.app.nextorderId = self.app.nextorderId + 1 notification_callback.emit( "Issued the BUY order at " + str(price) + "for " + str(stocksToBuy) + " Stocks of " + s) self.log_decision("LOG/buys.txt", "Issued the BUY order at " + str(price) + "for " + str(stocksToBuy) + " Stocks of " + s) else: notification_callback.emit("The single stock is too expensive - skipping") else: notification_callback.emit("Buying is not allowed in Settings - skipping the buying order")
def request_ticker_data(self, ticker: str): # todo implement ticker data functionality contract = createContract(ticker) id = self.app.nextorderId self.app.contract_processing = True self.app.reqContractDetails(self.app.nextorderId, contract) self.app.nextorderId = self.app.nextorderId + 1 while self.app.contract_processing: time.sleep(0.1) cd = self.app.contractDetailsList[id] i = 5 return cd
def evaluate_and_track_candidates(self, notification_callback=None): """ Starts tracking the Candidates and adds the statistics """ time.sleep(1) stock_names = [o.ticker for o in self.settings.CANDIDATES] notification_callback.emit("Starting to track " + ','.join(stock_names) + " Candidates") # starting querry trackedStockN = 1 for s in self.settings.CANDIDATES: id = self.app.nextorderId notification_callback.emit( "starting to track: " + str(trackedStockN) + " of " + str( len(self.settings.CANDIDATES)) + " " + s.ticker + " traking with Id:" + str(id)) c = createContract(s.ticker) self.app.candidatesLive[id] = {"Stock": s.ticker, "Close": "-", "Open": "-", "Bid": "-", "Ask": "-", "averagePriceDropP": "-", "averagePriceSpreadP": "-", "tipranksRank": "-", "LastUpdate": "-"} self.app.reqMarketDataType(1) self.app.reqMktData(id, c, '', False, False, []) self.app.nextorderId += 1 trackedStockN += 1 have_empty = True counter = 0 while have_empty: time.sleep(1) notification_callback.emit("Waiting for last requested candidate Close price :" + str(counter)) closings = [str(x['Close']) for x in self.app.candidatesLive.values()] if '-' in closings: have_empty = True else: have_empty = False counter += 1 self.add_market_data_to_live_candidates(notification_callback) notification_callback.emit(str(len(self.app.candidatesLive)) + " Candidates evaluated and started to track")
def check_if_holiday(self): id = self.app.nextorderId first = next(iter(self.settings.CANDIDATES)) c = createContract(first.ticker) self.app.reqContractDetails(id, c) while (self.app.trading_hours_received != True): print("waiting to get trading session status info") time.sleep(1) session_info_to_parse = self.app.trading_session today_string = session_info_to_parse.split(";")[0] if 'CLOSED' in today_string: self.trading_session_holiday = True else: self.trading_session_holiday = False self.app.nextorderId += 1
def check_if_holiday(self): id = self.app.nextorderId c = createContract( 'AAPL') # checked always with AAPL - can be no candidates self.app.reqContractDetails(id, c) while (self.app.trading_hours_received != True): time.sleep(1) session_info_to_parse = self.app.trading_session today_string = session_info_to_parse.split(";")[0] if 'CLOSED' in today_string: self.trading_session_holiday = True self.app.trading_session_state = "Closed" else: self.trading_session_holiday = False self.check_session_state() self.app.nextorderId += 1
def close_all_positions_cycle(self): try: connected = self.connect_to_tws() if connected: print("Preparing to close all open positions") self.check_if_holiday() self.update_open_positions() self.app.reqGlobalCancel() if self.trading_session_state == "Open": for s, p in self.app.openPositions.items(): if 'Value' in p.keys(): if p["Value"] != 0: print("Closing " + s) contract = createContract(s) order = createMktSellOrder(p['stocks']) self.app.placeOrder(self.app.nextorderId, contract, order) self.app.nextorderId = self.app.nextorderId + 1 print("Created a Market Sell order for " + s) else: print("Position " + s + " skept its Value is 0") else: print("Position " + s + " skept it has no Value") return True else: print( 'All positions closed was not done - session is Closed' ) else: print("Could not connect to TWS ....processing skept..") return False except Exception as e: self.app.disconnect() self.app.reset() if hasattr(e, 'message'): print("Error in closing all positions : " + str(e.message)) else: print("Error in closing all positions : " + str(e))
def update_open_positions(self, notification_callback=None): """ updating all openPositions, refreshed on each worker- to include changes from new positions after BUY """ # update positions from IBKR notification_callback.emit("Updating open Positions:") print("Request all positions general info") self.app.openPositionsLiveDataRequests = { } # reset requests dictionary as positions could be changed... self.app.openPositions = {} # reset open positions self.app.finishedPostitionsGeneral = False # flag to ensure all positions received self.app.reqPositions() # requesting open positions while (self.app.finishedPostitionsGeneral != True): print("waiting to get all general positions info") time.sleep(1) for s, p in self.app.openPositions.items( ): # start tracking one by one if s not in self.app.openPositionsLiveDataRequests.values(): id = self.app.nextorderId self.app.openPositions[s]["tracking_id"] = id self.app.openPositionsLiveDataRequests[id] = s self.app.reqPnLSingle(id, self.settings.ACCOUNT, "", p["conId"]) notification_callback.emit("Started tracking " + s + " position PnL") self.app.nextorderId += 1 # validate all values received have_empty = True counter = 0 while have_empty: time.sleep(1) have_empty = False notification_callback.emit( "Waiting to receive Value for all positions " + str(counter)) for c, v in self.app.openPositions.items(): if 'Value' not in v.keys(): have_empty = True print("The Value for " + c + " is still empty") else: print("The Value for " + c + " is :" + str(v["Value"])) counter += 1 for s, p in self.app.openPositions.items(): # requesting history id = self.app.nextorderId queryTime = datetime.today().strftime("%Y%m%d %H:%M:%S") contract = createContract(s) notification_callback.emit("Requesting History for " + s + " position for last 1 hour BID price") # self.app.reqHistoricalData(id, contract, "", "3600 S", "1 min", "BID", 0, 1, False, []) self.app.reqHistoricalData(id, contract, "", "1 D", "1 hour", "BID", 0, 1, False, []) self.app.openPositionsLiveHistoryRequests[id] = s self.app.nextorderId += 1 # validate all positions have history have_empty = True while have_empty: time.sleep(1) have_empty = False notification_callback.emit( "Waiting to receive Hisory for all positions ") for c, v in self.app.openPositions.items(): if len(v["HistoricalData"]) == 0: have_empty = True notification_callback.emit( str(len(self.app.openPositions)) + " open positions completely updated")
def process_positions(self): """ Processes the positions to identify Profit/Loss """ print("Processing profits") for s, p in self.app.openPositions.items(): if 'Value' in p.keys(): if p["Value"] != 0: print("Processing " + s) profit = p["UnrealizedPnL"] / p["Value"] * 100 print("The profit for " + s + " is " + str(profit) + " %") if profit > float(self.settings.PROFIT): orders = self.app.openOrders if s in orders: print("Order for " + s + "already exist- skipping") elif int(p["stocks"]) < 0: print( "The " + s + " is SHORT position number of stocks is negative: " + p["stocks"]) else: print( "Profit for: " + s + " is " + str(profit) + "Creating a trailing Stop Order to take a Profit" ) if self.settings.ALLOWSELL: contract = createContract(s) order = createTrailingStopOrder( p["stocks"], self.settings.TRAIL) self.app.placeOrder(self.app.nextorderId, contract, order) self.app.nextorderId = self.app.nextorderId + 1 print("Created a Trailing Stop order for " + s + " at level of " + str(self.settings.TRAIL) + "%") else: print( "Selling disabled in settings - skipping") elif profit < float(self.settings.LOSS): orders = self.app.openOrders if s in orders: print("Order for " + s + "already exist- skipping") else: print( "loss for: " + s + " is " + str(profit) + "Creating a Market Sell Order to minimize the Loss" ) if self.settings.ALLOWSELL: contract = createContract(s) order = createMktSellOrder(p['stocks']) self.app.placeOrder(self.app.nextorderId, contract, order) self.app.nextorderId = self.app.nextorderId + 1 print("Created a Market Sell order for " + s) else: print( "Selling disabled in settings - skipping") elif profit > 2 and bool(self.settings.APPLYMAXHOLD): positions_dict = {} for po in self.positions_open_on_server: opened = datetime.datetime.fromisoformat( po['opened']) positions_dict[po['ticker']] = opened if s in positions_dict.keys(): opened = positions_dict[s] delta = (datetime.datetime.now() - opened).days if delta > int(self.settings.MAXHOLDDAYS): orders = self.app.openOrders if s in orders: print("Order for " + s + "already exist- skipping") else: print( s + " is held for " + str(delta) + " days. Creating a Market Sell Order to utilize the funds" ) if self.settings.ALLOWSELL: contract = createContract(s) order = createMktSellOrder(p['stocks']) self.app.placeOrder( self.app.nextorderId, contract, order) self.app.nextorderId = self.app.nextorderId + 1 print( "Created a Market Sell order for " + s) else: print( "Selling disabled in settings - skipping" ) else: print("!!!!!!!!!Position " + s + " not Logged !!!!!") else: print("Position " + s + " skept its Value is 0") else: print("Position " + s + " skept it has no Value")
def evaluate_and_track_candidates(self): """ Starts tracking the Candidates and adds the statistics """ time.sleep(1) # clearing messages stock_names = [o['ticker'] for o in self.stocks_data_from_server] print("Requesting data for " + str(len(stock_names)) + " Candidates") # stock_names=stock_names[0:80] #trimming 90 queries to track less than 100 self.app.CandidatesLiveDataRequests = { } # reset candidates requests dictionary # starting querry trackedStockN = 1 message_number = 0 self.app.market_data_error = False for s in stock_names: if len(self.app.CandidatesLiveDataRequests) > 90: time.sleep(0.5) print( "Requested more than 90 candidates - waiting to be cleared..." ) id = self.app.nextorderId print("starting to track: " + str(trackedStockN) + " of " + str(len(stock_names)) + " " + s + " traking with Id:" + str(id)) c = createContract(s) self.app.CandidatesLiveDataRequests[id] = 'requested' self.app.candidatesLive[id] = { "Stock": s, "Close": 0, "Open": 0, "Bid": 0, "Ask": 0, "averagePriceDropP": 0, "averagePriceSpreadP": 0, "tipranksRank": 0, "yahoo_rank": 6, "stock_invest_rank": 0, "LastUpdate": 0 } self.app.reqMarketDataType(1) self.app.reqMktData(id, c, '', False, False, []) attempt = 0 while len(self.app.CandidatesLiveDataRequests) > 5: attempt = attempt + 1 print( 'Waiting to get last 5 candidates requests, the last to get is : ' + str(self.app.nextorderId) + "Attempt: " + str(attempt)) time.sleep(1) if attempt > 3: break self.app.nextorderId += 1 trackedStockN += 1 message_number += 1 counter = 0 while len(self.app.CandidatesLiveDataRequests) > 0: print("waiting for the last candidate data...." + str(counter)) print('missing:' + str(next(iter(self.app.CandidatesLiveDataRequests)))) counter = counter + 1 time.sleep(1) if counter > 120: return False have_empty = True m = 2 self.add_market_data_to_live_candidates() print( str(len(self.app.candidatesLive)) + " Candidates evaluated and started to track") self.api_connected = True return True