add growth financial-statements
This commit is contained in:
parent
db7e80703a
commit
4c2343cc9e
@ -1,6 +1,5 @@
|
|||||||
import os
|
import os
|
||||||
import ujson
|
import ujson
|
||||||
import random
|
|
||||||
import asyncio
|
import asyncio
|
||||||
import aiohttp
|
import aiohttp
|
||||||
import sqlite3
|
import sqlite3
|
||||||
@ -35,18 +34,32 @@ async def save_json(symbol, period, data_type, data):
|
|||||||
async def get_financial_statements(session, symbol, semaphore, request_counter):
|
async def get_financial_statements(session, symbol, semaphore, request_counter):
|
||||||
base_url = "https://financialmodelingprep.com/api/v3"
|
base_url = "https://financialmodelingprep.com/api/v3"
|
||||||
periods = ['quarter', 'annual']
|
periods = ['quarter', 'annual']
|
||||||
data_types = ['income-statement', 'balance-sheet-statement', 'cash-flow-statement', 'ratios']
|
financial_data_types = ['income-statement', 'balance-sheet-statement', 'cash-flow-statement', 'ratios']
|
||||||
|
growth_data_types = ['income-statement-growth', 'balance-sheet-statement-growth', 'cash-flow-statement-growth']
|
||||||
|
|
||||||
async with semaphore:
|
async with semaphore:
|
||||||
for period in periods:
|
for period in periods:
|
||||||
for data_type in data_types:
|
# Fetch regular financial statements
|
||||||
|
for data_type in financial_data_types:
|
||||||
url = f"{base_url}/{data_type}/{symbol}?period={period}&apikey={api_key}"
|
url = f"{base_url}/{data_type}/{symbol}?period={period}&apikey={api_key}"
|
||||||
data = await fetch_data(session, url, symbol)
|
data = await fetch_data(session, url, symbol)
|
||||||
if data:
|
if data:
|
||||||
await save_json(symbol, period, data_type, data)
|
await save_json(symbol, period, data_type, data)
|
||||||
|
|
||||||
request_counter[0] += 1 # Increment the request counter
|
request_counter[0] += 1 # Increment the request counter
|
||||||
if request_counter[0] >= 1000:
|
if request_counter[0] >= 500:
|
||||||
|
await asyncio.sleep(60) # Pause for 60 seconds
|
||||||
|
request_counter[0] = 0 # Reset the request counter after the pause
|
||||||
|
|
||||||
|
# Fetch financial statement growth data
|
||||||
|
for growth_type in growth_data_types:
|
||||||
|
growth_url = f"{base_url}/{growth_type}/{symbol}?period={period}&apikey={api_key}"
|
||||||
|
growth_data = await fetch_data(session, growth_url, symbol)
|
||||||
|
if growth_data:
|
||||||
|
await save_json(symbol, period, growth_type, growth_data)
|
||||||
|
|
||||||
|
request_counter[0] += 1 # Increment the request counter
|
||||||
|
if request_counter[0] >= 500:
|
||||||
await asyncio.sleep(60) # Pause for 60 seconds
|
await asyncio.sleep(60) # Pause for 60 seconds
|
||||||
request_counter[0] = 0 # Reset the request counter after the pause
|
request_counter[0] = 0 # Reset the request counter after the pause
|
||||||
|
|
||||||
|
|||||||
18
app/main.py
18
app/main.py
@ -111,6 +111,14 @@ with db_connection(INSTITUTE_DB) as cursor:
|
|||||||
cik_list = [row[0] for row in cursor.fetchall()]
|
cik_list = [row[0] for row in cursor.fetchall()]
|
||||||
#------End Institute DB------------#
|
#------End Institute DB------------#
|
||||||
|
|
||||||
|
#------Start Stock Screener--------#
|
||||||
|
with open(f"json/stock-screener/data.json", 'rb') as file:
|
||||||
|
stock_screener_data = orjson.loads(file.read())
|
||||||
|
|
||||||
|
print([item for item in stock_screener_data if item['symbol'] == 'TYL'])
|
||||||
|
#------End Stock Screener--------#
|
||||||
|
|
||||||
|
|
||||||
### TECH DEBT ###
|
### TECH DEBT ###
|
||||||
con = sqlite3.connect('stocks.db')
|
con = sqlite3.connect('stocks.db')
|
||||||
etf_con = sqlite3.connect('etf.db')
|
etf_con = sqlite3.connect('etf.db')
|
||||||
@ -1148,12 +1156,10 @@ async def stock_finder(data:StockScreenerData, api_key: str = Security(get_api_k
|
|||||||
always_include = ['symbol', 'marketCap', 'price', 'changesPercentage', 'name','volume','pe']
|
always_include = ['symbol', 'marketCap', 'price', 'changesPercentage', 'name','volume','pe']
|
||||||
|
|
||||||
try:
|
try:
|
||||||
with open(f"json/stock-screener/data.json", 'rb') as file:
|
filtered_data = [
|
||||||
data = orjson.loads(file.read())
|
{key: item.get(key) for key in set(always_include + rule_of_list) if key in item}
|
||||||
filtered_data = [
|
for item in stock_screener_data
|
||||||
{key: item.get(key) for key in set(always_include + rule_of_list) if key in item}
|
]
|
||||||
for item in data
|
|
||||||
]
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
filtered_data = []
|
filtered_data = []
|
||||||
|
|
||||||
|
|||||||
@ -63,15 +63,29 @@ def process_financial_data(file_path, key_list):
|
|||||||
if key in res:
|
if key in res:
|
||||||
try:
|
try:
|
||||||
value = float(res[key])
|
value = float(res[key])
|
||||||
if key in ['grossProfitMargin','netProfitMargin','pretaxProfitMargin','operatingProfitMargin']:
|
if 'growth' in file_path or key in ['grossProfitMargin','netProfitMargin','pretaxProfitMargin','operatingProfitMargin']:
|
||||||
value *= 100 # Multiply by 100 if key is 'grossProfitMargin'
|
value *= 100 # Multiply by 100 for percentage
|
||||||
data[key] = round(value, 2)
|
data[key] = round(value, 2)
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
|
# If there's an issue converting the value, leave it as None
|
||||||
data[key] = None
|
data[key] = None
|
||||||
except:
|
except (FileNotFoundError, KeyError, IndexError):
|
||||||
|
# If the file doesn't exist or there's an issue reading the data,
|
||||||
|
# data will retain None as the default value for all keys
|
||||||
pass
|
pass
|
||||||
|
|
||||||
return data
|
return data
|
||||||
|
|
||||||
|
def check_and_process(file_path, key_list):
|
||||||
|
"""
|
||||||
|
Check if the file exists, and then process the financial data if it does.
|
||||||
|
If the file doesn't exist, return a dictionary with all keys set to None.
|
||||||
|
"""
|
||||||
|
if os.path.exists(file_path):
|
||||||
|
return process_financial_data(file_path, key_list)
|
||||||
|
else:
|
||||||
|
return {key: None for key in key_list}
|
||||||
|
|
||||||
def get_financial_statements(item, symbol):
|
def get_financial_statements(item, symbol):
|
||||||
"""
|
"""
|
||||||
Update item with financial data from various JSON files.
|
Update item with financial data from various JSON files.
|
||||||
@ -134,11 +148,122 @@ def get_financial_statements(item, symbol):
|
|||||||
"totalInvestments", "totalDebt", "netDebt"
|
"totalInvestments", "totalDebt", "netDebt"
|
||||||
]
|
]
|
||||||
|
|
||||||
|
key_income_growth = [
|
||||||
|
"growthRevenue",
|
||||||
|
"growthCostOfRevenue",
|
||||||
|
"growthGrossProfit",
|
||||||
|
"growthGrossProfitRatio",
|
||||||
|
"growthResearchAndDevelopmentExpenses",
|
||||||
|
"growthGeneralAndAdministrativeExpenses",
|
||||||
|
"growthSellingAndMarketingExpenses",
|
||||||
|
"growthOtherExpenses",
|
||||||
|
"growthOperatingExpenses",
|
||||||
|
"growthCostAndExpenses",
|
||||||
|
"growthInterestExpense",
|
||||||
|
"growthDepreciationAndAmortization",
|
||||||
|
"growthEBITDA",
|
||||||
|
"growthEBITDARatio",
|
||||||
|
"growthOperatingIncome",
|
||||||
|
"growthOperatingIncomeRatio",
|
||||||
|
"growthTotalOtherIncomeExpensesNet",
|
||||||
|
"growthIncomeBeforeTax",
|
||||||
|
"growthIncomeBeforeTaxRatio",
|
||||||
|
"growthIncomeTaxExpense",
|
||||||
|
"growthNetIncome",
|
||||||
|
"growthNetIncomeRatio",
|
||||||
|
"growthEPS",
|
||||||
|
"growthEPSDiluted",
|
||||||
|
"growthWeightedAverageShsOut",
|
||||||
|
"growthWeightedAverageShsOutDil"
|
||||||
|
]
|
||||||
|
key_cash_flow_growth = [
|
||||||
|
"growthNetIncome",
|
||||||
|
"growthDepreciationAndAmortization",
|
||||||
|
"growthDeferredIncomeTax",
|
||||||
|
"growthStockBasedCompensation",
|
||||||
|
"growthChangeInWorkingCapital",
|
||||||
|
"growthAccountsReceivables",
|
||||||
|
"growthInventory",
|
||||||
|
"growthAccountsPayables",
|
||||||
|
"growthOtherWorkingCapital",
|
||||||
|
"growthOtherNonCashItems",
|
||||||
|
"growthNetCashProvidedByOperatingActivites",
|
||||||
|
"growthInvestmentsInPropertyPlantAndEquipment",
|
||||||
|
"growthAcquisitionsNet",
|
||||||
|
"growthPurchasesOfInvestments",
|
||||||
|
"growthSalesMaturitiesOfInvestments",
|
||||||
|
"growthOtherInvestingActivites",
|
||||||
|
"growthNetCashUsedForInvestingActivites",
|
||||||
|
"growthDebtRepayment",
|
||||||
|
"growthCommonStockIssued",
|
||||||
|
"growthCommonStockRepurchased",
|
||||||
|
"growthDividendsPaid",
|
||||||
|
"growthOtherFinancingActivites",
|
||||||
|
"growthNetCashUsedProvidedByFinancingActivities",
|
||||||
|
"growthEffectOfForexChangesOnCash",
|
||||||
|
"growthNetChangeInCash",
|
||||||
|
"growthCashAtEndOfPeriod",
|
||||||
|
"growthCashAtBeginningOfPeriod",
|
||||||
|
"growthOperatingCashFlow",
|
||||||
|
"growthCapitalExpenditure",
|
||||||
|
"growthFreeCashFlow"
|
||||||
|
]
|
||||||
|
key_balance_sheet_growth = [
|
||||||
|
"growthCashAndCashEquivalents",
|
||||||
|
"growthShortTermInvestments",
|
||||||
|
"growthCashAndShortTermInvestments",
|
||||||
|
"growthNetReceivables",
|
||||||
|
"growthInventory",
|
||||||
|
"growthOtherCurrentAssets",
|
||||||
|
"growthTotalCurrentAssets",
|
||||||
|
"growthPropertyPlantEquipmentNet",
|
||||||
|
"growthGoodwill",
|
||||||
|
"growthIntangibleAssets",
|
||||||
|
"growthGoodwillAndIntangibleAssets",
|
||||||
|
"growthLongTermInvestments",
|
||||||
|
"growthTaxAssets",
|
||||||
|
"growthOtherNonCurrentAssets",
|
||||||
|
"growthTotalNonCurrentAssets",
|
||||||
|
"growthOtherAssets",
|
||||||
|
"growthTotalAssets",
|
||||||
|
"growthAccountPayables",
|
||||||
|
"growthShortTermDebt",
|
||||||
|
"growthTaxPayables",
|
||||||
|
"growthDeferredRevenue",
|
||||||
|
"growthOtherCurrentLiabilities",
|
||||||
|
"growthTotalCurrentLiabilities",
|
||||||
|
"growthLongTermDebt",
|
||||||
|
"growthDeferredRevenueNonCurrent",
|
||||||
|
"growthDeferredTaxLiabilitiesNonCurrent",
|
||||||
|
"growthOtherNonCurrentLiabilities",
|
||||||
|
"growthTotalNonCurrentLiabilities",
|
||||||
|
"growthOtherLiabilities",
|
||||||
|
"growthTotalLiabilities",
|
||||||
|
"growthCommonStock",
|
||||||
|
"growthRetainedEarnings",
|
||||||
|
"growthAccumulatedOtherComprehensiveIncomeLoss",
|
||||||
|
"growthOtherTotalStockholdersEquity",
|
||||||
|
"growthTotalStockholdersEquity",
|
||||||
|
"growthTotalLiabilitiesAndStockholdersEquity",
|
||||||
|
"growthTotalInvestments",
|
||||||
|
"growthTotalDebt",
|
||||||
|
"growthNetDebt"
|
||||||
|
]
|
||||||
|
|
||||||
# Process each financial statement
|
# Process each financial statement
|
||||||
item.update(process_financial_data(f"json/financial-statements/ratios/annual/{symbol}.json", key_ratios))
|
statements = [
|
||||||
item.update(process_financial_data(f"json/financial-statements/cash-flow-statement/annual/{symbol}.json", key_cash_flow))
|
(f"json/financial-statements/ratios/annual/{symbol}.json", key_ratios),
|
||||||
item.update(process_financial_data(f"json/financial-statements/income-statement/annual/{symbol}.json", key_income))
|
(f"json/financial-statements/cash-flow-statement/annual/{symbol}.json", key_cash_flow),
|
||||||
item.update(process_financial_data(f"json/financial-statements/balance-sheet-statement/annual/{symbol}.json", key_balance_sheet))
|
(f"json/financial-statements/income-statement/annual/{symbol}.json", key_income),
|
||||||
|
(f"json/financial-statements/balance-sheet-statement/annual/{symbol}.json", key_balance_sheet),
|
||||||
|
(f"json/financial-statements/income-statement-growth/annual/{symbol}.json", key_income_growth),
|
||||||
|
(f"json/financial-statements/balance-sheet-statement-growth/annual/{symbol}.json", key_balance_sheet_growth),
|
||||||
|
(f"json/financial-statements/cash-flow-statement-growth/annual/{symbol}.json", key_cash_flow_growth)
|
||||||
|
]
|
||||||
|
|
||||||
|
# Process each financial statement
|
||||||
|
for file_path, key_list in statements:
|
||||||
|
item.update(check_and_process(file_path, key_list))
|
||||||
|
|
||||||
try:
|
try:
|
||||||
item['freeCashFlowMargin'] = round((item['freeCashFlow'] / item['revenue']) * 100,2)
|
item['freeCashFlowMargin'] = round((item['freeCashFlow'] / item['revenue']) * 100,2)
|
||||||
@ -180,7 +305,7 @@ async def get_stock_screener(con):
|
|||||||
|
|
||||||
#Stock Screener Data
|
#Stock Screener Data
|
||||||
|
|
||||||
cursor.execute("SELECT symbol, name, change_1W, change_1M, change_3M, change_6M, change_1Y, change_3Y, sma_50, sma_200, ema_50, ema_200, rsi, atr, stoch_rsi, mfi, cci, pe, marketCap, growthRevenue, growthNetIncome, growthGrossProfit, growthCostOfRevenue, growthCostAndExpenses, growthInterestExpense, growthResearchAndDevelopmentExpenses, growthEBITDA, growthEPS, growthOperatingExpenses, growthOperatingIncome, beta FROM stocks WHERE symbol NOT LIKE '%.%' AND eps IS NOT NULL AND revenue IS NOT NULL AND marketCap IS NOT NULL AND beta IS NOT NULL")
|
cursor.execute("SELECT symbol, name, change_1W, change_1M, change_3M, change_6M, change_1Y, change_3Y, sma_50, sma_200, ema_50, ema_200, rsi, atr, stoch_rsi, mfi, cci, pe, marketCap, 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()
|
raw_data = cursor.fetchall()
|
||||||
stock_screener_data = [{
|
stock_screener_data = [{
|
||||||
'symbol': symbol,
|
'symbol': symbol,
|
||||||
@ -202,23 +327,14 @@ async def get_stock_screener(con):
|
|||||||
'cci': cci,
|
'cci': cci,
|
||||||
'pe': pe,
|
'pe': pe,
|
||||||
'marketCap': marketCap,
|
'marketCap': marketCap,
|
||||||
'growthRevenue': growthRevenue,
|
|
||||||
'growthNetIncome': growthNetIncome,
|
|
||||||
'growthGrossProfit': growthGrossProfit,
|
|
||||||
'growthCostOfRevenue': growthCostOfRevenue,
|
|
||||||
'growthCostAndExpenses': growthCostAndExpenses,
|
|
||||||
'growthInterestExpense': growthInterestExpense,
|
|
||||||
'growthResearchAndDevelopmentExpenses': growthResearchAndDevelopmentExpenses,
|
|
||||||
'growthEBITDA': growthEBITDA,
|
|
||||||
'growthEPS': growthEPS,
|
|
||||||
'growthOperatingExpenses': growthOperatingExpenses,
|
|
||||||
'growthOperatingIncome': growthOperatingIncome,
|
|
||||||
'beta': beta,
|
'beta': beta,
|
||||||
} for (symbol, name, change_1W, change_1M, change_3M, change_6M, change_1Y, change_3Y, sma_50, sma_200, ema_50, ema_200, rsi, atr, stoch_rsi, mfi, cci, pe, marketCap, growthRevenue, growthNetIncome, growthGrossProfit, growthCostOfRevenue, growthCostAndExpenses, growthInterestExpense, growthResearchAndDevelopmentExpenses, growthEBITDA, growthEPS, growthOperatingExpenses, growthOperatingIncome, beta) in raw_data]
|
} for (symbol, name, change_1W, change_1M, change_3M, change_6M, change_1Y, change_3Y, sma_50, sma_200, ema_50, ema_200, rsi, atr, stoch_rsi, mfi, cci, pe, marketCap, 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]
|
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]
|
||||||
|
|
||||||
|
|
||||||
|
cursor.execute("SELECT symbol, name, change_1W, change_1M, change_3M, change_6M, change_1Y, change_3Y, sma_50, sma_200, ema_50, ema_200, rsi, atr, stoch_rsi, mfi, cci, pe, marketCap, 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()
|
||||||
|
|
||||||
# Iterate through stock_screener_data and update 'price' and 'changesPercentage' if symbols match
|
# Iterate through stock_screener_data and update 'price' and 'changesPercentage' if symbols match
|
||||||
# Add VaR value to stock screener
|
# Add VaR value to stock screener
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user