Fin_Research / pages /1_Fundamentals.py
Robert Castagna
feb8 meeting update
813fa51
raw
history blame
No virus
7.61 kB
from scraped_data import get_alpha_vantage_data, get_finnhub_data
import datetime
import pandas as pd
import streamlit as st
import yfinance as yf
from datetime import timedelta
def get_industry(ticker):
comp_info = get_finnhub_data(f'/stock/profile2?symbol={ticker}')
return comp_info
def get_company_metrics(ticker):
res_basic_fins = get_finnhub_data(f'/stock/metric?symbol={ticker}&metric=all')
metric_data = res_basic_fins['metric'] if 'metric' in res_basic_fins else 'N/A'
annual_series_data = res_basic_fins['series']['annual'] if ('series' in res_basic_fins and 'annual' in res_basic_fins['series']) else 'N/A'
quarterly_series_data = res_basic_fins['series']['quarterly'] if ('series' in res_basic_fins and 'quarterly' in res_basic_fins['series']) else 'N/A'
return metric_data, annual_series_data, quarterly_series_data
def calc_beta(ticker):
tick = yf.Ticker(f'{ticker}')
sp_hist = yf.Ticker('^GSPC').history(period="5y")['Close']
ticker_hist = tick.history(period="5y")['Close']
sp500 = sp_hist.reset_index().rename(columns={'Close':'sp500_Close'})
sp500['sp500_variance'] = sp500['sp500_Close'].var()
merged_df = sp500.merge(ticker_hist, how='outer', on='Date')
beta = merged_df.cov(numeric_only=True).loc['sp500_Close']['Close'] / sp500['sp500_variance'].max()
max_date = merged_df['Date'].max()
d = {'Beta': beta, 'Symbol': ticker}
df_beta = pd.DataFrame(d, index = [0])
return df_beta.set_index('Symbol')
def get_equity_gains(ticker, period):
sp = yf.Ticker(f"{ticker}")
sp_hist = sp.history(period=f'{period}d')[['Close','Dividends']]
sp500 = sp_hist.reset_index()
todays_close = sp500.sort_values('Date', ascending=False).iloc[0]
sp500_new_index = sp500.set_index('Date')
val = {}
if todays_close[0] - timedelta(days=period) in sp500_new_index.index:
delta = todays_close['Close'] - sp500_new_index.loc[todays_close[0] - timedelta(days=period)]['Close']
val[f'5Y_change'] = (delta / sp500_new_index.loc[todays_close[0] - timedelta(days=period)]['Close'])
else:
delta = todays_close['Close'] - sp500_new_index.loc[todays_close[0] - timedelta(days=period-4)]['Close']
val[f'5Y_change'] = (delta / sp500_new_index.loc[todays_close[0] - timedelta(days=period-4)]['Close'])
# add in dividend
recent_div = sp500.sort_values('Date', ascending=False)
first_non_zero_dividend_row = recent_div[recent_div['Dividends'] > 0.0]
if len(first_non_zero_dividend_row) == 0:
return val['5Y_change'], 0, recent_div['Close'].iloc[0]
else:
return val['5Y_change'], first_non_zero_dividend_row.iloc[0]['Dividends'], recent_div['Close'].iloc[0]
def get_90_day_tbill():
q = 'function=TREASURY_YIELD&'
t_bill_data = get_alpha_vantage_data(q)
df_t_bills = pd.DataFrame(t_bill_data['data']).rename(columns={'date':'Date', 'value':'90_day_t_bill'})
return float(df_t_bills.iloc[0]['90_day_t_bill'])/100.00
@st.cache_data
def get_list_of_tickers():
comp_info = get_finnhub_data('/stock/symbol?exchange=US')
list_of_tickers = []
for i in range(len(comp_info)-1):
for key in comp_info[i].keys():
if key == 'symbol':
list_of_tickers.append(comp_info[i]['symbol'])
return list_of_tickers
# ---------------------------------------------------------------------------------------------- #
symbols = []
list_of_tickers = get_list_of_tickers()
with st.form(key="selecting columns"):
symbols = st.multiselect(label='Enter Tickers Here. Cannot check metrics for Funds.', options=list_of_tickers, placeholder='MSFT, AAPL, ...')
strategy_selection = st.radio("Select Strategy", ('Value', 'Growth'), horizontal=True)
submit_button = st.form_submit_button(label='Compute Metrics')
if submit_button and symbols and strategy_selection == 'Value':
beta_dfs = []
gains_data = {}
hash_map = {}
for ticker in symbols:
st.spinner(text=f"Loading {ticker} Data...")
# make all the API calls and capture return json
basic_info = get_industry(ticker)
metric_data, annual_series_data, quarterly_series_data = get_company_metrics(ticker)
# reformat all JSON returns to be flattened dictionaries
roe_dict = {'roe': annual_series_data['roe'][0]['v'] if annual_series_data != 'N/A' else 'N/A'}
totalDebtToTotalCapital_y_dict = {'totalDebtToTotalCapital_y' : annual_series_data['totalDebtToTotalCapital'][0]['v'] if annual_series_data != 'N/A' else 'N/A'}
totalDebtToEquity_y_dict = {'totalDebtToEquity_y' : annual_series_data['totalDebtToEquity'][0]['v'] if annual_series_data != 'N/A' else 'N/A'}
eps_dict = {'eps' : annual_series_data['eps'][0]['v'] if annual_series_data != 'N/A' else 'N/A'}
totalDebtToTotalCapital_q_dict = {'totalDebtToTotalCapital_q' : quarterly_series_data['totalDebtToTotalCapital'][0]['v'] if quarterly_series_data != 'N/A' else 'N/A'}
totalDebtToEquity_q_dict = {'totalDebtToEquity_q' : quarterly_series_data['totalDebtToEquity'][0]['v'] if quarterly_series_data != 'N/A' else 'N/A'}
# merge all dictionary keys per ticker
combined_info = basic_info.copy() # Make a copy of the basic info
combined_info = combined_info | metric_data | roe_dict | totalDebtToTotalCapital_y_dict | totalDebtToEquity_q_dict |totalDebtToEquity_y_dict | eps_dict | totalDebtToTotalCapital_q_dict
hash_map[ticker] = combined_info
# beta calculations
df_b = calc_beta(ticker)
beta_dfs.append(df_b)
# equity gains
_, div, close_price = get_equity_gains(ticker=ticker, period=1810)
gains_data[ticker] = [div, close_price]
# Now, create a DataFrame from the hash_map
df_1 = pd.DataFrame.from_dict(hash_map, orient='index')[['finnhubIndustry','eps','roe','dividendGrowthRate5Y','epsGrowth5Y','payoutRatioAnnual','payoutRatioTTM','roeTTM','totalDebtToEquity_y','totalDebtToEquity_q', 'totalDebtToTotalCapital_y','totalDebtToTotalCapital_q']]
# Create beta df
beta_df = pd.concat(beta_dfs)
df_2 = pd.DataFrame.from_dict(gains_data, orient='index', columns=['Recent Dividend','Price'])
df_apis = df_1.join(beta_df)
df_final = df_apis.join(df_2)
# calculate additional columns
df_final['5Y_SP500_growth'], _, _ = get_equity_gains(ticker= '^GSPC', period=1810)
df_final['90_day_tbill'] = 4.06
df_final['P/E Ratio'] = df_final['Price'] / df_final['eps']
df_final['dividendGrowthRate5Y'] = df_final['dividendGrowthRate5Y']/100
df_final['CAPM'] = df_final['90_day_tbill']/100 + df_final['Beta']*(df_final['5Y_SP500_growth'] - df_final['90_day_tbill']/100)
df_final['DDM'] = (df_final['Recent Dividend'] * (1+df_final['dividendGrowthRate5Y'])) / (df_final['CAPM'] - df_final['dividendGrowthRate5Y'])
df_final = df_final[['finnhubIndustry','Price','eps','roe','P/E Ratio','epsGrowth5Y','payoutRatioAnnual','payoutRatioTTM','roeTTM','totalDebtToEquity_y','totalDebtToEquity_q', 'totalDebtToTotalCapital_y','totalDebtToTotalCapital_q','Beta','Recent Dividend','90_day_tbill','5Y_SP500_growth','dividendGrowthRate5Y','CAPM','DDM']]
df_final.rename({'finnhubIndustry':'Industry', 'eps':'EPS', 'roe':'ROE'}, inplace=True, axis=1)
st.write(df_final)
if submit_button and symbols and strategy_selection == 'Growth':
st.write("Not built yet...")