diff --git a/app/cron_financial_statements.py b/app/cron_financial_statements.py index ee0ce2e..240c4c9 100644 --- a/app/cron_financial_statements.py +++ b/app/cron_financial_statements.py @@ -1,5 +1,6 @@ import os import ujson +import orjson import asyncio import aiohttp import sqlite3 @@ -29,7 +30,53 @@ async def fetch_data(session, url, symbol, attempt=0): async def save_json(symbol, period, data_type, data): os.makedirs(f"json/financial-statements/{data_type}/{period}/", exist_ok=True) with open(f"json/financial-statements/{data_type}/{period}/{symbol}.json", 'w') as file: - ujson.dump(data, file) + ujson.dumps(data,file) + +async def calculate_margins(symbol): + for period in ['annual', 'quarter']: + # Load income statement data + income_path = f"json/financial-statements/income-statement/{period}/{symbol}.json" + with open(income_path, "r") as file: + income_data = orjson.loads(file.read()) + + # Load cash flow statement data + cash_flow_path = f"json/financial-statements/cash-flow-statement/{period}/{symbol}.json" + with open(cash_flow_path, "r") as file: + cash_flow_data = orjson.loads(file.read()) + + # Load ratios data + ratios_path = f"json/financial-statements/ratios/{period}/{symbol}.json" + with open(ratios_path, "r") as file: + ratio_data = orjson.loads(file.read()) + + # Ensure all datasets are available and iterate through the items + if income_data and cash_flow_data and ratio_data: + for ratio_item, income_item, cash_flow_item in zip(ratio_data, income_data, cash_flow_data): + # Extract required data + revenue = income_item.get('revenue', 0) + ebitda = income_item.get('ebitda',0) + free_cash_flow = cash_flow_item.get('freeCashFlow', 0) + + # Calculate freeCashFlowMargin if data is valid + if revenue != 0: # Avoid division by zero + ratio_item['freeCashFlowMargin'] = round((free_cash_flow / revenue) * 100, 2) + ratio_item['ebitdaMargin'] = round((ebitda / revenue) * 100,2) + ratio_item['grossProfitMargin'] = round(ratio_item['grossProfitMargin']*100,2) + ratio_item['operatingProfitMargin'] = round(ratio_item['operatingProfitMargin']*100,2) + ratio_item['pretaxProfitMargin'] = round(ratio_item['pretaxProfitMargin']*100,2) + ratio_item['netProfitMargin'] = round(ratio_item['netProfitMargin']*100,2) + else: + ratio_item['freeCashFlowMargin'] = None # Handle missing or zero revenue + ratio_item['ebitdaMargin'] = None + ratio_item['grossProfitMargin'] = None + ratio_item['operatingProfitMargin'] = None + ratio_item['pretaxProfitMargin'] = None + ratio_item['netProfitMargin'] = None + + # Save the updated ratios data back to the JSON file + with open(ratios_path, "wb") as file: + file.write(orjson.dumps(data,option=orjson.OPT_SERIALIZE_NUMPY).decode('utf-8')) + async def get_financial_statements(session, symbol, semaphore, request_counter): base_url = "https://financialmodelingprep.com/api/v3" @@ -80,7 +127,7 @@ async def get_financial_statements(session, symbol, semaphore, request_counter): await asyncio.sleep(60) # Pause for 60 seconds request_counter[0] = 0 # Reset the request counter after the pause - + await calculate_margins(symbol) async def run(): con = sqlite3.connect('stocks.db') diff --git a/app/primary_cron_job.py b/app/primary_cron_job.py index 9e568ef..d07a7aa 100755 --- a/app/primary_cron_job.py +++ b/app/primary_cron_job.py @@ -237,7 +237,7 @@ def run_market_moods(): def run_db_schedule_job(): #update db daily week = datetime.today().weekday() - if week <= 4: + if week <= 5: run_command(["bash", "run_universe.sh"])