def start_trading(self, Tmode=False): global ml now = datetime.datetime.now(TZ) Notify.info("Trading has begun") self.logger.info("Trading has begun") count = 1 if not Tmode: while now.time() < self.pack_up or self.is_dev_mode: try: for trader in self.traders: trader.run() self.logger.info(f"Completed round {count}") sleep(self.period) except Exception as e: Notify.fatal("Trading has been aborted") self.logger.critical( "Trade abort due to unexpected error : ", e) quit(0) finally: now = datetime.datetime.now(TZ) count += 1 else: Notify.info("Confirming access to live stock price...") self.logger.info("Confirming access to live stock price...") for trader in self.traders: try: get_live_price(trader.ticker) except Exception as e: Notify.fatal( "Error in fetching live stock price. Aborting") self.logger.critical( "Error in fetching live stock price : ", e)
def start_trading(self, Tmode=False): global ml now = datetime.datetime.now(TZ) Notify.info("Trading has begun") ml.info("Trading has begun") count = 1 if not Tmode: while now.time() < PACK_UP or DEV_MODE: try: for trader in self.traders: trader.run() ml.info("Completed round #", count) sleep(PERIOD_INTERVAL) except Exception as e: Notify.fatal("Trading has been aborted") ml.critical("Trade abort due to unexpected error : ", e) quit(0) finally: now = datetime.datetime.now(TZ) count += 1 else: Notify.info("Confirming access to live stock price...") ml.info("Confirming access to live stock price...") for trader in self.traders: try: get_live_price(trader.ticker) except Exception as e: Notify.fatal( "Error in fetching live stock price. Aborting") ml.critical("Error in fetching live stock price : ", e)
def get_stocks(stocks_temp, prev_data, key): if (not key in prev_data): raise Exception(f"Missing key '{key}' in prev_data") for ticker in prev_data[key]: stock_name, stock_ex = ticker.split(".") if stock_name in stocks_temp: Notify.fatal("Cannot buy and sell the same stock.") quit(0) stocks_temp[stock_name] = stock_ex
def make_decision(self): # global ACCOUNT # update tenkan data self.tenkan_data = [] for i in range(DATA_LIMIT - 9): tenkan_src = self.price[i:i + 9] self.tenkan_data.append((max(tenkan_src) + min(tenkan_src)) / 2) # update kijun data self.kijun_data = [] for i in range(DATA_LIMIT - 26): kijun_src = self.price[i:i + 26] self.kijun_data.append((max(kijun_src) + min(kijun_src)) / 2) # update x values for senkou A and senkou B self.x5 = self.time[78:78 + DATA_LIMIT - 26] self.x6 = self.time[104:104 + DATA_LIMIT - 52] # update senkou A data self.senkou_A_data = [ (self.tenkan_data[i + 17] + self.kijun_data[i]) / 2 for i in range(DATA_LIMIT - 26) ] # update senkou B data self.senkou_B_data = [] for i in range(DATA_LIMIT - 52): senkou_B_src = self.price[i:i + 52] self.senkou_B_data.append( (max(senkou_B_src) + min(senkou_B_src)) / 2) # get Ichimoku params for comparison x = self.time[26:26 + DATA_LIMIT][-1] curr_price = self.price[-1] tenkan = self.tenkan_data[-1] kijun = self.kijun_data[-1] sen_A = self.get_value(self.senkou_A_data, self.x5, x) sen_B = self.get_value(self.senkou_B_data, self.x6, x) self.logger.info( f"Current status - Price : {curr_price}, Tenkan : {tenkan}, Kijun : {kijun}, Senkou A : {sen_A}, Senkou B : {sen_B}" ) # conditions for long trade entry # If Kumo cloud is green and current price is above kumo, strong bullish signal cond1 = (sen_A > sen_B) and (curr_price >= sen_A) if cond1: self.logger.debug("Sensing strong bullish signal") # conditions for short trade entry # If Kumo cloud is red and current price is below kumo, strong bearish signal cond2 = (sen_A < sen_B) and (curr_price <= sen_A) if cond2: self.logger.debug("Sensing strong bearish signal") # check allocated money cond3 = curr_price < self.account # IF all conditions are right, long trade entry if cond1 and not self.IN_LONG_TRADE and cond3: self.buy(curr_price, "LONG") self.price_for_buffer = curr_price self.IN_LONG_TRADE = True self.STOCKS_TO_SELL += 1 if not cond3: Notify.fatal( f"[Trader #{self.number} {self.ticker}] : Oops! Out of cash!") self.logger.critical("Trader out of cash to buy stocks!") # If all conditions are right, short trade entry if cond2 and not self.IN_SHORT_TRADE: self.sell(curr_price, "SHORT") self.price_for_buffer = curr_price self.IN_SHORT_TRADE = True self.STOCKS_TO_BUY_BACK += 1 # setup buffer for stop loss and trade exit buffer = self.price_for_buffer * BUFFER_PERCENT cond4 = abs(curr_price - kijun) >= buffer # Get stopped out as the price moves through the buffer area beyond the Kijun if self.IN_LONG_TRADE: if cond4: self.sell(curr_price, "LONG") self.IN_LONG_TRADE = False self.STOCKS_TO_SELL -= 1 if self.IN_SHORT_TRADE: if cond4 and cond3: self.buy(curr_price, "SHORT") self.IN_SHORT_TRADE = False self.STOCKS_TO_BUY_BACK -= 1 if not cond3: Notify.fatal( f"[Trader #{self.number} {self.ticker}] : Oops! Out of cash!" ) self.logger.critical("Trader out of cash to buy back stock !")
def main(): """ Main Function """ # make sure that market is open if not DEV_MODE and CHECK_MARKET: if args.t: Notify.for_input("Check Market? (y/n) : ") confirm = input().strip().lower() print("") else: confirm = "y" if is_open() or confirm == "n": pass else: Notify.fatal("Market is closed at the moment, aborting.") print("") quit(0) # else: # Notify.warn("You are in developer mode, if not intended, please quit.") # Notify.info("Press ENTER to continue, Ctrl+C to quit") # input() # allow market to settle to launch Ichimoku strategy if IDLE_DELAY == 0: Notify.info("Skipped Idle phase") else: Notify.info( f"Entered Idle phase at {datetime.datetime.now(TZ).strftime('%H:%M:%S')}" ) master_logger.info(f"Entered Idle phase") Notify.info(f"\tExpected release : after {IDLE_DELAY // 60} minutes") print("") sleep(IDLE_DELAY) master_logger.info("Idle phase complete") # find relevant stocks to focus on Notify.info("Finding stocks to focus on .....") try: stocks_to_focus = fetch_stocks() except Exception as ex: print(f'Exception was {ex}') stocks_to_focus = [] Notify.fatal( "Could not fetch relevant stocks. Verify Network connection and check logs for details." ) master_logger.critical( "Could not fetch relevant stocks, Most possibly due to network error" ) quit(0) Notify.info("\tStatus : Complete") master_logger.info("Successfully found relevant stocks") print("") # setup traders and begin trade master = Master(PERIOD_INTERVAL, master_logger, FEASIBLE_PERCENT, ACCOUNT, PACK_UP, DEV_MODE) master.validate_repo() master.lineup_traders(stocks_to_focus) master.init_traders(args.t) master.start_trading(args.t) # trading in over by this point Notify.info("Trading complete") master_logger.info("Trading complete") # initiate packup del master quit(0)
def fetch_stocks(): """ Find relevant stocks to focus on for trading Returns: Deque of tickers of relevant stocks """ global ml # url to grab data from url = f'https://finance.yahoo.com/gainers?count={NUM_OF_STOCKS_TO_SEARCH}' # request header headers = { 'user-agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36' } try: src = requests.get(url=url, headers=headers).content except Exception as e: src = None Notify.fatal( "Trade abort due to unexpected error. Check activity log for details" ) master_logger.critical("Encountered error : ", e) quit(0) # soup object of source code soup = BeautifulSoup(src, "html.parser") rows = soup.find('table').tbody.find_all('tr') # initialisations stocks_temp = dict() # check previous day's closing status prev_data = json.loads(open("database/user_info.json").read()) get_sells(stocks_temp, prev_data, "stocks_to_sell") get_buys(stocks_temp, prev_data, "stocks_to_buy_back") # set counter count = len(stocks_temp) stocks = deque() # iterate over rows in web page for tr in rows: # exit if if count == NUM_OF_STOCKS_TO_FOCUS: break else: row_data = tr.find_all('td') ticker = row_data[0].text.strip() price = get_live_price(ticker) # split ticker for checking if same stock of different stock exchange is selected or not stock_name = "" stock_ex = "US" stock_name = ticker #ticker.split(".") if price >= PENNY_STOCK_THRESHOLD and stock_name not in stocks_temp: stocks_temp[stock_name] = stock_ex count += 1 # get back ticker for stock in stocks_temp: stocks.append(f"{stock}") # stocks.append(f"{stock}.{stocks_temp[stock]}") # return deque of stocks to focus on return stocks
############################################################## TODAY = datetime.date.today().strftime("%d-%m-%Y") if not os.path.exists(f"database/{TODAY}"): os.mkdir(f"database/{TODAY}") master_logger = master_logger(f'database/{TODAY}/master.log') master_logger.info("-" * 76) master_logger.info("-" * 27 + " NEW SESSION DETECTED " + "-" * 27) sys.stderr = open(f"database/{TODAY}/errorStream.txt", "a") ############################################################## try: ACCOUNT = json.loads(open("database/user_info.json").read() )["account_balance"] * FEASIBLE_PERCENT except FileNotFoundError: Notify.fatal('User info not found, Aborting.') master_logger.critical("User info not found") quit(0) master_logger.info("Successfully loaded user_info.json") master_logger.info("-" * 76) ############################################################## HEADERS = { "user-agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36" } ############################################################## parser = argparse.ArgumentParser(