diff --git a/app/cron_info_text.py b/app/cron_info_text.py index b421ac6..64afbb3 100644 --- a/app/cron_info_text.py +++ b/app/cron_info_text.py @@ -523,8 +523,11 @@ data = { "evFCF": { "text": "The enterprise value to free cash flow (EV/FCF) ratio is similar to the price to free cash flow ratio, except the price is adjusted for the company's cash and debt.", "equation": "EV/FCF Ratio = Enterprise Value / Free Cash Flow", - } - + }, + "inventoryTurnover": { + "text": "The inventory turnover ratio measures how many times inventory has been sold and replaced during a time period.", + "equation": "Inventory Turnover Ratio = Cost of Revenue / Average Inventory", + }, } diff --git a/app/restart_json.py b/app/restart_json.py index b12aa28..ce5e953 100755 --- a/app/restart_json.py +++ b/app/restart_json.py @@ -28,6 +28,47 @@ benzinga_api_key = os.getenv('benzinga_api_key') berlin_tz = pytz.timezone('Europe/Berlin') +query_price = """ + SELECT + close + FROM + "{symbol}" + WHERE + date <= ? + ORDER BY + date DESC + LIMIT 1 +""" + +time_frames = { + 'change1W': (datetime.now() - timedelta(days=7)).strftime('%Y-%m-%d'), + 'change1M': (datetime.now() - timedelta(days=30)).strftime('%Y-%m-%d'), + 'change3M': (datetime.now() - timedelta(days=90)).strftime('%Y-%m-%d'), + 'change6M': (datetime.now() - timedelta(days=180)).strftime('%Y-%m-%d'), + 'change1Y': (datetime.now() - timedelta(days=365)).strftime('%Y-%m-%d'), + 'change3Y': (datetime.now() - timedelta(days=365 * 3)).strftime('%Y-%m-%d'), +} + +def calculate_price_changes(symbol, item, con): + try: + # Loop through each time frame to calculate the change + for name, date in time_frames.items(): + item[name] = None # Initialize to None + + query = query_price.format(symbol=symbol) + data = pd.read_sql_query(query, con, params=(date,)) + + # Check if data was retrieved and calculate the percentage change + if not data.empty: + past_price = data.iloc[0]['close'] + current_price = item['price'] + item[name] = round(((current_price - past_price) / past_price) * 100, 2) + + except: + # Handle exceptions by setting all fields to None + for name in time_frames.keys(): + item[name] = None + # Replace NaN values with None in the resulting JSON object def replace_nan_inf_with_none(obj): if isinstance(obj, list): @@ -403,17 +444,11 @@ async def get_stock_screener(con): #Stock Screener Data - cursor.execute("SELECT symbol, name, change_1W, change_1M, change_3M, change_6M, change_1Y, change_3Y, sma_20, sma_50, sma_100, sma_200, ema_20, ema_50, ema_100, ema_200, rsi, atr, stoch_rsi, mfi, cci, beta FROM stocks WHERE symbol NOT LIKE '%.%' AND eps IS NOT NULL AND marketCap IS NOT NULL AND beta IS NOT NULL") + cursor.execute("SELECT symbol, name, sma_20, sma_50, sma_100, sma_200, ema_20, ema_50, ema_100, ema_200, rsi, atr, stoch_rsi, mfi, cci, beta FROM stocks WHERE symbol NOT LIKE '%.%' AND eps IS NOT NULL AND marketCap IS NOT NULL AND beta IS NOT NULL") raw_data = cursor.fetchall() stock_screener_data = [{ 'symbol': symbol, 'name': name, - 'change1W': change_1W, - 'change1M': change_1M, - 'change3M': change_3M, - 'change6M': change_6M, - 'change1Y': change_1Y, - 'change3Y': change_3Y, 'sma20': sma_20, 'sma50': sma_50, 'sma100': sma_100, @@ -428,7 +463,7 @@ async def get_stock_screener(con): 'mfi': mfi, 'cci': cci, 'beta': beta, - } for (symbol, name, change_1W, change_1M, change_3M, change_6M, change_1Y, change_3Y, sma_20, sma_50, sma_100, sma_200, ema_20, ema_50, ema_100, ema_200, rsi, atr, stoch_rsi, mfi, cci, beta) in raw_data] + } for (symbol, name, sma_20, sma_50, sma_100, sma_200, ema_20, ema_50, ema_100, ema_200, rsi, atr, stoch_rsi, mfi, cci, beta) in raw_data] stock_screener_data = [{k: round(v, 2) if isinstance(v, (int, float)) else v for k, v in entry.items()} for entry in stock_screener_data] @@ -460,6 +495,9 @@ async def get_stock_screener(con): item['pe'] = None item['marketCap'] = None + calculate_price_changes(symbol, item, con) + + try: with open(f"json/stockdeck/{symbol}.json", 'r') as file: res = orjson.loads(file.read())[0] diff --git a/app/ta_signal.py b/app/ta_signal.py index b34b5f7..44ec65d 100755 --- a/app/ta_signal.py +++ b/app/ta_signal.py @@ -39,24 +39,7 @@ class TASignals: ta_df['atr'] = AverageTrueRange(self.data['High'], self.data['Low'], self.data['Close'], window=14).average_true_range() ta_df['cci'] = CCIIndicator(high=self.data['High'], low=self.data['Low'], close=self.data['Close']).cci() ta_df['mfi'] = MFIIndicator(high=self.data['High'], low=self.data['Low'], close=self.data['Close'], volume=self.data['Volume']).money_flow_index() - # Calculate 52-week change - # Define periods for different time frames - periods = { - '1W': 5, - '1M': 21, - '3M': 63, - '6M': 126, - '1Y': 252, - '3Y': 756 - } - # Calculate percentage change for each period - for period_name, period_days in periods.items(): - if len(self.data['Close']) >= period_days: - change = ((self.data['Close'].iloc[-1] - self.data['Close'].iloc[-period_days]) / self.data['Close'].iloc[-period_days]) * 100 - ta_df[f'change_{period_name}'] = change - else: - ta_df[f'change_{period_name}'] = np.nan # Not enough data for the period last_values = {col: [round(ta_df[col].iloc[-1],2)] for col in ta_df.columns} if not ta_df.empty else None last_values_df = pd.DataFrame(last_values) @@ -121,8 +104,9 @@ def process_symbol(ticker): create_columns(con, ta_df) update_database(ta_df, ticker, con) - except Exception as e: - print(f"Failed create ta signals for {ticker}: {e}") + except: + pass + #print(f"Failed create ta signals for {ticker}: {e}")