File size: 10,178 Bytes
8f8ed2b 60a045a 8f8ed2b |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 |
import yfinance as yf
import streamlit as st
import pandas as pd
class CalculateMetric:
def __init__(self, symbol: str):
self.ticker = yf.Ticker(symbol)
# Get financial statements and info
balance_sheet = self.ticker.balance_sheet
income_statement = self.ticker.financials
cash_flow = self.ticker.cashflow
# Transpose the DataFrames to have dates as rows
balance_sheet = balance_sheet.T
income_statement = income_statement.T
cash_flow = cash_flow.T
# Sort the DataFrames by date in descending order
self.balance_sheet = balance_sheet.sort_index(ascending=False)
self.income_statement = income_statement.sort_index(ascending=False)
self.cash_flow = cash_flow.sort_index(ascending=False)
self.z_weightage = 0.6
self.f_weightage = 0.4
def calculate_F_Score(self) -> int:
latest = 0
previous = 1
# Criterion 1: Positive Net Income
net_income_latest = self.income_statement["Net Income"].iloc[latest]
net_income_prev = self.income_statement["Net Income"].iloc[previous]
c1 = 1 if net_income_latest > 0 and net_income_latest > net_income_prev else 0
# Criterion 2: Positive Operating Cash Flow
op_cash_flow_latest = self.cash_flow["Operating Cash Flow"].iloc[latest]
c2 = 1 if op_cash_flow_latest > 0 else 0
# Criterion 3: Return on Assets improving
total_assets_latest = self.balance_sheet["Total Assets"].iloc[latest]
total_assets_prev = self.balance_sheet["Total Assets"].iloc[previous]
roa_latest = (
net_income_latest / total_assets_latest if total_assets_latest != 0 else 0
)
roa_prev = net_income_prev / total_assets_prev if total_assets_prev != 0 else 0
c3 = 1 if roa_latest > roa_prev else 0
# Criterion 4: Quality of Earnings
c4 = 1 if op_cash_flow_latest > net_income_latest else 0
# Criterion 5: No New Debt or Debt Reduction
long_term_debt_latest = self.balance_sheet["Long Term Debt"].iloc[latest]
long_term_debt_prev = self.balance_sheet["Long Term Debt"].iloc[previous]
c5 = 1 if long_term_debt_latest <= long_term_debt_prev else 0
# Criterion 6: Improvement in Current Ratio
current_assets_latest = self.balance_sheet["Current Assets"].iloc[latest]
current_liabilities_latest = self.balance_sheet["Current Liabilities"].iloc[
latest
]
current_ratio_latest = (
current_assets_latest / current_liabilities_latest
if current_liabilities_latest != 0
else 0
)
current_assets_prev = self.balance_sheet["Current Assets"].iloc[previous]
current_liabilities_prev = self.balance_sheet["Current Liabilities"].iloc[
previous
]
current_ratio_prev = (
current_assets_prev / current_liabilities_prev
if current_liabilities_prev != 0
else 0
)
c6 = 1 if current_ratio_latest > current_ratio_prev else 0
# Criterion 7: No New Shares Issued
shares_outstanding_latest = self.balance_sheet["Common Stock"].iloc[latest]
shares_outstanding_prev = self.balance_sheet["Common Stock"].iloc[previous]
c7 = 1 if shares_outstanding_latest <= shares_outstanding_prev else 0
# Criterion 8: Improvement in Gross Margin
gross_profit_latest = self.income_statement["Gross Profit"].iloc[latest]
total_revenue_latest = self.income_statement["Total Revenue"].iloc[latest]
gross_margin_latest = (
gross_profit_latest / total_revenue_latest
if total_revenue_latest != 0
else 0
)
gross_profit_prev = self.income_statement["Gross Profit"].iloc[previous]
total_revenue_prev = self.income_statement["Total Revenue"].iloc[previous]
gross_margin_prev = (
gross_profit_prev / total_revenue_prev if total_revenue_prev != 0 else 0
)
c8 = 1 if gross_margin_latest > gross_margin_prev else 0
# Criterion 9: Improvement in Asset Turnover
total_revenue_prev = self.income_statement["Total Revenue"].iloc[previous]
total_assets_prev = self.balance_sheet["Total Assets"].iloc[previous]
asset_turnover_latest = (
total_revenue_latest / total_assets_latest
if total_assets_latest != 0
else 0
)
asset_turnover_prev = (
total_revenue_prev / total_assets_prev if total_assets_prev != 0 else 0
)
c9 = 1 if asset_turnover_latest > asset_turnover_prev else 0
# Calculate Piotroski F-Score
f_score = c1 + c2 + c3 + c4 + c5 + c6 + c7 + c8 + c9
return f_score
def calculate_altman_z_score(self) -> float:
info = self.ticker.info
current_assets = self.balance_sheet["Current Assets"].iloc[0] / 1000000
current_liabilities = (
self.balance_sheet["Current Liabilities"].iloc[0] / 1000000
)
total_assets = self.balance_sheet["Total Assets"].iloc[0] / 1000000
retained_earnings = self.balance_sheet["Retained Earnings"].iloc[0] / 1000000
ebit = self.income_statement["EBIT"].iloc[0] / 1000000
sales = self.income_statement["Total Revenue"].iloc[0] / 1000000
market_cap = info["marketCap"] / 1000000
total_liabilities = (
self.balance_sheet["Total Liabilities Net Minority Interest"].iloc[0]
/ 1000000
)
X1 = (current_assets - current_liabilities) / total_assets
X2 = retained_earnings / total_assets
X3 = ebit / total_assets
X4 = market_cap / total_liabilities
X5 = sales / total_assets
# Calculate Altman Z-Score for non-manufacturing firms
Z = 1.2 * X1 + 1.4 * X2 + 3.3 * X3 + 0.6 * X4 + 1.0 * X5
return Z
def health(self):
try:
combined_metric = (
(self.f_weightage * self.calculate_F_Score())
+ (self.z_weightage * self.calculate_altman_z_score())
)
except:
return "Error: Unable to calculate metrics", 0, False
is_investable = False
if combined_metric >= 7:
is_investable = True
message = "The company's fundamentals are Extremely Strong"
return message, combined_metric, is_investable
elif combined_metric >=4:
is_investable = True
message = "The company's fundamentals are Strong"
return message, combined_metric, is_investable
else:
message = "The company's fundamentals are Weak"
return message, combined_metric, is_investable
st.set_page_config(page_title='Fundler', page_icon='💰')
st.title('Gemstone Score Calculator💰')
st.write('Enter a Yahoo Finance compatible ticker symbol to get investment recommendations based on fundamental analysis.')
ticker_symbol = st.text_input('Enter Ticker Symbol', help='e.g., AAPL for Apple Inc.', value='MSFT')
if st.button('Submit'):
try:
calculator = CalculateMetric(ticker_symbol)
message, score, invest = calculator.health()
# Display the results
st.subheader('Analysis Results:')
st.write(f'**Message:** {message}')
st.write(f'**Score:** {score:.2f}')
if invest:
st.write('**Investment Decision:** Yes, consider investing in this stock.')
else:
st.write('**Investment Decision:** No, do not invest in this stock.')
except Exception as e:
st.error(f'An error occurred: {e}')
st.write("---")
st.markdown("Made By Adeeb [GitHub](https://github.com/Itachi-Uchiha581)")
st.subheader('Ticker Symbol Naming Conventions for Different Exchanges')
data = {
"Exchange Name": [
"Bombay Stock Exchange (BSE)",
"National Stock Exchange (NSE)",
"New York Stock Exchange (NYSE)",
"NASDAQ",
"London Stock Exchange (LSE)",
"Tokyo Stock Exchange (TSE)",
"Hong Kong Stock Exchange (HKEX)",
"Shanghai Stock Exchange (SSE)",
"Shenzhen Stock Exchange (SZSE)",
"Euronext Amsterdam",
"Euronext Paris",
"Toronto Stock Exchange (TSX)",
"Australian Securities Exchange (ASX)",
"Deutsche Börse Xetra (Frankfurt)",
"Swiss Exchange (SIX)",
"Milan Stock Exchange (Borsa Italiana)",
"Vienna Stock Exchange (WBAG)",
"Madrid Stock Exchange (BME)",
"Stockholm Stock Exchange (OMX)",
"Johannesburg Stock Exchange (JSE)",
"São Paulo Stock Exchange (B3)",
"Moscow Exchange (MOEX)",
"Taiwan Stock Exchange (TWSE)",
"Korean Stock Exchange (KRX)",
"OTC Markets (Over-the-Counter, US)",
"Currency Exchange (Forex)",
"Cryptocurrencies",
],
"Suffix": [
".BO", ".NS", "No Suffix Required", "No Suffix Required", ".L", ".T", ".HK", ".SS", ".SZ", ".AS", ".PA", ".TO",
".AX", ".DE", ".SW", ".MI", ".VI", ".MC", ".ST", ".JO", ".SA", ".ME", ".TW",
".KS", ".OTC", ".X", ".CRYPTO"
],
"Example Ticker Symbol": [
"RELIANCE.BO, TCS.BO",
"RELIANCE.NS, TCS.NS",
"AAPL, MSFT",
"GOOGL, TSLA",
"HSBA.L, RIO.L",
"7203.T (Toyota), 6758.T (Sony)",
"0005.HK (HSBC), 0700.HK (Tencent)",
"600519.SS (Kweichow Moutai)",
"000001.SZ (Ping An Bank)",
"ADYEN.AS, PHIA.AS",
"BNP.PA, AIR.PA",
"RY.TO, TD.TO",
"BHP.AX, CBA.AX",
"DBK.DE (Deutsche Bank), SAP.DE",
"NESN.SW, UBSG.SW",
"ENEL.MI, ISP.MI",
"EBS.VI, ANDR.VI",
"SAN.MC, IBE.MC",
"ERIC.ST, VOLV.ST",
"NPN.JO, AGL.JO",
"PETR4.SA, VALE3.SA",
"GAZP.ME, SBER.ME",
"2330.TW (TSMC), 2303.TW",
"005930.KS (Samsung), 000660.KS",
"TCEHY.OTC, BABA.OTC",
"USDINR=X, EURUSD=X",
"BTC-USD, ETH-USD"
],
}
exchange_df = pd.DataFrame(data)
# Display the table
st.table(exchange_df) |