def __init__(self): self.engine = create_engine('postgresql://*****:*****@localhost:5432/nyse_financials') self.api = al.alpaca2Login().getApi() self.fin_db = "financials" self.earnings_db = "earning_dates" self.sentiment_db = "sentiment" self.nothingToGet = True self.db = Database()
def __init__(self): self.db = Database() self.symbols = self.db.get_symbols(TableName.DAY) self.sectors = self.db.get_sectors(TableName.DAY) self.sm = StockMess() self.ss = SectorStats() self.app = self.get_home_page() self.submit = None
def __init__(self): self.db = Database() self.sectors_trend = [] self.spy_trend = [] self.last_date = None self.spy = None self.stocks = None self.in_day_stocks = None self.trend_data = None
def __init__(self): self.db = Database() self.ss = SectorStats() self.last_date = None self.financials = None self.earnings = None self.sentiment = None self.spy = None self.stocks = None self.in_day_stocks = None self.trend_data = None
def __init__(self, trading_provider: Optional[TradingProviders] = None, trading_strategy: Optional[TradingStrategies] = None, fill_open_trades=OpenTradesSource.DB, table_name="buy_sell_bt"): if trading_provider == TradingProviders.ALPACA: self.trading_provider = TradingProvider(name=trading_provider, instance=AlpacaBuySell()) self.trading_strategy = trading_strategy # self.credit["start_amount"] = 1000 # self.credit['curr_amount'] = credit['start_amount'] self.buyed_stocks = pd.DataFrame() # self.stock_stats = Sdf() # self.startCredit = 10000 self.credit = {'curr_amount': 10000, "start_amount": 10000} self.money: float = 100000 self.prev_stock = None self.buyed_stocks = 0 self.first_stock = pd.DataFrame() self.buy_marks = pd.DataFrame() self.sell_marks = pd.DataFrame() self.top_stocks_list = pd.DataFrame() self.last_buyed_stock = Optional[dict] self.first_buyed_price = 0.0 self.profit_perc = 0.0 self.profit_perc_all = 0.0 self.transactions = 0 self.buy_sell_closed = pd.DataFrame() self.share_amount = 1 self.close_alpaca_postition = False self.db = Database() self.shares_amount = 1 self.startCredit = 10000 self.table_name = table_name # self.tv = TradingVars() if fill_open_trades == OpenTradesSource.DB: self.buy_sell_open = self.fill_open_trades_from_db() elif fill_open_trades == OpenTradesSource.ALPACA: # FIX DOESNT WORK self.buy_sell_open = self.fill_trades_from_alpaca()
class getData(): def __init__(self): self.engine = create_engine('postgresql://*****:*****@localhost:5432/nyse_financials') self.api = al.alpaca2Login().getApi() self.fin_db = "financials" self.earnings_db = "earning_dates" self.sentiment_db = "sentiment" self.nothingToGet = True self.db = Database() # df = pd.DataFrame() def get_bars(self, symbol, interval, limit, after): # print(after.isoformat()) data = self.api.get_barset(symbol, interval, limit, after=after.isoformat()) data = data.df[symbol] print(data) return data def get_sentiment(self, days_before=0, days_after=30): from stocknews import StockNews self.get_sentiment_from_csv() symbols = self.db.get_symbols() # print(symbols) sn = StockNews(symbols, wt_key='0d57e2849d73713e95f395c7440380ff') df_sum, r_count = sn.summarize() print("rows: " + str(r_count)) self.save_sentiment(df_sum) print("get sentiment ends") # print(df_new) return df_sum def get_sentiment_from_csv(self): df = pd.read_csv("./data/data.csv", sep=";") print(df) self.save_sentiment(df) def save_sentiment(self, df_sum): """[summary] !!!! WARNING this method ends with exiting whole script Args: df_sum ([type]): [description] """ try: dfdb = pd.read_sql(self.sentiment_db, con=self.engine) df_new = df_sum.append(dfdb, ignore_index=True) except: df_new = df_sum print("Database sentiment doesnt exists") try: df_new.drop(columns=['index','open','close','high','low','volume','change'], inplace=True) except KeyError : print("some columns to drop hasnt been found") df_new.drop_duplicates( subset=["id","stock", "news_dt"], inplace=True, keep="first") df_new.to_sql(self.sentiment_db, con=self.engine, if_exists='replace', index=True) print("Sentiment saved") exit() # return df_new def get_earnings(self, days_before = 0, days_after = 30): from yahoo_earnings_calendar import YahooEarningsCalendar dfdb = pd.read_sql(self.earnings_db, con=self.engine) yec = YahooEarningsCalendar() dfd = pd.DataFrame(yec.earnings_between( datetime.now() - timedelta(days=days_before), datetime.now() + timedelta(days=days_after))) df_new = dfd.append(dfdb, ignore_index=True) df_new.drop_duplicates(subset=["ticker","startdatetime","startdatetimetype"], inplace=True, keep="first") #save DATAFRAME to database df_new.to_sql(self.earnings_db, con=self.engine, if_exists='replace', index=False) print(df_new) return df_new # def convertUnixTimeToDate(columns,df): # for col in columns: # df[col] = pd.to_datetime(df[col],unit="s") # return df def fill_database(self, dfs,interval, limit, table_name, after): self.nothingToGet = True for row in dfs['Symbol']: if row: row = str.strip(row) print(row) # check last date for specific symbol dfp = pd.read_sql('select MAX("index") as last_time from '+ table_name + ' where sym = \'' + row + '\' ', con=self.engine) if dfp.iloc[0].last_time is not None: after = dfp.iloc[0].last_time # get data from ALPACA df = self.get_bars(row, interval, limit, after) if len(df) > 0: self.nothingToGet = False # add symbol df["sym"] = row #add sector # dff = pd.read_sql('select sector from '+ self.fin_db + ' where symbol = \'' + row + '\' and sector is not null limit 1', con=self.engine) # if len(dff) > 0 and dff.iloc[0].sector: # df["sector"] = dff.iloc[0].sector df.index.rename('index', inplace = True) #save DATAFRAME to database df.to_sql(table_name, con=self.engine, if_exists='append', index = True) if table_name == TableName.MIN15: self.save_bar_as_last_in_day(df) def get_last_working_day(self): offset = max(0, (datetime.today().weekday() + 6) % 7 - 3) timedelta2 = timedelta(offset) # most_recent = datetime.today().replace(hour=0, minute=0, second=0, microsecond=0) - timedelta2 most_recent = datetime.today() - timedelta2 return most_recent def save_bar_as_last_in_day(self,last_bar:pd.DataFrame): last_day = self.db.get_last_n_days( sym=last_bar.iloc[-1].sym, n_days_back=1, table=TableName.DAY) last_day.iloc[-1].close = last_bar.iloc[-1].close last_day.iloc[-1].high = last_day.iloc[-1].high if last_day.iloc[-1].high > last_bar.iloc[-1].high else last_bar.iloc[-1].high last_day.iloc[-1].low = last_day.iloc[-1].low if last_day.iloc[-1].low < last_bar.iloc[-1].low else last_bar.iloc[-1].low last_day.to_sql(TableName.DAY, con=self.engine, if_exists='replace', index=False) # param interval could be 1,5,15, 0 - for day def start_download(self, min_interval, start_date, infinity = False): dfs = pd.read_csv("./datasets/RevolutStock.csv", delimiter="|") print(start_date) min_interval = int(min_interval) if min_interval > 0: db_name = 'p_'+ str(min_interval) +'min' else: db_name = 'p_day' while True: try: if min_interval > 0: self.fill_database(dfs,str(min_interval) + "Min",1000, 'p_'+ str(min_interval) +'min', start_date) else: self.fill_database(dfs,"day",1000, 'p_day', start_date) if infinity and self.nothingToGet: break Utils.countdown(60) except KeyboardInterrupt: print("END by keybord interruption") exit() except: print("Unexpected error:", sys.exc_info()[0]) print("Waiting 3 minutes and try it again") Utils.countdown(60) print("DONE")
class BuySell(): trading_provider: TradingProvider # buyed_titles = [{"buy_price","sell_price", "sym", "shares_amount", "buy_date", "sell_date", "profit", "remain_credit"}] # credit = {"start_amount", "curr_amount"} def __init__(self, trading_provider: Optional[TradingProviders] = None, trading_strategy: Optional[TradingStrategies] = None, fill_open_trades=OpenTradesSource.DB, table_name="buy_sell_bt"): if trading_provider == TradingProviders.ALPACA: self.trading_provider = TradingProvider(name=trading_provider, instance=AlpacaBuySell()) self.trading_strategy = trading_strategy # self.credit["start_amount"] = 1000 # self.credit['curr_amount'] = credit['start_amount'] self.buyed_stocks = pd.DataFrame() # self.stock_stats = Sdf() # self.startCredit = 10000 self.credit = {'curr_amount': 10000, "start_amount": 10000} self.money: float = 100000 self.prev_stock = None self.buyed_stocks = 0 self.first_stock = pd.DataFrame() self.buy_marks = pd.DataFrame() self.sell_marks = pd.DataFrame() self.top_stocks_list = pd.DataFrame() self.last_buyed_stock = Optional[dict] self.first_buyed_price = 0.0 self.profit_perc = 0.0 self.profit_perc_all = 0.0 self.transactions = 0 self.buy_sell_closed = pd.DataFrame() self.share_amount = 1 self.close_alpaca_postition = False self.db = Database() self.shares_amount = 1 self.startCredit = 10000 self.table_name = table_name # self.tv = TradingVars() if fill_open_trades == OpenTradesSource.DB: self.buy_sell_open = self.fill_open_trades_from_db() elif fill_open_trades == OpenTradesSource.ALPACA: # FIX DOESNT WORK self.buy_sell_open = self.fill_trades_from_alpaca() def fill_trades_from_alpaca(self): positions = self.trading_provider.instance.get_positions() # logger.debug(positions['symbol']) # todo parse this m**********r to buy:sell structure for item in positions: print(item) return positions def fill_open_trades_from_db(self): sql_string = f"select * from {self.table_name} where state='open'" logger.info(sql_string) try: return pd.read_sql(sql_string, con=self.db.engine) except: return pd.DataFrame() def fill_closed_trades_from_db(self): sql_string = f"select * from {self.table_name} where state='closed'" logger.info(sql_string) return pd.read_sql(sql_string, con=self.db.engine) # def sell_stock(self, stock:Union[pd.DataFrame,StockDataFrame], sell_price: float= None, table_name: str= "buy_sell_bt", shares_amount:float = 1)->None: # """DEPRECATED # Args: # stock (Union[pd.DataFrame,StockDataFrame]): [description] # sell_price (float, optional): [description]. Defaults to None. # table_name (str, optional): [description]. Defaults to "buy_sell_bt". # shares_amount (float, optional): [description]. Defaults to 1. # """ # sell_price = sell_price if sell_price else stock["close"] # self.profit_perc += round((sell_price - self.last_buyed_stock['buy']) / ( # self.last_buyed_stock['buy']/100), 2) # self.buyed_stocks -= shares_amount # self.money = self.money + (sell_price * shares_amount) # buy_sell_stock = pd.DataFrame() # buy_sell_stock.append(stock) # buy_sell_stock["sell"] = sell_price # buy_sell_stock["buy"] = self.last_buyed_stock['buy'] # buy_sell_stock["buy_date"] = self.last_buyed_stock.index # buy_sell_stock["shares_amount"] = shares_amount # buy_sell_stock["state"] = "closed" # self.buy_sell_open = self.buy_sell_open.append(buy_sell_stock) # logger.info("selling: " + str(stock['sym']) + " " + # str(stock.name) + ' -- ' + str((sell_price * shares_amount))) # if table_name: # self.db.save_data(table_name=table_name, # data=self.buy_sell_open, if_exists="replace") # def buy_stock(self, stock: Union[pd.DataFrame, StockDataFrame], buy_price: float=None, table_name:str="buy_sell_bt", shares_amount:float=1, process_live:bool=False, profit_loss:float=None): # """DEPRECATED # Args: # stock (Union[pd.DataFrame, StockDataFrame]): [description] # buy_price (float, optional): [description]. Defaults to None. # table_name (str, optional): [description]. Defaults to "buy_sell_bt". # shares_amount (float, optional): [description]. Defaults to 1. # process_live (bool, optional): [description]. Defaults to False. # profit_loss (float, optional): [description]. Defaults to None. # """ # buy_price = buy_price if buy_price else stock["close"] # if self.transactions == 0: # self.first_buyed_price = buy_price # self.buyed_stocks += shares_amount # self.money = self.money - (buy_price * shares_amount) # self.transactions += 1 # buy_sell_stock = pd.DataFrame() # buy_sell_stock.append(stock) # buy_sell_stock["buy"] = buy_price # buy_sell_stock["shares_amount"] = shares_amount # buy_sell_stock["state"] = "open" # if profit_loss: # buy_sell_stock["profit"] = profit_loss["profit"] # buy_sell_stock["loss"] = profit_loss["loss"] # logger.info("buying: " + str(stock['sym']) + " " + # str(stock.name) + ' -- ' + str((buy_price * shares_amount))) # self.buy_sell_open = self.buy_sell_open.append(buy_sell_stock) # self.last_buyed_stock = buy_sell_stock def sell_stock_t(self, sym: str, price: float, table_name: str = "buy_sell_close", qty: Optional[float] = 1, sell_date: datetime = None, stock: pd.DataFrame = None) -> Optional[pd.DataFrame]: if stock is not None: sell_date = stock.index[0] price = stock.close buyed_stock = self.buy_sell_open[self.buy_sell_open["sym"] == sym] #sell only if some buyed stocks exist if buyed_stock is not None and len(buyed_stock) == 1: buyed_stock = buyed_stock.iloc[0] self.profit_perc += round((price - self.last_buyed_stock['buy']) / (self.last_buyed_stock['buy'] / 100), 2) if qty is None: qty = buyed_stock.shares_amount self.buyed_stocks = self.buyed_stocks - \ qty if buyed_stock.shares_amount >= qty else self.buyed_stocks - buyed_stock.shares_amount self.money = self.money + (price * qty) buyed_stock.sell = price buyed_stock.sell_date = sell_date buyed_stock.shares_amount = ( buyed_stock.shares_amount - qty) if buyed_stock.shares_amount - qty > 0 else 0 buyed_stock.profit = buyed_stock.sell - buyed_stock.buy # print(buyed_stock.buy) # print(buyed_stock.sell) buyed_stock.perc_profit = Utils.calc_perc(buyed_stock.buy, buyed_stock.sell, 2) if buyed_stock.shares_amount == 0: buyed_stock.state = "closed" self.buy_sell_open.drop( self.buy_sell_open[self.buy_sell_open["sym"] == sym].index, inplace=True) # self.buy_sell = self.buy_sell.append(buy_sell_stock) logging.info("selling: " + str(buyed_stock.sell_date)) self.buy_sell_closed = self.buy_sell_closed.append(buyed_stock) self.db.save_data(table_name=table_name, data=self.buy_sell_closed, if_exists="replace") # sell stocks on provider platform if self.trading_provider is not None and self.trading_provider.name == TradingProviders.ALPACA: if self.close_alpaca_postition == False: self.trading_provider.instance.submitOrder(qty, sym, "sell") else: self.trading_provider.instance.close_postions(sym) return buyed_stock else: return None def buy_stock_t(self, stock: pd.DataFrame, price: float = None, table_name: str = "buy_sell_bt", qty: float = 1, process_live: bool = False, profit_loss: Dict = None, buy_already_buyed: bool = False) -> pd.DataFrame: buy_sell_stock: pd.DataFrame = None price = price if price else stock["close"] if self.transactions == 0: self.first_buyed_price = price logger.warning(self.buy_sell_open) money: float = (self.money - (price * qty)) already_buyed:Bool = (buy_already_buyed is True or \ (buy_already_buyed is False and stock.sym not in self.buy_sell_open )) if money <= 0: logger.warning("not enough money") if already_buyed: logger.warning("symbol is already buyed") logger.info(money) logger.debug(already_buyed) if money > 0 and already_buyed: logger.debug( "MOENY OK........................ ALREADY_BUUYED................OK" ) self.money = money self.buyed_stocks += qty self.transactions += 1 # buy_sell_stock = pd.DataFrame() buy_sell_stock = stock.copy() buy_sell_stock["buy"] = price buy_sell_stock["shares_amount"] = qty buy_sell_stock["state"] = "open" buy_sell_stock["sell"] = None buy_sell_stock["sell_date"] = None buy_sell_stock["profit"] = None buy_sell_stock["perc_profit"] = None buy_sell_stock["strategy"] = self.trading_strategy if profit_loss: buy_sell_stock["est_profit"] = profit_loss["profit"] buy_sell_stock["est_loss"] = profit_loss["loss"] logger.info("buying: " + str(buy_sell_stock)) self.buy_sell_open = self.buy_sell_open.append(buy_sell_stock) self.last_buyed_stock = buy_sell_stock logger.debug(self.trading_provider) logger.debug("TRADIGN PROVIDER") # buy stocks on provider platform if self.trading_provider is not None and self.trading_provider.name == TradingProviders.ALPACA: logger.debug("BUYIIIIIIIIIIIIIIIIIIIIIIIIIIIING ON ALPACA") self.trading_provider.instance.submitOrder( qty, stock.tail(1)["sym"], "buy") time.sleep(5) try: self.db.save_data(table_name=table_name, data=self.buy_sell_open, if_exists="replace") except Exception as e: logger.error("Database save failed:" + str(e)) return buy_sell_stock def close_all_alpaca_postitions(self): self.trading_provider.instance.close_all_postions() def clean_all_db_postitions(self): # self.buy_sell_closed = self.fill_closed_trades_from_db() self.db.save_data(table_name=self.table_name, data=pd.DataFrame(), if_exists="append") # self.db.save_data(table_name=self.table_name, # data=self.buy_sell_closed, if_exists="replace") def get_buyed_symbols_on_alpaca(self): buyed_stocks_table = "buyed_stocks" try: #get buyed stocks on alpaca abs = AlpacaBuySell() alp_pos, alp_orders = abs.get_positions() symbols = list() for position in alp_pos: symbols.append(position.symbol) for position in alp_orders: symbols.append(position.symbol) #------------------------------------------------ df_sym = pd.DataFrame(symbols, columns=['sym']) self.db.save_data(buyed_stocks_table, df_sym, "replace") except Exception as e: logger.error("loading buyed symbols from localDB | Err: " + str(e)) symbols = self.db.get_data(buyed_stocks_table) symbols = symbols.sym.tolist() return symbols def check_credit(self, price_sum): if self.credit["curr_amount"] is not None and self.credit[ "curr_amount"] >= price_sum: return True else: return False def get_credit(self): """ return available credit """ pass # return credit["curr_amount"] # def show_stats(self, symbol): # print(" ---------SUMMARY--------------- ") # print("STOCKS: " + str(symbol)) # print("Stocks in buy: " + str(self.buyed_stocks) + " | Last price: " + str(self.prev_stock.close)+ " | Last buyed price: " + str(self.last_buyed_stock['close'])) # afterSellingStockMoney = round(self.money + (self.buyed_stocks * self.last_buyed_stock['close']),2) # # profit = afterSellingStockMoney - self.startCredit; # # tradingGainPercent = (afterSellingStockMoney - self.startCredit) / ( self.startCredit/100)/self.share_amount # tradingGainPercent = (afterSellingStockMoney - self.first_buyed_price) / ( self.first_buyed_price/100)/self.share_amount # tradingGainPercentCurrentPrice = (round(self.money + (self.buyed_stocks * self.prev_stock.close), 2) - # self.credit["start_amount"]) / (self.credit["start_amount"]/100)/self.share_amount # gainWithoutTradingPerc = (self.last_buyed_stock['close'] - self.first_stock.close) / (self.first_stock.close/100) # afterSellingStockMoneyLastPrice = round(self.money + (self.buyed_stocks * self.last_buyed_stock['close']),2) # gainWithoutTradingPercLastPrice = (self.prev_stock.close - self.first_stock.close) / (self.first_stock.close/100) # if self.buyed_stocks > 0: # self.sell_stock(self.prev_stock) # # calculate average perc profit # perc_divider = 1 # if self.profit_perc_all > 0: # perc_divider = 2 # self.profit_perc_all = round((self.profit_perc_all+self.profit_perc)/perc_divider,2) # # print("Money: " + str(self.money)) # # print("After selling remaining stocks for last buyed price: " + str(afterSellingStockMoney) + " | " + str(round(afterSellingStockMoney-self.startCredit,2)) + " | " + str(round(tradingGainPercent,2)) + "%") # # print("After selling remaining stocks for current price: " + str(afterSellingStockMoney) + " | " + str(round(afterSellingStockMoney-self.startCredit,2)) + " | " + str(round(tradingGainPercentCurrentPrice,2)) + "%") # print("First stock p.: " + str(self.first_stock.close) + " | Last stock p. : " +str(self.prev_stock.close) + " | Last buyed stock p. : " +str(self.last_buyed_stock['close'])) # print("Profit from " + str(symbol) +" trade: " + str(self.profit_perc) + '%') # print("Profit from all trades: " + str(self.profit_perc_all) + '%') # print("Profit without trading: " + str(round(gainWithoutTradingPercLastPrice,2)) + "%") # # print("Gain without trading last buyed price: " + str(round(self.last_buyed_stock['close'] - self.first_stock.close, 2)*self.share_amount) + " | " + str(round(gainWithoutTradingPerc,2)) + "%") # # print("Profit without trading: " + str(round(self.prev_stock.close - self.first_stock.close, 2)*self.share_amount) + " | " + str(round(gainWithoutTradingPercLastPrice,2)) + "%") # print("transactions: " + str(self.transactions)) # print("best settings" + str(self.best_settings)) def trading_results(self, show=True) -> Union[None, pd.DataFrame]: res: pd.DataFrame = self.buy_sell_closed.copy() if len(res) > 0: res["profit_money"] = res.buy res["profit_percents"] = round((res.buy) / (res.buy / 100), 2) res["sum_profit_money"] = res["profit_money"].sum() res["sum_profit_percents"] = res["profit_percents"].sum() if show: logger.info("Profit money: ") logger.info(res["profit_money"]) logger.info("Profit percents: ") logger.info(res["profit_percents"]) logger.info("SUM Profit money: ") logger.info(res["sum_profit_money"][0]) logger.info("SUM Profit percents: ") logger.info(res["sum_profit_percents"][0]) return res else: return None def trading_stats(self, symbol: str, bt_stocks: pd.DataFrame) -> str: stats_mess: str = "" stats_mess += ("Last Buyed Stocks: " + str(self.last_buyed_stock)) stats_mess += ("buy sell dataframe : " + str(self.buy_sell_open)) stats_mess += (" ---------SUMMARY--------------- ") stats_mess += ("STOCKS: " + str(symbol)) stats_mess += ("Stocks in buy: " + str(self.buyed_stocks) + " | Last price: " + str(bt_stocks.iloc[-1].close) + " | Last buyed price: " + str(self.last_buyed_stock.buy)) afterSellingStockMoney = round( self.money + (self.buyed_stocks * self.last_buyed_stock.buy), 2) # profit = afterSellingStockMoney - self.startCredit; # tradingGainPercent = (afterSellingStockMoney - self.startCredit) / ( self.startCredit/100)/self.share_amount tradingGainPercent = (afterSellingStockMoney - self.first_buyed_price ) / (self.first_buyed_price / 100) / self.shares_amount tradingGainPercentCurrentPrice = ( round(self.money + (self.buyed_stocks * bt_stocks.iloc[-1].close), 2) - self.startCredit) / (self.startCredit / 100) / self.shares_amount gainWithoutTradingPerc = (self.last_buyed_stock.buy - bt_stocks.iloc[0].close) / ( bt_stocks.iloc[0].close / 100) # afterSellingStockMoneyLastPrice = round(self.money + (self.buyed_stocks * self.last_buyed_stock['close']),2) gainWithoutTradingPercLastPrice = (bt_stocks.iloc[-1].close - bt_stocks.iloc[0].close) / ( bt_stocks.iloc[0].close / 100) if self.buyed_stocks > 0: self.sell_stock(bt_stocks.iloc[-1]) # calculate average perc profit perc_divider = 1 if self.profit_perc_all > 0: perc_divider = 2 self.profit_perc_all = round( (self.profit_perc_all + self.profit_perc) / perc_divider, 2) # stats_mess +=("Money: " + str(self.money)) # stats_mess +=("After selling remaining stocks for last buyed price: " + str(afterSellingStockMoney) + " | " + str(round(afterSellingStockMoney-self.startCredit,2)) + " | " + str(round(tradingGainPercent,2)) + "%") # stats_mess +=("After selling remaining stocks for current price: " + str(afterSellingStockMoney) + " | " + str(round(afterSellingStockMoney-self.startCredit,2)) + " | " + str(round(tradingGainPercentCurrentPrice,2)) + "%") print(self.last_buyed_stock) stats_mess += ("First stock p.: " + str(bt_stocks.iloc[0].close) + " | Last stock p. : " + str(bt_stocks.iloc[-1].close) + " | Last buyed stock p. : " ) #+ str(self.last_buyed_stock['close'])) stats_mess += ("Profit from " + str(symbol) + " trade: " + str(self.profit_perc) + '%') stats_mess += ("Profit from all trades: " + str(self.profit_perc_all) + '%') stats_mess += ("Price change : " + str(round(gainWithoutTradingPercLastPrice, 2)) + "%") # stats_mess +=("Gain without trading last buyed price: " + str(round(self.last_buyed_stock['close'] - bt_stocks.iloc[0].close, 2)*self.share_amount) + " | " + str(round(gainWithoutTradingPerc,2)) + "%") # stats_mess +=("Profit without trading: " + str(round(bt_stocks.iloc[-1].close - bt_stocks.iloc[0].close, 2)*self.share_amount) + " | " + str(round(gainWithoutTradingPercLastPrice,2)) + "%") stats_mess += ("transactions: " + str(self.transactions)) self.show_sym_bs_stats(symbol) return stats_mess def show_sym_bs_stats(self, sym: str): self.db.limit = None dfp, financials, sentiment, earnings, spy = self.db.get_all_data( self.db.time_from, sym) dfp = FinI.add_indicators(dfp) dfp = FinI.add_fib(dfp, last_rows=10) # print(dfp) # last 5 financials financials = financials.tail(5) days_to_earnings = FinI.days_to_earnings(earnings) # print(earnings) if days_to_earnings is None: earnings = None fig, axs = plt.subplots(2, 1, figsize=(16, 16)) PlotI.set_margins(plt) PlotI.plot_spy(axs[0], spy.loc[spy.index.isin(dfp.index)]) axsp = PlotI.plot_stock_prices(axs[0].twinx(), dfp, sym, 0.5) axsp = PlotI.plot_sma(axsp, dfp, ["sma9", "sma50"]) axsp.xaxis.set_major_formatter(plt.NullFormatter()) axsp = PlotI.plot_candles(dfp, axsp, body_w=0.5, shadow_w=0.1, alpha=0.5) axsp = PlotI.plot_fib(dfp, axsp, alpha=0.4) axsp = PlotI.plot_fib(dfp, axsp, alpha=0.4, fib_name="fb_mid") axsp = PlotI.plot_fib(dfp, axsp, alpha=0.4, fib_name="fb_bot") axsp = PlotI.plot_weeks(axsp, dfp) PlotI.plot_boll(axsp, dfp, sym) axsp2 = PlotI.plot_volume_bars(axsp.twinx(), dfp) axsp2 = PlotI.plot_rsi(axs[1], dfp) axsp2 = PlotI.plot_macd_boll(axs[1].twinx(), dfp) # ax_macd = PlotI.plot_macd(ax_macd,dfp) axsp2 = PlotI.plot_volume_bars(axs[1].twinx(), dfp) if self.buy_sell_closed is not None and len(self.buy_sell_closed) > 0: axsp = PlotI.plot_bs(axsp, self.buy_sell_closed) axsp2 = PlotI.plot_bs(axsp2.twinx(), self.buy_sell_closed) plt.show()
train, test = dataset[0:train_size, :], dataset[ train_size:len(dataset), :] print(len(train), len(test)) return train, test # convert an array of values into a dataset matrix def create_dataset(self, dataset: list, look_back=1) -> Tuple[numpy.array, numpy.array]: dataX, dataY = [], [] for i in range(len(dataset) - look_back - 1): a = dataset[i:(i + look_back), 0] dataX.append(a) dataY.append(dataset[i + look_back, 0]) return numpy.array(dataX), numpy.array(dataY) # Manual run from command line for arg in args: if arg == "run": db = Database() m_df = db.load_data(table_name=TableName.DAY, time_from="-380d", symbols=["TSLA"]) m_df_spy = db.load_data(table_name=TableName.DAY, time_from="-380d", symbols=["SPY"]) lstm = MarketLSTM(m_df_spy[["close"]])
class StockMess(): def __init__(self): self.db = Database() self.ss = SectorStats() self.last_date = None self.financials = None self.earnings = None self.sentiment = None self.spy = None self.stocks = None self.in_day_stocks = None self.trend_data = None async def mail_stats(self, data, subject, last_date=None, spy=None): # print(data) if spy is None: spy = sdf.retype( self.db.load_data(TableName.DAY, ["spy"], time_from="-60d", time_to="0d")) for key, value in data.iterrows(): if "flpd" in value: subject_flpd = subject + " " + str(round(value.flpd, 2)) + "% | " try: sym = value.sym except AttributeError: sym = key self.set_fundamentals(sym=sym) self.set_prices(sym=sym) self.mail_sym_stats(sym, subject_flpd, last_date=last_date) def a_mail_sym_stats(self, sym, subject, last_date=None): self.mail_sym_stats(sym, subject, last_date=None) def mail_sym_stats(self, sym, subject, last_date=None): # self.db.last_date = last_date # if self.spy is None: # self.spy = sdf.retype(self.db.load_data( # TableName.DAY, ["spy"], time_from="-60d", time_to="0d")) # self.stocks = sdf.retype(self.db.load_data(TableName.DAY, sym, time_from="-60d", time_to = "0d")) # self.stocks = FinI.add_indicators(self.stocks) # time_to = last_date # self.earnings, self.sentiment, self.financials = self.db.get_fundamentals(self.stocks.iloc[-1]["sym"], # tf={"e": "-5d", # "s": "-20d", # "f": "-14d"}, # tt={"e": "30d", "s": "0d", "f": "0d"}) mess, curr_price, days_to_earnings = self.get_subj_mess(subject, sym=sym) details = self.get_fund_mess(self.financials, curr_price, self.earnings, self.sentiment, days_to_earnings, self.stocks) plt = self.show_sym_stats(sym, True) Utils.send_mm_mail(mess, details, plt) def get_subj_mess(self, subject, sym=None): mess = "" if self.stocks is None or sym != self.stocks.iloc[0].sym: self.stocks = self.ss.get_trend_slice(table_name=None, time_from="-120d", time_to="0d", symbol=sym) curr_price = self.stocks.iloc[-1].close # print(self.stocks) days_to_earnings = FinI.days_to_earnings(self.earnings) sector_mess, spy_mess, vol_mess = self.get_common_mess(self.stocks) mess = subject + " " + str(sym) + \ self.subject_fund_info(self.financials, self.sentiment, self.earnings, days_to_earnings = days_to_earnings) mess += str(sector_mess) mess += str(spy_mess) mess += str(vol_mess) self.stocks = FinI.add_levels(self.stocks) # hl = FinI.get_fib_hl(self.stocks, self.stocks.iloc[-1].close) pl = self.stocks.price_level.dropna() low, high = FinI.get_nearest_values(pl, curr_price) mess += " Price: " + str(curr_price) mess += " | Loss: " + str(Utils.calc_perc( curr_price, low[0])) + "%, " if low is not None and len(low) > 0 else "" mess += " " + "Prof.: " + str(Utils.calc_perc( curr_price, high[0])) + "% " if high is not None and len(high) > 0 else " | " print("get_subj_mess() - done") return mess, curr_price, days_to_earnings @staticmethod def get_fib_mess(df, close_price): mess = "" last_fib = -1 for col in df: if col.startswith('fb'): if close_price > last_fib and close_price < df.iloc[-1][col]: mess += str(Utils.calc_perc(close_price, last_fib)) + "% | " \ "Price: " + str(close_price) + \ " | " + str(Utils.calc_perc(close_price, df.iloc[-1][col])) + "% \n\r" mess += str(col) + ": " + str(round(df.iloc[0][col], 2)) + "\n\r" last_fib = df.iloc[-1][col] return mess def show_sym_stats(self, sym, save_img=False): # last financials if self.financials is not None and len(self.financials) > 0: self.financials = self.financials.tail(5) days_to_earnings = FinI.days_to_earnings(self.earnings) # print(earnings) if days_to_earnings is None: self.earnings = None plots_num = 4 if save_img else 5 fig, axs = plt.subplots(plots_num, 1, figsize=(16, 18)) PlotI.set_margins(plt) if self.spy is not None: PlotI.plot_spy( axs[0], self.spy.loc[self.spy.index.isin(self.stocks.index)]) axsp = PlotI.plot_stock_prices(axs[0].twinx(), self.stocks, sym, alpha=0.3) axsp = PlotI.plot_sma(axsp, self.stocks, ["sma9", "sma50"]) axsp = PlotI.plot_candles(self.stocks, axsp, body_w=0.5, shadow_w=0.1, alpha=0.5) axsp = PlotI.plot_fib(self.stocks, axsp, alpha=0.4) axsp = PlotI.plot_fib(self.stocks, axsp, alpha=0.4, fib_name="fb_mid") axsp = PlotI.plot_fib(self.stocks, axsp, alpha=0.4, fib_name="fb_bot") PlotI.plot_boll(axsp, self.stocks, sym) PlotI.plot_weeks(axsp, self.stocks) PlotI.plot_rsi(axs[1], self.stocks) ax_macd = PlotI.plot_macd_boll(axs[1].twinx(), self.stocks) # ax_macd = PlotI.plot_macd(ax_macd,dfp) PlotI.plot_volume_bars(axs[1].twinx(), self.stocks) if self.in_day_stocks is None: self.in_day_stocks = sdf.retype( self.db.load_data(TableName.MIN15, sym, time_from="-1d", time_to="0d")) if len(self.in_day_stocks) < 1: self.in_day_stocks = sdf.retype( self.db.load_data(TableName.MIN15, sym, limit=20)) # self.plot_volume(axs[2], last_prices) ax = PlotI.plot_candlesticks2(axs[2], self.in_day_stocks) self.in_day_stocks = FinI.add_fib_from_day_df(self.in_day_stocks, self.stocks) ax = PlotI.plot_fib(self.in_day_stocks, axs[2], alpha=0.4, fib_name="fb_mid") # PlotI.plot_boll(ax, last_prices, sym) sectors = self.ss.sectors_day_stats() PlotI.plot_sector_stats(axs[3], sectors, self.stocks.iloc[0].sector) if (save_img): return plt # self.plot_spy(axs[2], self.spy) #self.plot_yahoo_candles(last_prices) # self.plot_volume(axs[2], last_prices) # set rotation of tick labels axs[3].text(0.02, 0.9, str(self.financials.beta.name) + ' | ' + str(self.financials.beta.to_list()), fontsize=8) axs[3].text( 0.02, 0.8, str(self.financials.priceToSalesTrailing12Months.name) + ' | ' + str(self.financials.priceToSalesTrailing12Months.to_list()), fontsize=8) axs[3].text(0.02, 0.7, str(self.financials.enterpriseToRevenue.name) + ' | ' + str(self.financials.enterpriseToRevenue.to_list()), fontsize=8) axs[3].text(0.02, 0.6, str(self.financials.profitMargins.name) + ' | ' + str(self.financials.profitMargins.to_list()), fontsize=8) axs[3].text(0.02, 0.5, str(self.financials.enterpriseToEbitda.name) + ' | ' + str(self.financials.enterpriseToEbitda.to_list()), fontsize=8) axs[3].text(0.02, 0.4, str(self.financials.trailingEps.name) + ' | ' + str(self.financials.trailingEps.to_list()), fontsize=8) axs[3].text(0.02, 0.3, str(self.financials.forwardEps.name) + ' | ' + str(self.financials.forwardEps.to_list()), fontsize=8) axs[3].text(0.02, 0.2, str(self.financials.priceToBook.name) + ' | ' + str(self.financials.priceToBook.to_list()), fontsize=8) axs[3].text(0.02, 0.1, str(self.financials.bookValue.name) + ' | ' + str(self.financials.bookValue.to_list()), fontsize=8) axs[3].text(0.4, 0.9, str(self.financials.shortRatio.name) + ' | ' + str(self.financials.shortRatio.to_list()), fontsize=8) axs[3].text(0.4, 0.8, str(self.financials.sharesShortPriorMonth.name) + ' | ' + str(self.financials.sharesShortPriorMonth.to_list()), fontsize=8) axs[3].text(0.4, 0.7, str(self.financials.pegRatio.name) + ' | ' + str(self.financials.pegRatio.to_list()), fontsize=8) axs[3].text(0.4, 0.6, str(self.financials.earningsQuarterlyGrowth.name) + ' | ' + str(self.financials.earningsQuarterlyGrowth.to_list()), fontsize=8) axs[3].text(0.4, 0.5, str(self.financials.bid.name) + ' | ' + str(self.financials.bid.to_list()), fontsize=8) axs[3].text(0.4, 0.4, str(self.financials.trailingPE.name) + ' | ' + str(self.financials.trailingPE.to_list()), fontsize=8) axs[3].text(0.4, 0.3, str(self.financials.forwardPE.name) + ' | ' + str(self.financials.forwardPE.to_list()), fontsize=8) axs[3].text(0.4, 0.2, str(self.financials.industry.to_list()) + ' | ' + str(self.financials.sector.to_list()), fontsize=8) axs[3].text(0.4, 0.1, str(self.financials.heldPercentInstitutions.name) + ' | ' + str(self.financials.heldPercentInstitutions.to_list()) + ' ||| ' + str(self.financials.heldPercentInsiders.name) + ' | ' + str(self.financials.heldPercentInsiders.to_list()), fontsize=8) axs[3].text(0.6, 0.9, str(self.financials.fiftyDayAverage.name) + ' | ' + str(self.financials.fiftyDayAverage.to_list()), fontsize=8) axs[3].text(0.6, 0.7, str("Last CLose Price: ") + ' | ' + str(self.in_day_stocks.iloc[-1].close), fontsize=8) axs[3].text( 0.6, 0.5, str("Days to earn.: ") + ' | ' + str(days_to_earnings.days) + " D" if self.earnings is not None else str("Days to earn.: NaN "), fontsize=8) axs[3].text(0.6, 0.4, str("Earn. est. | act. | surp.: ") + str(self.earnings.iloc[-1].epsestimate) + ' | ' + str(self.earnings.iloc[-1].epsactual) + ' | ' + str(self.earnings.iloc[-1].epssurprisepct) if self.earnings is not None else str("Earn est.: NaN "), fontsize=8) axs[3].text(0.6, 0.3, str(" Sentiment article/title: ") + str(self.sentiment.sentiment_summary_avg.to_list()) + '/' + str(self.sentiment.sentiment_title_avg.to_list()) if self.sentiment is not None and len(self.sentiment) > 0 else str(" Sentiment: NaN "), fontsize=8) axs[3].text(0.02, 0.01, str(self.financials.longBusinessSummary.to_list()), fontsize=8) # self.plot_candlesticks(last_prices) # axs[3].plot([2], [1], 'o') # plt.text() # plt.show() return plt def subject_fund_info(self, financials, sentiment, earnings, days_to_earnings=None): mess = "" if len(financials) > 0: eps, pe = chi.eps_pe(financials) mess += ''.join([ " | ShortR: ", str(financials.iloc[-1].shortRatio), " | TrEps/FwdEps: ", str(eps) + "%", " | TrPE/FwdPE: ", str(pe) + "%", " | 50_DA_move: ", str( Utils.calc_perc(financials.iloc[0].fiftyDayAverage, financials.iloc[-1].fiftyDayAverage)) + "%", " | Beta: ", str(financials.iloc[0].beta), " | PriceToBook: ", str(financials.iloc[0].priceToBook), " | DividRate: ", str(financials.iloc[0].dividendRate) ]) if earnings is not None and len(earnings) > 0: mess += ''.join([ str(" | Earn. est./act./surp.: "), str(earnings.iloc[-1].epsestimate), '/', str(earnings.iloc[-1].epsactual) + '/', str(earnings.iloc[-1].epssurprisepct), "" ]) if days_to_earnings is not None: days_to_earnings = str(days_to_earnings).split(",") mess += ''.join([" | Earn :", str(days_to_earnings[0])]) if sentiment is not None and len(sentiment) > 0: mess += ''.join([ str(" | Sentiment article/title: "), str(sentiment.iloc[-1].sentiment_summary_avg), '/', str(sentiment.iloc[-1].sentiment_title_avg) if sentiment is not None and len(sentiment) > 0 else str("Sentiment: NaN ") ]) return mess # def plot_sectors(self, plt): # data = self.sectors_uptrend_by_month(yf=2021,yt=2021, show_chart = False) # plt = self.sector_stats_to_plt(self,plt, data) # return plt # def classify_sectors(self, time_from = "7d", table_name = "p_day", loosers = False): # stocks = self.classify_sectors_uptrend(table_name) # stocks = stocks.sort_values(by='flpd', ascending=loosers) # return stocks def create_sectors_trend_mess(self, sector): sector_mess = "" # if self.sectors_trend is None and len(self.sectors_trend) < 1: self.ss.set_spy_sectors_trend() sector0 = self.ss.sectors_trend[0][self.ss.sectors_trend[0].index == sector] sector1 = self.ss.sectors_trend[1][self.ss.sectors_trend[1].index == sector] if len(sector0) > 0 and len(sector1) > 0: sector_mess = " | " + str(sector) + ": " + str( round(sector0.iloc[0].flpd, 1)) + "% -> " + str( round(sector1.iloc[0].flpd, 1)) + "%" print("create_sectors_trend_mess() - done") return sector_mess def create_spy_trend_mess(self): spy_mess = "" if self.ss.spy_trend is not None and \ self.ss.spy_trend[0] is not None and \ len(self.ss.spy_trend) > 2 and \ len(self.ss.spy_trend[0]) > 0 and \ len(self.ss.spy_trend[1]) > 0: print(self.ss.spy_trend[0]) spy_mess = " | SPY: " + str( round(self.ss.spy_trend[0].flpd.mean(), 2)) + "% -> " + str( round(self.ss.spy_trend[1].flpd.mean(), 2)) + "%" else: spy_mess = "No Data" return spy_mess def get_common_mess(self, stocks): # print(stocks.iloc[0].sector) vol_mess = vol_perc = spy_mess = sector_mess = "" if stocks is not None and len(stocks) > 0: sector_mess = self.create_sectors_trend_mess(stocks.iloc[0].sector) if stocks is not None and "boll" in stocks: vol_perc = Utils.calc_perc(stocks.iloc[-1].boll, stocks.iloc[-1].boll_ub) vol_mess = " | Vlt: " + str(vol_perc) + "% " else: vol_perc = 0 spy_mess = self.create_spy_trend_mess() print("get_common_mess() - done") return sector_mess, spy_mess, vol_mess def get_fund_mess(self, financials, curr_price, earnings, sentiment, days_to_earnings, day_stocks=None): mess = "" mess += ''.join("Detail | ") financials.sort_values(by=["date"], inplace=True, ascending=True) if len(financials) > 0: cols = [ "date", "shortRatio", "sharesShortPriorMonth", "fiftyDayAverage", "beta", "dividendRate", "exDividendDate", "priceToSalesTrailing12Months", "enterpriseToRevenue", "profitMargins", "enterpriseToEbitda", "trailingEps", "forwardEps", "priceToBook", "bookValue", "pegRatio", "earningsQuarterlyGrowth", "bid", "volume", "trailingPE", "forwardPE", "heldPercentInstitutions", "heldPercentInsiders" ] mess += ''.join([ "T_EPS->F_EPS: ", str( Utils.calc_perc(financials.iloc[0].trailingEps, financials.iloc[0].forwardEps)), "%\n\r", "T_PE->F_PE: ", str( Utils.calc_perc(financials.iloc[0].trailingPE, financials.iloc[0].forwardPE)) + "%\n\r" ]) for item in cols: # financials[item].dropna(inplace=True) first = financials.iloc[0][item] last = financials.iloc[-1][item] mess += ''.join([ item + ": ", str(Utils.human_format(first)), " -> ", str(Utils.human_format(last)), " | ", str(Utils.calc_perc(first, last)), "%\n\r", ]) mess += ''.join([ str(financials.iloc[0].sector), ' | ', str(financials.iloc[0].industry), "\n\r", str("Current Price: "), ' | ', str(curr_price), "\n\r", str("Days to earn.: "), ' | ', str(days_to_earnings), " D", "\n\r" ]) if earnings is not None and len(earnings) > 0: mess += str("Earn. est. | act. | surp.: ") + str(earnings.iloc[-1].epsestimate) + \ ' | ' + str(earnings.iloc[-1].epsactual) + \ ' | ' + str(earnings.iloc[-1].epssurprisepct) + "\n\r" if sentiment is not None and len(sentiment) > 0: mess += str("Sentiment article/title: ") + str(sentiment.sentiment_summary_avg.to_list()) + \ '/' + str(sentiment.sentiment_title_avg.to_list()) if sentiment is not None and len(sentiment)>0 else str("Sentiment: NaN ") + "\n\r" if financials is not None and len(financials) > 0: mess += str(financials.iloc[0].longBusinessSummary) + "\n\r" sector_mess, spy_mess, vol_mess = self.get_common_mess(self.stocks) mess += "\n\r" + sector_mess mess += "\n\r" + spy_mess mess += "\n\r" + vol_mess hl = FinI.get_fib_hl(self.stocks, curr_price) mess += "\n\r" + "Loss: " + str(Utils.calc_perc(curr_price, hl["l"])) + "% " + " " + str(hl['l']) +" | "+\ " Price: " + str(curr_price) + \ " | " + "Profit: " + str(hl['h']) + \ " " + str(Utils.calc_perc(curr_price, hl["h"])) + "% \n\r" mess += self.get_fib_mess(self.stocks, curr_price) + "\n\r" print("get_fund_mess() - done") return mess def set_fundamentals(self, sym, last_date=None, tf={ "e": "-5d", "s": "-20d", "f": "-30d" }, tt={ "e": "14d", "s": "2d", "f": "0d" }): if last_date: self.db.last_date = last_date print("set_fund_mess() - done") self.earnings, self.sentiment, self.financials = self.db.get_fundamentals( sym=sym, tf=tf, tt=tt) def set_prices(self, sym=None, last_date=None, time_from="-90d", time_to="0d"): if last_date: self.db.last_date = last_date self.in_day_stocks = sdf.retype(self.db.get_last_n_days(sym)) self.stocks = sdf.retype( self.db.load_data(TableName.DAY, sym, time_from=time_from, time_to=time_to)) self.stocks = FinI.add_indicators(sdf.retype(self.stocks)) self.stocks = FinI.add_fib(self.stocks, last_rows=10) self.spy = sdf.retype( self.db.load_data(TableName.DAY, ["SPY"], time_from=time_from, time_to=time_to)) print("set_prices() - done")
class SlBt(): selected_stock = None timetick = None time_from = None time_to = None selected = {} action_type = None types = ["sector-stats", "stock-detail", "stocks-stats"] bs = BuySell() db = Database() sm = StockMess() sw = StockWhisperer() submit = None warning_check_list = [] bt_day_gain = {} dft = pd.DataFrame() def __init__(self): self.symbols = self.db.get_symbols(TableName.DAY) self.sectors = self.db.get_sectors(TableName.DAY) self.app = self.get_home_page() # self.fig = None # logging.info(self.df) # def load_data(self, option, time_from = "-180d", time_to = None): # df = self.db.load_data( # "p_day", symbols=option, time_from=time_from, time_to = time_to) # df = FinI.add_indicators(sdf.retype(df)) # return df def testing_mess(self): self.sm.stocks = self.db.load_data( table_name=TableName.DAY, symbols=["PLUG"], time_from=self.time_from, time_to=self.time_to, ) self.sm.get_subj_mess("Base Fund: ", "PLUG") def get_home_page(self): # logging.info(st) st.set_page_config(layout="wide") self.hide_footer() self.left_menu() # self.testing_mess() self.action_router() def left_menu(self): self.time_from = st.sidebar.text_input("Time from now -1m, -1h, -1d,", value="-120d") self.time_to = st.sidebar.text_input("Time to 1m, 1h, 1d,") self.portfolio = st.sidebar.text_input( 'Portfolio', value='GPS,FCX,CYH,VALE,F,AMAT,MU,ABT,HIMX,SBSW') self.selected_stock = st.sidebar.selectbox('Select stock', self.symbols) # if self.selected_stock == 0: # self.selected_stock = "TSLA" def action_router(self): if st.sidebar.button('test buy'): self.buy_alg() if st.sidebar.button('Machine learning'): self.prepare_data_for_ml() if st.sidebar.button('Portfolio opt'): self.portfolio_opt() if st.sidebar.button('Up-down stats'): self.up_down_stats() if st.sidebar.button('Logistic regresion'): self.logistic_regresion() if st.sidebar.button('L.R. Find Best Buy Candidate'): self.lr_best_candidate() def lr_best_candidate(self): df_best_buy = pd.DataFrame() symbols = self.db.get_symbols() for sym in symbols: try: st.write(f"filling: {sym}") df_lr_raw = self.logistic_regression_raw(sym) df_best_buy = df_best_buy.append(df_lr_raw.tail(1)) except Exception as e: st.write(e) st.dataframe(df_best_buy.sort_values(by="prob_1")) def logistic_regression_raw(self, symbol="SPY"): #TODO finish thos functioo for find best buy for stock with best Linear Regression probability params df = self.db.load_data(table_name=TableName.DAY, time_from=self.time_from, symbols=[symbol]) # m_df_spy = self.db.load_data( # table_name=TableName.DAY, time_from=self.time_from, symbols=["SPY"]) df['open-close'] = df['close'] - df['open'].shift(1) df['close-close'] = df['close'].shift(-1) - df['close'] # wrong close close only for research df['close-close-prev'] = df['close'] - df['close'].shift(1) df['S_9'] = df['close'].rolling(window=9).mean() df['S_20'] = df['close'].rolling(window=20).mean() # df['S_50'] = df['close'].rolling(window=50).mean() # df['S_200'] = df['close'].rolling(window=200).mean() df['Corr_9'] = df['close'].rolling(window=9).corr(df['S_9']) df['Corr_20'] = df['close'].rolling(window=9).corr(df['S_20']) df['RSI'] = ta.momentum.rsi(close=df['close']) y = np.where(df['close'].shift(-1) > df['close'], 1, -1) df = df[["Corr_9", "open-close", "close-close-prev", "RSI", "S_9"]] df = df.dropna() X = df.iloc[:, :30] # st.write(len(y)) # st.write(len(X)) split = int(0.7 * len(df)) X_train, X_test, y_train, y_test = X[:split], X[split:], y[:split], y[ split:] # We will instantiate the logistic regression in Python using ‘LogisticRegression’ # function and fit the model on the training dataset using ‘fit’ function. model = LogisticRegression() model = model.fit(X_train, y_train) # Examine coeficients # pd.DataFrame(zip(X.columns, np.transpose(model.coef_))) # st.write("Examine The Coefficients") # st.write(pd.DataFrame(zip(X.columns, np.transpose(model.coef_)))) #We will calculate the probabilities of the class for the test dataset using ‘predict_proba’ function. probability = model.predict_proba(X_test) df['Predicted_Signal'] = model.predict(X) df = df.tail(len(probability)) df["prob_0"] = probability[:, 0] df["prob_1"] = probability[:, 1] df["sym"] = symbol return df def logistic_regresion(self, symbols=None): if symbols is None: symbols = [self.selected_stock] # LOGISTIC REGRESSION sucesfully finish this logic st.write(f"Logistic regression: {self.selected_stock}") df = self.db.load_data(table_name=TableName.DAY, time_from=self.time_from, symbols=symbols) m_df_spy = self.db.load_data(table_name=TableName.DAY, time_from=self.time_from, symbols=["SPY"]) df_best_buy = pd.DataFrame() df_lr_raw = self.logistic_regression_raw() st.write("logistic regression RAW SPY") st.dataframe(df_lr_raw) # remove volume, industry, symbol cols # df = df.iloc[:,:4] # df = df.dropna() # df = df.iloc[:, :4] # df = df.retype(spy) df['open-close'] = df['close'] - df['open'].shift(1) df['close-close'] = df['close'].shift(-1) - df['close'] # wrong close close only for research df['close-close-prev'] = df['close'] - df['close'].shift(1) # df['close-close-1'] = df['close'] - df['close'].shift(1) # df['close-close-2'] = df['close'].shift(1) - df['close'].shift(2) # df['close-close-3'] = df['close'].shift(2) - df['close'].shift(3) # df['close-close-4'] = df['close'].shift(3)- df['close'].shift(4) df, m_df_spy = FinI.get_sizes(df, m_df_spy) # df = FinI.add_weekday(df) # df = FinI.add_week_of_month(df) df = FinI.add_yearweek(df) # df = FinI.add_levels(df) # only first nine rows be aware of this # df = FinI.add_indicators(df) # df["MACD"] = ta.trend.macd(close=df['close']) # df['S_9'] = df['close'].rolling(window=9).mean() # df['S_20'] = df['close'].rolling(window=20).mean() # df['S_50'] = df['close'].rolling(window=50).mean() # df['Corr'] = df['close'].rolling(window=10).corr(df['S_9']) # df['RSI'] = ta.momentum.rsi(close= df['close'], n=9) # Initialize Bollinger Bands Indicator # Add Bollinger Bands features # df['bb_bbm'] = indicator_bb.bollinger_mavg() # df['bb_bbh'] = indicator_bb.bollinger_hband() # df['bb_bbl'] = indicator_bb.bollinger_lband() df['S_9'] = df['close'].rolling(window=9).mean() df['S_20'] = df['close'].rolling(window=20).mean() # df['S_50'] = df['close'].rolling(window=50).mean() # df['S_200'] = df['close'].rolling(window=200).mean() df['Corr_9'] = df['close'].rolling(window=9).corr(df['S_9']) df['Corr_20'] = df['close'].rolling(window=9).corr(df['S_20']) df['RSI'] = ta.momentum.rsi(close=df['close']) # df["MACD"] = ta.trend.macd(close=df['close']) df = df.fillna(0) st.write("Correlation Matrix - Heatmap") self.get_heatmap(df) # remove open, high, low # df = df.iloc[:,3:] y = np.where(df['close'].shift(-1) > df['close'], 1, -1) st.write("Rows:") st.write(len(df)) # df = df.drop(columns= ["date", # "yearweek", # "size_boll_ub", # "size_boll_lb", # "size_boll", # "up_down_row", # "green_red_row", # "price_level", # "weekday", # "boll", # "sma9", # "close_20_sma", # "size_top", # "size_btm", # "close_20_mstd", # "size_top-2", # "size_top-1", # "size_btm-2", # "size_btm-1", # "boll_ub", # "boll_lb", # "size_btm-3", # "size_top-3", # "size_sma9", # "size_sma20", # "sma20", # "open", # "close", # "high", # "low", # "size_body-1", # "size_body-2", # "size_body-3", # "week_in_month", # "size_body", # "size_prev_chng", # "symbol", # "sector", # "sym", # "industry", # "amount", # "volume", # "open-close", # "close-close" # ]) df_strategy = df.copy() # relatively good negative prediction # df = df[["size_sma9"]] # values by corelation matrix # df = df[["size_sma20","size_sma9","up_down_row"]] # df = df[["green_red_row", "size_sma9", "up_down_row", "size_body"]] # df = df[["green_red_row", "size_sma9", "up_down_row", "size_body","volume"]] # origin # df = df[["Corr_9","Corr_20", "open-close", "close-close-prev", "RSI","sma9"]] df = df[["Corr_9", "open-close", "close-close-prev", "RSI", "sma9"]] # overnight, negative precision # df = df[["green_red_row", "size_body-1","size_body-2","size_body-3", "size_prev_chng","weekday"]] # df = df[["close", "sma9", "sma20"]] st.write("Dataframe") st.dataframe(df) X = df.iloc[:, :30] st.write(len(y)) st.write(len(X)) # split to test dataset split = int(0.7 * len(df)) X_train, X_test, y_train, y_test = X[:split], X[split:], y[:split], y[ split:] # We will instantiate the logistic regression in Python using ‘LogisticRegression’ # function and fit the model on the training dataset using ‘fit’ function. model = LogisticRegression() model = model.fit(X_train, y_train) # Examine coeficients pd.DataFrame(zip(X.columns, np.transpose(model.coef_))) st.write("Examine The Coefficients") st.write(pd.DataFrame(zip(X.columns, np.transpose(model.coef_)))) #We will calculate the probabilities of the class for the test dataset using ‘predict_proba’ function. st.write("probability") probability = model.predict_proba(X_test) st.write(probability) st.write("predicted") predicted = model.predict(X_test) st.write(predicted) st.write("Y test") st.write(y_test) st.write(len(X_test)) st.write("Confusion matrix") conf_matrix = metrics.confusion_matrix(y_test, predicted) st.write(conf_matrix) st.write("classification report") st.write(metrics.classification_report(y_test, predicted)) st.write("model accuracy") st.write(model.score(X_test, y_test)) st.write("cross validation accuracy") cross_val = cross_val_score(LogisticRegression(), X, y, scoring='accuracy', cv=10) st.write(cross_val) st.write(cross_val.mean()) st.write("Trading Strategy") df['Predicted_Signal'] = model.predict(X) st.write("Predicted signals") st.dataframe(df) #STRARTEGY count st.dataframe(df_strategy) # df_strategy = df_strategy.tail(len(df_strategy) - split) df_strategy["Predicted_Signal"] = model.predict(X) price_change = df_strategy.iloc[len(df_strategy) - 1].close - df_strategy.iloc[0].close st.write("Perfect gain") df_strategy["perfect_gain"] = df_strategy["close-close"].where( df_strategy["close-close"] > 0).sum() st.write(df_strategy["perfect_gain"].iloc[0]) st.write("Invest Gain") st.write(price_change) st.write("L.G. gain") df_strategy["lg_gain"] = df_strategy["close-close"].where( df_strategy["Predicted_Signal"] > 0).sum() st.write(df_strategy["lg_gain"].iloc[0]) gap = -2 st.write("sma9 gain: " + str(gap)) df_strategy["sma9_gain"] = df_strategy["close-close"].where( df_strategy["size_sma9"] > gap).sum() st.write(df_strategy["sma9_gain"].iloc[0]) st.write("sma9 gain 0") df_strategy["sma9_gain"] = df_strategy["close-close"].where( df_strategy["size_sma9"] > 0).sum() st.write(df_strategy["sma9_gain"].iloc[0]) st.write("sma20 gain") df_strategy["sma20_gain"] = df_strategy["close-close"].where( df_strategy["size_sma20"] > -2).sum() st.write(df_strategy["sma20_gain"].iloc[0]) # df['Nifty_returns'] = np.log(df['close']/df['close'].shift(1)) # Cumulative_Nifty_returns = np.cumsum(df[split:]['Nifty_returns']) # df['Startegy_returns'] = df['Nifty_returns']* df['Predicted_Signal'].shift(1) # Cumulative_Strategy_returns = np.cumsum(df[split:]['Startegy_returns']) # st.line_chart(Cumulative_Nifty_returns) # st.line_chart(Cumulative_Strategy_returns) def up_down_stats(self): m_df = self.db.load_data(table_name=TableName.DAY, time_from=self.time_from, symbols=[self.selected_stock]) m_df_spy = self.db.load_data(table_name=TableName.DAY, time_from=self.time_from, symbols=["SPY"]) m_df, m_df_spy = FinI.get_sizes(m_df, m_df_spy) self.candle_chart(m_df, m_df_spy) # above_sma9, under_sma9, above_boll,under_boll = {"1":0,"2":0,"3":0,"4":0,"5":0,"6":0} ind = pd.DataFrame() ws = pd.DataFrame() u = 0 pred = pd.DataFrame() for index, row in m_df.iterrows(): if row.weekday == 0: i = 1 while m_df.iloc[ m_df.index.get_loc(index) + i].weekday == m_df.iloc[m_df.index.get_loc(index) + 1 + i].weekday - 1: rw = m_df.iloc[m_df.index.get_loc(index) + i] st.write(str(rw.date) + " - " + str(rw.size_body)) i += 1 st.write(row.week_in_month) if True or row.size_sma9 > 0 and row.size_boll > 0: if row.size_body > 0: # st.write(u) if u < 0: ind = ind.append([u]) u = 0 u += 1 elif row.size_body < 0: if u > 0: ind = ind.append([u]) # st.write(ind) u = 0 u -= 1 # st.dataframe(ind) st.dataframe(ind.groupby(ind.columns[0]).size()) # def get_size_data(self, stocks = None): # if stocks is None: # stocks = self.selected_stock # m_df = self.db.load_data( # table_name=TableName.DAY, time_from=self.time_from, symbols=[stocks]) # m_df_spy = self.db.load_data( # table_name=TableName.DAY, time_from=self.time_from, symbols=["SPY"]) # m_df_spy["oc_mean"] = ((m_df_spy.close + m_df_spy.open)/2) # m_df = sdf.retype(m_df) # m_df.get("boll") # m_df = FinI.add_sma(9, m_df) # m_df = FinI.add_weekday(m_df) # m_df = FinI.add_week_of_month(m_df) # m_df = FinI.add_levels(m_df) # m_df["size_top"] = m_df.apply(lambda row: Utils.calc_perc( # row.open, row.high) if row.open > row.close else Utils.calc_perc(row.close, row.high), axis=1) # m_df["size_btm"] = m_df.apply(lambda row: Utils.calc_perc( # row.low, row.close) if row.open > row.close else Utils.calc_perc(row.low, row.open), axis=1) # m_df["size_body"] = m_df.apply(lambda row: Utils.calc_perc(row.open, row.close), axis=1) # m_df["size_sma9"] = m_df.apply(lambda row: Utils.calc_perc(row.sma9, row.close), axis=1) # m_df["size_boll"] = m_df.apply( # lambda row: Utils.calc_perc(row.boll, row.close), axis=1) # m_df["size_boll_ub"] = m_df.apply( # lambda row: Utils.calc_perc(row.boll_ub, row.close), axis=1) # m_df["size_boll_lb"] = m_df.apply( # lambda row: Utils.calc_perc(row.boll_lb, row.close), axis=1) # m_df["size_top-1"] = m_df.shift(1).size_top # m_df["size_btm-1"] = m_df.shift(1).size_btm # m_df["size_body-1"] = m_df.shift(1).size_body # m_df["size_top-2"] = m_df.shift(2).size_top # m_df["size_btm-2"] = m_df.shift(2).size_btm # m_df["size_body-2"] = m_df.shift(2).size_body # m_df["size_top-3"] = m_df.shift(3).size_top # m_df["size_btm-3"] = m_df.shift(3).size_btm # m_df["size_body-3"] = m_df.shift(3).size_body # m_df["size_prev_chng"] = ( # m_df.open - m_df.shift(1).close) / (m_df.shift(1).close/100) # return m_df, m_df_spy def prepare_data_for_ml(self): m_df = self.db.load_data(table_name=TableName.DAY, time_from=self.time_from, symbols=[self.selected_stock]) m_df_spy = self.db.load_data(table_name=TableName.DAY, time_from=self.time_from, symbols=["SPY"]) m_df, m_df_spy = FinI.get_sizes(m_df, m_df_spy) st.dataframe(m_df) self.process_data(m_df) self.candle_chart(m_df, m_df_spy) self.show_sizes(m_df) self.get_heatmap(m_df) self.nn_pred(m_df) def show_sizes(self, df): sets = [{ 'x': df.index, 'y': df.size_body, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'blue' }, 'name': 'body' }] sets += [{ 'x': df.index, 'y': df.size_prev_chng, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'green' }, 'name': 'prev day' }] sets += [{ 'x': df.index, 'y': df.weekday, 'type': 'scatter', 'mode': 'lines+markers', 'line': { 'width': 1, 'color': 'brown' }, 'name': 'weeks' }] sets += [{ 'x': df.index, 'y': df.week_in_month, 'type': 'scatter', 'mode': 'lines+markers', 'line': { 'width': 1, 'color': 'orange' }, 'name': 'weeks' }] fig = make_subplots(rows=1, cols=1, shared_xaxes=True, vertical_spacing=0.009, horizontal_spacing=0.009, row_width=[0.5], specs=[[{ "secondary_y": True }]]) fig.add_traces(data=sets, cols=1, rows=1) fig.update_yaxes(showgrid=True, zeroline=False, showticklabels=True, showspikes=True, spikemode='across', spikesnap='cursor', showline=True, spikedash='dash', spikethickness=0.5) fig.update_xaxes(showgrid=True, zeroline=False, rangeslider_visible=False, showticklabels=True, showspikes=True, showline=True, spikemode='across', spikesnap='cursor', spikedash='dash', spikethickness=0.5) fig.update_layout(autosize=True, height=600, hoverdistance=1, hovermode='x', spikedistance=1000) st.plotly_chart( fig, use_container_width=True, use_container_height=True, template="plotly_dark", ) def get_heatmap(self, df): # fig = px.imshow( df, # x= ["size_body", "size_btm", "size_top", "size_body-1", "size_top-1", "size_btm-1", "size_prev_chng"], # y=["size_body", "size_btm", "size_top", "size_body-1", "size_top-1", "size_btm-1", "size_prev_chng"], # ) # fig = px.scatter_matrix(df) # fig.show() df_c = pd.DataFrame( df, columns=[ "size_body", "size_prev_chng", "weekday", "week_in_month", "size_btm", "size_top", "size_body-1", "size_top-1", "size_btm-1", "size_body-2", "size_top-2", "size_btm-2", "size_body-3", "size_top-3", "size_btm-3", "size_sma9", "size_sma20", "size_boll", "size_boll_ub", "size_boll_lb", "green_red_row", "up_down_row" ]) st.write(df_c.corr()) def portfolio_opt(self): portfolio = self.portfolio.split(",") df = self.db.load_data(TableName.DAY, time_from=self.time_from, symbols=portfolio) # df = FinI.add_date_col(df) df = df[["close", "sym"]] df2 = df.copy() df2 = df2.drop(columns=["close", "sym"]) for sym in portfolio: df2[sym] = df[df["sym"] == sym]["close"] df2 = df2.drop_duplicates() # df = df.transpose() # df.index = pd.to_datetime(df['date']).astype(int) / 10**9 st.write(df2) # Calculate expected returns and sample covariance mu = expected_returns.mean_historical_return(df2) S = risk_models.sample_cov(df2) # Optimize for maximal Sharp ratio ef = EfficientFrontier(mu, S) raw_weights = ef.max_sharpe() cleaned_weights = ef.clean_weights() # ef.save_weights_to_file("weights.csv") # saves to file st.write(cleaned_weights) mu, sigma, sharpe = ef.portfolio_performance(verbose=True) st.write("Expected annual return: {:.1f}%".format(100 * mu)) st.write("Annual volatility: {:.1f}%".format(100 * sigma)) st.write("Sharpe Ratio: {:.2f}".format(sharpe)) def process_data(self, m_df): from sklearn import datasets from sklearn.neighbors import KNeighborsClassifier knn = KNeighborsClassifier(n_neighbors=6) # knn.fit(m_df.iloc[0,len(m_df/2)], m_df[len(m_df)/2,len(m_df)]) def nn_pred(self, df): # st.dataframe(df[["close"]]) #Number of neurons in the input, output, and hidden layers stock_data = df[["close"]] lstm = MarketLSTM(stock_data) # stock_data["seconds"] = stock_data.apply(lambda row: row.index.astype(int) / 10**9) # stock_data = stock_data[["seconds", "close"]] # stock_data = scale(stock_data) # #gets the price and dates from the matrix # prices = stock_data[:, 1].reshape(-1, 1) # dates = stock_data[:, 0].reshape(-1, 1) # chart_data = pd.DataFrame([dates[:,0],prices[:,0]]) # chart_data = chart_data.transpose() # self.nn_train(dates,prices) def nn_train(self, dates, prices): pass def nn_train_OLD(self, dates, prices): input = 1 output = 1 hidden = 50 #array of layers, 3 hidden and 1 output, along with the tanh activation function layers = [('F', hidden), ('AF', 'tanh'), ('F', hidden), ('AF', 'tanh'), ('F', hidden), ('AF', 'tanh'), ('F', output)] #construct the model and dictate params mlpr = ANNR([input], layers, batchSize=256, maxIter=20000, tol=0.2, reg=1e-4, verbose=True) #number of days for the hold-out period used to access progress holdDays = 5 totalDays = len(dates) #fit the model to the data "Learning" mlpr.fit(dates[0:(totalDays - holdDays)], prices[0:(totalDays - holdDays)]) # stocks_day["sym"] = stocks_day["sym"].astype('category') def candle_chart(self, df, m_df_spy): sets = [{ 'x': df.index, 'open': df.open, 'close': df.close, 'yaxis': "y1", 'high': df.high, 'low': df.low, "hovertext": "", 'type': 'candlestick', "opacity": 1, 'line': { 'width': 0.5, } }] sets += [{ 'x': df.index, 'y': df.boll_ub, 'type': 'scatter', 'yaxis': "y1", 'mode': 'lines', 'line': { 'width': 1, 'color': 'green' }, 'name': 'Boll UP' }] sets += [{ 'x': df.index, 'y': df.boll, 'yaxis': "y1", 'type': 'scatter', "fill": 'tonexty', 'line': { 'width': 0, }, "fillcolor": 'rgba(128, 255, 128,0.2)' }] sets += [{ 'x': df.index, 'y': df.boll_lb, 'type': 'scatter', 'yaxis': "y1", 'mode': 'lines', 'line': { 'width': 1, 'color': 'green' }, 'name': 'Boll Down' }] sets += [{ 'x': df.index, 'y': df.boll, 'yaxis': "y1", 'type': 'scatter', "fill": 'tonexty', 'line': { 'width': 0, }, "fillcolor": 'rgba(255, 128, 128,0.2)' }] sets += [{ 'x': df.index, 'y': df.boll_ub, 'type': 'scatter', 'yaxis': "y1", 'mode': 'lines', 'line': { 'width': 1, 'color': 'green' }, 'name': 'Boll UP' }] sets += [{ 'x': df.index, 'y': df.sma9, 'type': 'scatter', 'yaxis': "y1", 'mode': 'lines', 'line': { 'width': 1, 'color': 'blue' }, 'name': 'Boll Down' }] for i, r in df.iterrows(): if r.price_level is not None: sets += [{ 'x': [r.date, df.iloc[-1].date], 'y': [r.price_level, r.price_level], 'type': 'scatter', 'yaxis': "y1", 'mode': 'lines', 'line': { 'width': 1, 'color': 'brown', "dash": "dot" }, 'name': '' }] fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.009, horizontal_spacing=0.009, row_width=[0.1, 0.5], specs=[[{ "secondary_y": True }], [{ "secondary_y": True }]]) fig.add_traces(data=sets, cols=1, rows=1) # sets = [] fig.add_trace( { 'x': m_df_spy.index, 'y': m_df_spy.oc_mean, 'type': 'scatter', 'yaxis': "y2", 'mode': 'lines', 'line': { 'width': 1, 'color': 'red' }, 'name': 'SPY' }, 1, 1, secondary_y=True, ) df.loc[df.open > df.close, "vol_color"] = "red" df.loc[df.open <= df.close, "vol_color"] = "green" fig.add_trace( { 'x': df.index, 'y': df.volume, 'type': 'bar', 'name': 'Volume', 'marker_color': df.vol_color }, 2, 1, secondary_y=False, ) fig.update_yaxes(showgrid=True, zeroline=False, showticklabels=True, showspikes=True, spikemode='across', spikesnap='cursor', showline=True, spikedash='dash', spikethickness=0.5) fig.update_xaxes(showgrid=True, zeroline=False, rangeslider_visible=False, showticklabels=True, showspikes=True, showline=True, spikemode='across', spikesnap='cursor', spikedash='dash', spikethickness=0.5) fig.update_layout(autosize=True, height=600, hoverdistance=1, hovermode='y', spikedistance=10000) st.plotly_chart( fig, use_container_width=True, use_container_height=True, template="plotly_dark", ) def buy_alg(self, stats_time=None): if stats_time is None: stats_time = "-60d" backtest_time = "-14d" self.db.last_date = self.db.get_date_format(backtest_time) spy = self.db.load_data(table_name=TableName.DAY_FS, symbols=["SPY"], time_from=stats_time) # spy = sdf.retype(spy) # spy = FinI.add_indicators(spy) stocks_day = self.db.load_data(table_name=TableName.DAY_FS, time_from=stats_time) stocks_day["sym"] = stocks_day["sym"].astype('category') stocks_15 = self.db.load_data(table_name=TableName.MIN15, time_from=backtest_time) stocks_15["sym"] = stocks_15["sym"].astype('category') spy_15 = stocks_15[stocks_15["sym"] == "SPY"] # logging.info(spy) symbols = self.db.get_symbols() # for testing performance reason here are only few stocks symbols = [ "INTC", "BYND", "ZM", "NKE", "HIMX", "JKS", "ENPH", "DUK", "GE", "DIS", "LEVI", "NVAX", "SLCA", "GPS" ] # iterate over days in market spy2 = spy.tail(20) # retype to stocks dataframe if not isinstance(stocks_day, sdf): stocks_day = sdf.retype(stocks_day) for index, spy_row_day in spy2.iterrows(): st.write("spy: " + str(spy_row_day)) st.write("DATE" + str(index)) for symbol in symbols: # load stocks for stats stocks_day_sym = stocks_day[stocks_day["sym"] == symbol] # stocks_day_sym = FinI.add_indicators(stocks_day_sym) # stocks_day_sym = FinI.add_sma(9, stocks_day_sym) # stocks_day_sym = FinI.add_sma(50, stocks_day_sym) # stocks_day_sym.get('boll') # stocks_day_sym.get('volume_delta') # stocks_day_sym.get('macd') # stocks_day_sym.get('kdjk') # stocks_day_sym.get('open_-2_r') # logging.info(" ------------------------------------------------- --------------") # logging.info(stocks_day_sym) # stocks_day_sym = FinI.add_day_types(stocks_day_sym) # stocks_day_sym = FinI.add_levels(stocks_day_sym) stocks_15_sym = stocks_15[stocks_15["sym"] == symbol] stock_rows15 = stocks_15_sym.loc[ stocks_15_sym.index <= pytz.utc.localize(index)] # logging.info(stock_rows15.iloc[-1].sym + " | " + str(stock_rows15.index[-1])) if len(stock_rows15) > 1: self.back_buy_best_stock(stocks_day_sym, index) # st.write((stock_rows15.iloc[-1].sym + " | " + str(stock_rows15.index[-1]))) logging.info(stock_rows15.iloc[-1].sym + " | " + str(stock_rows15.index[-1])) self.buy_sell(stocks_day_sym, stock_rows15, spy, spy_15, spy_row_day) st.write(self.dft) def back_buy_best_stock(self, df, index, days_back=-2): # self.bt_day_gain[index] df2 = pd.DataFrame() if df is not None and len(df) > 0: dff = df[df.index <= index] if len(dff) > 1: gain = Utils.calc_perc(dff.iloc[days_back].close, dff.iloc[-1].close) df2 = dff.iloc[days_back] df2["gain"] = gain df2["days_back"] = days_back self.dft = self.dft.append(df2) # st.write(self.dft) def set_mess_data(self, fin=None, sen=None, earn=None, spy=None, stc=None): if earn is not None: self.sm.earnings = earn if fin is not None: self.sm.financials = fin if sen is not None: self.sm.sentiment = sen if spy is not None: self.sm.spy = spy # if stc_d is not None: # self.sm.in_day_stocks if stc is not None: self.sm.stocks = stc def buy_sell(self, stocks_day, stocks_15, spy, spy_row15, spy_row_day): """ By sell backtrading simaltion with specific strategy Args: stocks_day ([type]): [description] stocks_15 ([type]): [description] spy ([type]): [description] spy_row15 ([type]): [description] spy_row_day ([type]): [description] """ # self.stocks = self.stocks.append(stocks_day.iloc[-1]) self.db.last_date = stocks_15.iloc[-1].name logging.info(self.db.last_date) sym = stocks_day.iloc[-1].sym # send only one buy suggestion per day hash_warn = hash(sym + str(stocks_15.index[-1].strftime("%d/%m/%Y"))) hl = FinI.get_fib_hl(stocks_day, stocks_day.iloc[-1].close) # logging.info(str(stocks_day)) if len(stocks_day) > 1: # stocks_day = sdf.retype(stocks_day) # stocks_day = FinI.add_indicators(stocks_day) stocks_day.sort_index(ascending=True, inplace=True) stocks_day["flpd"] = Utils.calc_flpd(stocks_day) hl = FinI.get_fib_hl(stocks_day, stocks_15.iloc[-1].close) #OLD CHECK SELL moved to this Fce # self.check_sell(stocks_15.iloc[-1]) earnings, sentiment, financials = self.db.get_fundamentals( stocks_day.iloc[-1]["sym"]) self.set_mess_data(fin=financials, sen=sentiment, earn=earnings, spy=spy, stc=stocks_day) # st.write("BUYSELL OPEN trades amount:" + str(len(self.bs.buy_sell_open))) #-----------------------------SELL------------------------------------------ if len(self.bs.buy_sell_open) > 0: logging.info("not selled stocks:" + str(self.bs.buy_sell_open[ self.bs.buy_sell_open.state == "open"])) logging.info("Current SYM: " + str(stocks_15.iloc[-1].sym)) bs = self.bs.buy_sell_open[self.bs.buy_sell_open.sym == stocks_15.iloc[-1].sym] if len(bs) > 0: st.write( "--------------------SELLING----------------------------" ) for index, row in bs.iterrows(): if Utils.calc_perc(stocks_15.iloc[-1].close, hl["h"], 2) <= 1 or \ chi.check_sma9(stocks=stocks_day, live_stocks=stocks_15, buy=False): # self.bs.buy_sell_open[(self.bs.buy_sell_open.sym == stocks_15.iloc[-1].sym) & (self.bs.buy_sell_open.state == "open")] = self.bs.sell_stock_t(stocks_15.iloc[-1], sell_price=stocks_15.iloc[-1].close, sold_stock = self.bs.sell_stock_t( sym=stocks_15.iloc[-1].sym, price=stocks_15.iloc[-1].close, sell_date=stocks_15.iloc[-1].name) st.write(sold_stock) # st.write(sym + " | Selling Profit: " + str(stocks_15.iloc[-1].sym) + " | " + str(stocks_15.index[-1]) + " | " + # " | B.S.:" + str(row["buy"]) + "/" + str(stocks_15.iloc[-1].close) + # " | " + str(Utils.calc_perc(row["buy"], stocks_15.iloc[-1].close)) + # "% | " + str(stocks_15.iloc[-1].name) + # " | ", stocks_15.iloc[-1].name) # asyncio.run(self.sm.a_mail_sym_stats(sym, "Selling Profit: " + str(stocks_15.iloc[-1].sym) + " | " + str(stocks_15.index[-1]) + " | " + # " | B.S.:" + str(row["buy"]) + "/" + str(stocks_15.iloc[-1].close) + # " | " + str(Utils.calc_perc(row["buy"], stocks_15.iloc[-1].close)) + # "% | " + str(stocks_15.iloc[-1].name) + # " | ", stocks_15.iloc[-1].name), debug=True) #------------------------------------------------------------BUY--------------------------------------------- if hash_warn not in self.warning_check_list \ and stocks_day.iloc[-1]["flpd"] > 0 \ and chi.check_financials(financials) \ and (len(self.bs.buy_sell_open) == 0 or stocks_15.iloc[-1].sym not in self.bs.buy_sell_open[self.bs.buy_sell_open.state == "open"].sym) \ and chi.check_pre_sma9(stocks_day, live_stocks=stocks_15): # and chi.check_sentiment(sentiment) \ # and chi.check_financials(financials) \ self.warning_check_list.append(hash_warn) self.bs.buy_stock_t(stocks_15.iloc[-1], stocks_15.iloc[-1].close, table_name="buy_sell_lt", profit_loss={ "profit": hl["h"], "loss": hl["l"] }) st.write( "---------------------------BUYiNG-------------------------------" ) # logging.info(self.bs.buy_sell) st.write( sym + " | Buy: " + str(stocks_15.iloc[-1].sym) + " | " + str(stocks_15.index[-1]) + " | " + str(stocks_15.iloc[-1].close) + " | " + str(hl), stocks_15.iloc[-1].name) # asyncio.run(self.sm.a_mail_sym_stats(sym, "Buy: " + # str(stocks_15.iloc[-1].sym) + " | " + str(stocks_15.index[-1]) + " | " + # str(stocks_15.iloc[-1].close) + " | " + # str(hl), stocks_15.iloc[-1].name)) def set_time_to(self): if self.time_from is None: time_from = "-180d" else: time_from = self.time_from return time_from def hide_footer(self): hide_streamlit_style = """ <style> #MainMenu {visibility: visible;} footer {visibility: hidden;} </style> """ st.markdown(hide_streamlit_style, unsafe_allow_html=True) def _max_width_(self): max_width_str = f"max-width: 2000px;max-height:1000px;" st.markdown( f""" <style> .reportview-container .main .block-container{{ {max_width_str} }} </style> """, unsafe_allow_html=True, )
class RunData(): selected_stock = None timetick = None time_from = None time_to = None selected = {} action_type = None types = ["sector-stats", "stock-detail", "stocks-stats"] sw = StockWhisperer() inday_days = 2 def __init__(self): self.db = Database() self.symbols = self.db.get_symbols(TableName.DAY) self.sectors = self.db.get_sectors(TableName.DAY) self.sm = StockMess() self.ss = SectorStats() self.app = self.get_home_page() self.submit = None # self.fig = None # print(self.df) # def load_data(self, option, time_from = "-180d", time_to = None): # df = self.db.load_data( # "p_day", symbols=option, time_from=time_from, time_to = time_to) # df = FinI.add_indicators(sdf.retype(df)) # return df def testing_mess(self): self.sm.stocks = self.db.load_data( table_name=TableName.DAY, symbols=["PLUG"], time_from=self.time_from, time_to=self.time_to, ) self.sm.get_subj_mess("Base Fund: ", "PLUG") def get_home_page(self): query_params = st.experimental_get_query_params() if len(query_params) > 0 and query_params.get("type")[0] == "detail": st.set_page_config(initial_sidebar_state="collapsed", page_title=query_params.get("sym")[0], layout="wide") else: st.set_page_config(layout="wide") self.hide_footer() self.left_menu() # self.testing_mess() self.action_router(query_params) async def prepare_detail_tasks(self, sym=None): tasks = [] tasks.append(asyncio.ensure_future(self.get_price_detail(sym=sym))) tasks.append(asyncio.ensure_future( self.get_inday_price_graph(sym=sym))) tasks.append(asyncio.ensure_future(self.get_fund_detail(sym=sym))) await asyncio.gather(*tasks, return_exceptions=True) def left_menu(self): self.time_from = st.sidebar.text_input("Time from now -1m, -1h, -1d,", value="-120d") self.time_to = st.sidebar.text_input("Time to 1m, 1h, 1d,") self.selected_sector = st.sidebar.selectbox('Select sector', self.sectors) self.selected_stock = st.sidebar.selectbox('Select stock', self.symbols) self.inday_days = st.sidebar.number_input('inday chart days', value=2) if self.selected_stock == 0: self.selected_stock = "TSLA" # loop = asyncio.get_event_loop() # task = None # try: # task = loop.create_task(self.watch()) # except KeyboardInterrupt: # task.cancel() # print('after async') # st.sidebar.text_area("websocket",self.timetick) # self.action_type = st.sidebar.selectbox( # 'Seeect Type', # self.types) # self.submit = st.sidebar.button("Submit", "submit") def action_router(self, query_params=None): if st.sidebar.button('stock-detail') or ( len(query_params) > 0 and query_params.get("type")[0] == "detail"): asyncio.new_event_loop().run_until_complete( self.prepare_detail_tasks(sym=query_params.get("sym")[0] if len(query_params) > 0 else None)) if st.sidebar.button('top-sectors'): self.top_sectors(time_from=self.time_from, time_to=self.time_to) if st.sidebar.button('top-industries'): self.top_sectors(time_from=self.time_from, time_to=self.time_to, is_industries=True) if st.sidebar.button('top-stocks'): self.top_stocks(time_from=self.time_from, time_to=self.time_to) if st.sidebar.button('bottom-stocks'): self.top_stocks(time_from=self.time_from, time_to=self.time_to, ascending=True) if st.sidebar.button("find-stocks-to-buy"): self.find_stocks_to_buy() if st.sidebar.button("Last-Financials"): self.last_financials() def last_financials(self): df = self.db.get_last_financials() df.dropna(inplace=True, axis='columns', how="all") df.drop(columns=['zip','city','phone','longBusinessSummary','companyOfficers','maxAge','address1','previousClose', \ 'regularMarketOpen','regularMarketDayHigh','navPrice','totalAssets','regularMarketPreviousClose','open','yield', \ 'priceHint', 'currency', 'dayLow', 'ask', 'askSize','website','longName', \ 'exchange'], inplace=True) df.set_index(df.symbol, inplace=True) st.dataframe(df, height=2000) def find_stocks_to_buy(self): st.title("Stocks to buy") self.sw.time_from = self.time_from if self.sectors is not None: self.sw.sectors = [self.sectors] self.sw = StockWhisperer() try: output = self.sw.find_stocks(TableName.DAY, False) except KeyboardInterrupt: st.write("stopped by keyboard") stocks = output[[ "close", "open", "high", "low", "volume", "amount", "flpd", "sym" ]] # print(stocks) self.print_stocks_list(stocks, True, from_top=0, show_stocks_num=50) def show_sectors(self, stocks, is_industries=False): fig = px.bar(stocks, y='flpd', x=stocks.index) # fig.update_traces(texttemplate=stocks.sector, textposition='inside') fig.update_layout(uniformtext_minsize=8, uniformtext_mode='hide', barmode='group') st.plotly_chart( fig, use_container_width=True, use_container_height=True, template="plotly_dark", ) # st.bar_chart(stocks) def top_sectors(self, ascending=False, time_from=None, time_to=None, is_industries=False): # st.write(time_to) # st.write(time_from) title = "Top industries" if is_industries else "Top sectors" separator = " | " st.title(title + str(time_from)) if not time_from: time_from = "-7d" table = TableName.DAY if time_from.find("m") > -1 or time_from.find("m") > -1: table = TableName.MIN15 stocks = self.ss.classify_sectors_uptrend(table_name=table, time_from=time_from, time_to=time_to, from_db=True, is_industries=is_industries, separator=separator) if stocks is not None and len(stocks) > 0: stocks = stocks.sort_values(by='flpd', ascending=ascending) stocks.drop( columns=["close", "open", "high", "low", "volume", "amount"], inplace=True) self.show_sectors(stocks, is_industries=is_industries) for idx, row in stocks.iterrows(): st.write(str(idx) + ": " + str(round(row.flpd, 2)) + "%") self.top_stocks(group=idx, ascending=ascending, time_from=time_from, time_to=time_to, table=table, is_industries=is_industries, separator=separator) else: st.write("No data") def top_stocks(self, group=None, ascending=False, time_from=None, time_to=None, table=None, from_top=0, show_stocks_num=20, is_industries=False, separator=None): st.empty() table = TableName.DAY if time_from.find("m") > -1: table = TableName.MIN15 subject = "Loosers: " if ascending else "Gainers: " if isinstance(group, str): industry = str.split(group, separator) group = industry[1] if len(industry) > 1 else industry[0] group = [group] if is_industries: stocks = self.db.load_data( table_name=table, industries=group, time_from=time_from, time_to=time_to, ) else: stocks = self.db.load_data( table_name=table, sectors=group, time_from=time_from, time_to=time_to, ) # self.stocks = FinI.add_change(self.stocks) stocks = Utils.add_first_last_perc_diff(stocks) self.print_stocks_list(stocks, ascending, from_top=from_top, show_stocks_num=show_stocks_num) def print_stocks_list(self, stocks, ascending, from_top=0, show_stocks_num=20): if stocks is not None and len(stocks) > 0: stocks = stocks.groupby(by="sym").mean() stocks = stocks.sort_values(by='flpd', ascending=ascending) top_stocks = stocks.iloc[from_top:(from_top + show_stocks_num)] top_stocks = self.fill_with_mess(top_stocks) reduced_top_stocks = top_stocks.drop( columns=["open", "high", "low", "amount"]) reduced_top_stocks["detail"] = '<a href="/?type=detail&sym=' + \ reduced_top_stocks.index + '" target="_blank"> ' + \ reduced_top_stocks.index + '</a>' reduced_top_stocks["news"] = '<a href="https://finance.yahoo.com/quote/' + \ reduced_top_stocks.index + '" target="_blank"> yahoo </a>' reduced_top_stocks["rating"] = '<a href="https://zacks.com/stock/quote/' + \ reduced_top_stocks.index + '" target="_blank"> zacks </a>' st.write(reduced_top_stocks.to_html(escape=False, index=False), unsafe_allow_html=True) # selected_indices = st.multiselect('Select rows:', stocks.index) # selected_rows = stocks.loc[selected_indices] # self.top_stocks_list = top_stocks.index.tolist() # self.draw_chart_values(top_stocks) #send_mails # asyncio.run(self.sm.mail_stats(top_stocks, subject)) else: print('No stocks has been found') def fill_with_mess(self, stocks): mess_block = [] for index, row in stocks.iterrows(): self.sm.set_fundamentals(index) # st.write(index) mess, curr_price, days_to_earnings = self.sm.get_subj_mess( "", index) mess_block.append(mess) # print(stocks.loc[index]) stocks["fund"] = mess_block return stocks def set_time_to(self): if self.time_from is None: time_from = "-180d" else: time_from = self.time_from return time_from async def get_inday_price_graph(self, sym=None): if sym is None: sym = self.selected_stock inday_df = self.db.get_last_n_days(sym, n_days_back=self.inday_days, table=TableName.MIN15) inday_df = FinI.add_indicators(sdf.retype(inday_df)) await self.inday_price_graph(sym, inday_df) async def get_price_detail(self, sym=None): if sym is None: sym = self.selected_stock time_from = self.set_time_to() df = self.db.load_data( table_name=TableName.DAY, symbols=sym, time_from=time_from, time_to=self.time_to, ) m_df_spy = self.db.load_data(table_name=TableName.DAY, time_from=time_from, time_to=self.time_to, symbols=["SPY"]) m_df_spy["oc_mean"] = (m_df_spy.close + m_df_spy.open) / 2 # self.stocks = FinI.add_change(self.stocks) df = FinI.add_indicators(sdf.retype(df)) await self.price_graph(sym, df, m_df_spy=m_df_spy) # self.macd_rsi_graph(option, df) self._max_width_() # await asyncio.sleep(0.001) async def get_fund_detail(self, sym=None): if sym is None: sym = self.selected_stock self.sm.set_fundamentals(sym) time_from = self.set_time_to() self.sm.stocks = self.db.load_data( table_name=TableName.DAY, symbols=sym, time_from=time_from, time_to=self.time_to, ) mess, curr_price, days_to_earnings = self.sm.get_subj_mess( "Base Fund: ", sym) st.write(mess) await st.write( self.sm.get_fund_mess(self.sm.financials, curr_price, self.sm.earnings, self.sm.sentiment, days_to_earnings, self.sm.stocks)) def macd_rsi_graph(self, option, df): data = PlotP.plot_rsi(df, ax="y") data += PlotP.plot_macd_boll(df=df, ax="y2") fig = go.Figure(data=data) fig.update_layout(autosize=True, height=400, yaxis=dict(title="RSI", titlefont=dict(color="green"), tickfont=dict(color="green")), yaxis2=dict(title="macd", titlefont=dict(color="#8888ff"), tickfont=dict(color="#8888ff"), anchor="free", overlaying="y", side="left", position=0)) # Create figure with secondary y-axis st.plotly_chart(fig, use_container_width=True) def gainers(self): pass def hide_footer(self): hide_streamlit_style = """ <style> #MainMenu {visibility: visible;} footer {visibility: hidden;} </style> """ st.markdown(hide_streamlit_style, unsafe_allow_html=True) # def sector_stats(self, time_from, time_to, loosers): # stocks = self.ss.classify_sectors_uptrend(table_name =TableName.DAY) # stocks = stocks.sort_values(by='flpd', ascending=loosers) # if False: # self.sw.sectors = [self.sw.stocks.iloc[:-1].index[0]] # self.sw.top_stocks(table_name=None, top_losers=loosers) def inday_price_graph(self, option, df, ax="y2"): st.write("In day chart: -" + str(self.inday_days) + "d") sets = [{ 'x': df["index"], 'open': df.open, 'close': df.close, 'high': df.high, 'low': df.low, 'yaxis': ax, "hovertext": "", 'type': 'candlestick' }] sets += [{ 'x': df["index"], 'y': df.boll, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'green' }, 'name': 'Boll' }] sets += [{ 'x': df["index"], 'y': df.boll + df.boll_2, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 0.3, 'color': 'green', "dash": "dot" }, 'name': '-' }] sets += [{ 'x': df["index"], 'y': df.boll + df.boll_3, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 0.3, 'color': 'green', "dash": "dot" }, 'name': '-' }] # sets += [{'x': df["index"], 'y': df.boll + df.boll_5, 'yaxis': ax, 'type': 'scatter', # 'mode': 'lines', 'line': {'width': 0.3, 'color': 'green'}, 'name': '-'}] sets += [{ 'x': df["index"], 'y': df.boll + df.boll_6, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 0.3, 'color': 'green', "dash": "dot" }, 'name': '-' }] sets += [{ 'x': df["index"], 'y': df.boll - df.boll_2, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 0.3, 'color': 'green', "dash": "dot" }, 'name': '-' }] sets += [{ 'x': df["index"], 'y': df.boll - df.boll_3, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 0.3, 'color': 'green', "dash": "dot" }, 'name': '-' }] # sets += [{'x': df["index"], 'y': df.boll - df.boll_5, 'yaxis': ax, 'type': 'scatter', # 'mode': 'lines', 'line': {'width': 0.3, 'color': 'green'}, 'name': '-'}] sets += [{ 'x': df["index"], 'y': df.boll - df.boll_6, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 0.3, 'color': 'green', "dash": "dot" }, 'name': '-' }] sets += [{ 'x': df["index"], 'y': df.boll_ub, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'green' }, 'name': 'Boll UP' }] sets += [{ 'x': df["index"], 'y': df.boll, 'yaxis': ax, 'type': 'scatter', "fill": 'tonexty', 'line': { 'width': 0, }, "fillcolor": 'rgba(128, 255, 128,0.2)' }] sets += [{ 'x': df["index"], 'y': df.boll_lb, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'green' }, 'name': 'Boll Down' }] sets += [{ 'x': df["index"], 'y': df.boll, 'yaxis': ax, 'type': 'scatter', "fill": 'tonexty', 'line': { 'width': 0, }, "fillcolor": 'rgba(128, 255, 128,0.2)' }] sets += [{ 'x': df["index"], 'y': df.sma9, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'blue' }, 'name': 'sma9' }] sets += [{ 'x': df["index"], 'y': df.sma50, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'darkblue' }, 'name': 'sma50' }] sets += [{ 'x': df["index"], 'y': df.sma100, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'orange' }, 'name': 'sma100' }] df = FinI.add_levels(df) for i, r in df.iterrows(): if r.price_level is not None: sets += [{ 'x': [r["index"], df.iloc[-1]["index"]], 'y': [r.price_level, r.price_level], 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'brown', "dash": "dot" }, 'name': '' }] # print(levels) # sets += [{'x': df["index"], 'y': df.price_level, 'yaxis': ax, 'type': 'scatter', # 'mode': 'lines', 'line': {'width': 1, 'color': 'orange'}, 'name': 'sma100'}] # data += PlotP.plot_rsi(df, ax="y2") # data += PlotP.plot_macd_boll(df=df, ax="y3") # st.area(df, x=df["index"], y=df.boll, color="continent", # line_group="country") # fig = go.Figure(data=sets) fig = make_subplots(rows=2, cols=1, shared_xaxes=True, vertical_spacing=0.009, horizontal_spacing=0.009, row_width=[0.1, 0.5], specs=[[{ "secondary_y": True }], [{ "secondary_y": True }]]) fig.add_traces(data=sets, cols=1, rows=1) # data = PlotP.plot_rsi(df, ax="y") # fig.add_traces(data, 3, 1) # data = PlotP.plot_macd_boll(df=df, ax="y2") # fig.add_traces(data, 3, 1) df.loc[df.open > df.close, "vol_color"] = "red" df.loc[df.open <= df.close, "vol_color"] = "green" # print(df.vol_color) fig.add_trace( { 'x': df["index"], 'y': df.volume, 'type': 'bar', 'name': 'Volume', 'marker_color': df.vol_color }, 2, 1, secondary_y=False, ) # fig['layout']['margin'] = {'l': 30, 'r': 10, 'b': 50, 't': 25} fig.update_yaxes(showgrid=True, zeroline=False, showticklabels=True, showspikes=True, spikemode='across', spikesnap='cursor', showline=True, spikedash='dash', spikethickness=0.5) fig.update_xaxes(showgrid=True, zeroline=False, rangeslider_visible=False, showticklabels=True, showspikes=True, showline=True, spikemode='across', spikesnap='cursor', spikedash='dash', spikethickness=0.5) fig.update_layout(autosize=True, height=600, hoverdistance=1, hovermode='y', spikedistance=10000) st.plotly_chart( fig, use_container_width=True, use_container_height=True, template="plotly_dark", ) # st.line_chart(df.close) def price_graph(self, option, df, m_df_spy=None, ax="y2"): st.write("Days chart: " + str(self.time_from)) sets = [{ 'x': df.index, 'open': df.open, 'close': df.close, 'high': df.high, 'low': df.low, 'yaxis': ax, "hovertext": "", 'type': 'candlestick' }] sets += [{ 'x': df.index, 'y': df.boll, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'green' }, 'name': 'Boll' }] sets += [{ 'x': df.index, 'y': df.boll + df.boll_2, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 0.3, 'color': 'green', "dash": "dot" }, 'name': '-' }] sets += [{ 'x': df.index, 'y': df.boll + df.boll_3, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 0.3, 'color': 'green', "dash": "dot" }, 'name': '-' }] # sets += [{'x': df.index, 'y': df.boll + df.boll_5, 'yaxis': ax, 'type': 'scatter', # 'mode': 'lines', 'line': {'width': 0.3, 'color': 'green'}, 'name': '-'}] sets += [{ 'x': df.index, 'y': df.boll + df.boll_6, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 0.3, 'color': 'green', "dash": "dot" }, 'name': '-' }] sets += [{ 'x': df.index, 'y': df.boll - df.boll_2, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 0.3, 'color': 'green', "dash": "dot" }, 'name': '-' }] sets += [{ 'x': df.index, 'y': df.boll - df.boll_3, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 0.3, 'color': 'green', "dash": "dot" }, 'name': '-' }] # sets += [{'x': df.index, 'y': df.boll - df.boll_5, 'yaxis': ax, 'type': 'scatter', # 'mode': 'lines', 'line': {'width': 0.3, 'color': 'green'}, 'name': '-'}] sets += [{ 'x': df.index, 'y': df.boll - df.boll_6, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 0.3, 'color': 'green', "dash": "dot" }, 'name': '-' }] sets += [{ 'x': df.index, 'y': df.boll_ub, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'green' }, 'name': 'Boll UP' }] sets += [{ 'x': df.index, 'y': df.boll, 'yaxis': ax, 'type': 'scatter', "fill": 'tonexty', 'line': { 'width': 0, }, "fillcolor": 'rgba(128, 255, 128,0.2)' }] sets += [{ 'x': df.index, 'y': df.boll_lb, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'green' }, 'name': 'Boll Down' }] sets += [{ 'x': df.index, 'y': df.boll, 'yaxis': ax, 'type': 'scatter', "fill": 'tonexty', 'line': { 'width': 0, }, "fillcolor": 'rgba(255, 128, 128,0.2)' }] sets += [{ 'x': df.index, 'y': df.sma9, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'blue' }, 'name': 'sma9' }] sets += [{ 'x': df.index, 'y': df.sma50, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'darkblue' }, 'name': 'sma50' }] sets += [{ 'x': df.index, 'y': df.sma100, 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'orange' }, 'name': 'sma100' }] df = FinI.add_levels(df) for i, r in df.iterrows(): if r.price_level is not None: sets += [{ 'x': [i, df.iloc[-1].name], 'y': [r.price_level, r.price_level], 'yaxis': ax, 'type': 'scatter', 'mode': 'lines', 'line': { 'width': 1, 'color': 'brown', "dash": "dot" }, 'name': '' }] # print(levels) # sets += [{'x': df.index, 'y': df.price_level, 'yaxis': ax, 'type': 'scatter', # 'mode': 'lines', 'line': {'width': 1, 'color': 'orange'}, 'name': 'sma100'}] # data += PlotP.plot_rsi(df, ax="y2") # data += PlotP.plot_macd_boll(df=df, ax="y3") # st.area(df, x=df.index, y=df.boll, color="continent", # line_group="country") # fig = go.Figure(data=sets) fig = make_subplots(rows=3, cols=1, shared_xaxes=True, vertical_spacing=0.009, horizontal_spacing=0.009, row_width=[0.2, 0.1, 0.5], specs=[[{ "secondary_y": True }], [{ "secondary_y": True }], [{ "secondary_y": True }]]) fig.add_traces(data=sets, cols=1, rows=1) if m_df_spy is not None: fig.add_trace( { 'x': m_df_spy.index, 'y': m_df_spy.oc_mean, 'type': 'scatter', 'yaxis': "y", 'mode': 'lines', 'line': { 'width': 1, 'color': 'red' }, 'name': 'SPY' }, 1, 1, secondary_y=True, ) # data = PlotP.plot_rsi(df, ax="y") # fig.add_traces(data, 3, 1) mb = PlotP.plot_macd_boll(df=df, ax="y") fig.add_traces( data=mb, rows=3, cols=1, ) rsi = PlotP.plot_rsi(df=df, ax="y3") fig.add_traces(data=rsi, rows=3, cols=1, secondary_ys=[True, True, True, True, True]) df.loc[df.open > df.close, "vol_color"] = "red" df.loc[df.open <= df.close, "vol_color"] = "green" # print(df.vol_color) fig.add_trace( { 'x': df.index, 'y': df.volume, 'type': 'bar', 'name': 'Volume', 'marker_color': df.vol_color }, 2, 1, secondary_y=False, ) # fig['layout']['margin'] = {'l': 30, 'r': 10, 'b': 50, 't': 25} fig.update_yaxes(showgrid=True, zeroline=False, showticklabels=True, showspikes=True, spikemode='across', spikesnap='cursor', showline=True, spikedash='dash', spikethickness=0.5) fig.update_xaxes(showgrid=True, zeroline=False, rangeslider_visible=False, showticklabels=True, showspikes=True, showline=True, spikemode='across', spikesnap='cursor', spikedash='dash', spikethickness=0.5) fig.update_layout( autosize=True, height=600, hoverdistance=1, hovermode='y', spikedistance=10000, ) st.plotly_chart( fig, use_container_width=True, use_container_height=True, template="plotly_dark", ) # st.line_chart(df.close) def _max_width_(self): max_width_str = f"max-width: 2000px;max-height:1000px;" st.markdown( f""" <style> .reportview-container .main .block-container{{ {max_width_str} }} </style> """, unsafe_allow_html=True, )
class SectorStats(): def __init__(self): self.db = Database() self.sectors_trend = [] self.spy_trend = [] self.last_date = None self.spy = None self.stocks = None self.in_day_stocks = None self.trend_data = None def show_sectors_stats(self, data, save_image=False, plt=None): if plt is None: return False fig, axs = plt.subplots(len(data)) fig.suptitle('Sector overview') # print(axs) plt = self.sector_stats_to_plt(plt, data, axs) if save_image: return plt else: plt.show() def sector_stats_to_plt(self, plt, data, axs): i = 0 for key in data.keys(): plotdata = data[key] # plt.subplots(len(data)) # axs.bar(plotdata, height = 2) plotdata.plot(kind="bar", ax=axs[i]) axs[i].set_title("Year " + str(key)) axs[i].grid(True) # plt.title("Year " + str(key)) plt.xticks(rotation=45) plt.xlabel("Sector") plt.ylabel("Change") axs[i].legend().set_visible(False) # for i, j in zip(data[key].index, data[key].flpd): # axs[i].annotate(str(j), xy=(i, j)) i += 1 return plt def sectors_day_stats(self, table_name=TableName.DAY, time_from="-180d", time_to="0d"): # technical, healthcare, financials etc. sectors = sdf.retype( self.db.load_data(table_name, time_from=time_from, time_to=time_to)) sectors = sdf.retype(sectors) # normalize data sectors["date"] = sectors.index # print(sectors) # sectors.get('close_-1_r') # sectors = Utils.add_first_last_perc_diff(sectors) sectors = sectors.groupby(by=["sector", "date"]).mean() # for item in sectors # sectors = sectors.sort_(by = ["sector","date"]) # print(sectors.where(cond=sectors.index.name == "Basic Materials")) res = sdf() for index in sectors.index.unique('sector'): sec = sectors.iloc[sectors.index.get_level_values('sector') == index] sec = sdf.retype(sec) sec['close_n'] = (sec.close - sec.close.min()) / (sec.close.max() - sec.close.min()) sec.get('close_-1_r') sec.get('volume_-1_r') # print(sec) res = res.append(sec) # self.show_sec_day_stats(res) # print(res) return res # print(self.stocks.head()) def get_trend_slice(self, table_name=None, time_from=None, time_to=None, symbol=None, from_db=False): if time_to is None: time_to = "0d" if time_from is None: time_from = "-14d" # print(time_from + " --- " + time_to) if self.trend_data is None or from_db: tn = table_name if table_name else TableName.DAY self.trend_data = sdf.retype( self.db.load_data(table_name=tn, time_from=time_from, time_to=time_to)) print("--------filling trend_data------------") print("get_trend_slice() - done") stocks = self.trend_data.copy() stocks = stocks[stocks.index.to_series().between( self.db.get_date_format(time_from), self.db.get_date_format(time_to))] # print(str(symbol) + " SYMBOOOOOL") if symbol is not None: stocks = stocks[stocks.sym == symbol.upper()] # print(stocks) # print(self.trend_data) if stocks is not None and len(stocks) > 0: return stocks else: return None # def get_splited_spy_sectors_uptrends(self, table_name=None, time_from=None, time_to=None): # stocks = self.get_trend_slice(full_stock=True) # df1 = stocks.iloc[:, :round(len(stocks)/2, 0)] # df2 = stocks.iloc[:, round(len(stocks)/2, 0):] # self.sectors_trend.append(self.classify_sectors_uptrend( # table_name=table_name, time_from="-14d", time_to="-7d")) # self.sectors_trend.append(self.classify_sectors_uptrend(table_name=table_name, time_from="-7d", time_to="0d")) # # ----------------------------set spy trend----------------------------- # self.spy_trend.append(self.get_trend_slice( # table_name=table_name, time_from="-14d", time_to="-7d", symbol="SPY")) # self.spy_trend[0] = Utils.add_first_last_perc_diff(self.spy_trend[0]) # self.spy_trend.append(sdf.retype(self.get_trend_slice( # table_name=table_name, time_from="-7d", time_to="0d", symbol="SPY"))) # self.spy_trend[1] = Utils.add_first_last_perc_diff(self.spy_trend[1]) # # print(self.spy_trend) def classify_sectors_uptrend(self, table_name=None, time_from=None, time_to=None, stocks=None, from_db=False, is_industries=False, separator=""): # print(self.trend_data) if stocks is None: stocks = self.get_trend_slice(table_name=table_name, time_from=time_from, time_to=time_to, from_db=from_db) # technical, healthcare, financials etc. # print(stocks) if stocks is not None: stocks = Utils.add_first_last_perc_diff(stocks) stocks[ "industry"] = stocks["sector"] + separator + stocks["industry"] group_by = "sector" if is_industries is False else "industry" stocks = stocks.groupby(by=group_by).mean() return stocks else: return stocks # print(self.stocks.head()) def sectors_uptrend_by_month(self, yf=2017, yt=None, show_chart=True): # technical, healthcare, financials etc. sectors = self.db.get_sectors() sectors_month_stats = pd.DataFrame() sec_year_stats = {} # print(sectors) # self.sectors = [sec] stocks = sdf.retype(self.db.load_data(TableName.DAY)) stocks.index = pd.to_datetime(stocks.index, utc=True) stocks['month'] = stocks.index.to_series().dt.month stocks['year'] = stocks.index.to_series().dt.year if not yt: max_year = stocks.year.max() else: max_year = yt # data contain more sectors since 2016 for year in range(yf, max_year + 1): one_year_stocks = stocks.where( cond=stocks['year'] == year).dropna() sectors_month_stats = pd.DataFrame() # print(one_year_stocks) min_month = one_year_stocks.month.min() max_month = one_year_stocks.month.max() for month in range(int(min_month), int(max_month) + 1): one_month_stocks = one_year_stocks.where( cond=one_year_stocks['month'] == month).dropna() one_month_stocks = Utils.add_first_last_perc_diff( one_month_stocks) sectors_data = one_month_stocks.groupby( by=one_month_stocks['sector']).mean() sectors_month_stats["sector"] = sectors_data.index sectors_month_stats[month] = sectors_data.flpd.tolist() sectors_month_stats.set_index('sector', inplace=True) sec_year_stats[year] = sectors_month_stats.copy() if show_chart: self.show_sectors_stats(sec_year_stats, False, plt) return sectors_month_stats def set_spy_sectors_trend(self): table_name = TableName.DAY if self.trend_data is None: self.classify_sectors_uptrend(table_name=table_name, time_from="-14d", time_to="0") df1 = self.trend_data.iloc[0:int(round(len(self.trend_data) / 2, 0))] df2 = self.trend_data.iloc[int(round(len(self.trend_data) / 2, 0)):len(self.trend_data)] # ---------------------------set sectors trend -------------------- self.sectors_trend.append(self.classify_sectors_uptrend(stocks=df1)) self.sectors_trend.append(self.classify_sectors_uptrend(stocks=df2)) # ----------------------------set spy trend----------------------------- dfs1 = df1[df1.sym == "SPY"] dfs2 = df2[df2.sym == "SPY"] self.spy_trend.append(Utils.add_first_last_perc_diff(dfs1)) self.spy_trend.append(Utils.add_first_last_perc_diff(dfs2)) print("set_spy_sectors_trend() - done")