Spaces:
Running
Running
Update info.py
Browse files
info.py
CHANGED
|
@@ -1,85 +1,100 @@
|
|
| 1 |
-
#
|
|
|
|
|
|
|
|
|
|
|
|
|
| 2 |
import yfinance as yf
|
| 3 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
-
|
| 6 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 7 |
try:
|
| 8 |
-
|
| 9 |
-
|
|
|
|
|
|
|
| 10 |
if not info:
|
| 11 |
-
|
| 12 |
-
else:
|
| 13 |
-
long_summary = info.pop("longBusinessSummary", None)
|
| 14 |
-
officers = info.pop("companyOfficers", None)
|
| 15 |
-
|
| 16 |
-
# Categories
|
| 17 |
-
info_categories = {
|
| 18 |
-
"Company Overview": [
|
| 19 |
-
"longName", "symbol", "exchange", "quoteType", "sector", "industry",
|
| 20 |
-
"fullTimeEmployees", "website", "address1", "city", "state", "zip", "country", "phone"
|
| 21 |
-
],
|
| 22 |
-
"Valuation Metrics": [
|
| 23 |
-
"marketCap", "enterpriseValue", "trailingPE", "forwardPE", "pegRatio",
|
| 24 |
-
"priceToSalesTrailing12Months", "enterpriseToRevenue", "enterpriseToEbitda"
|
| 25 |
-
],
|
| 26 |
-
"Key Financials": [
|
| 27 |
-
"fiftyTwoWeekHigh", "fiftyTwoWeekLow", "fiftyDayAverage", "twoHundredDayAverage",
|
| 28 |
-
"trailingAnnualDividendRate", "trailingAnnualDividendYield", "dividendRate", "dividendYield",
|
| 29 |
-
"exDividendDate", "lastSplitFactor", "lastSplitDate", "lastDividendValue", "payoutRatio",
|
| 30 |
-
"beta", "sharesOutstanding", "impliedSharesOutstanding"
|
| 31 |
-
],
|
| 32 |
-
"Operational Details": [
|
| 33 |
-
"auditRisk", "boardRisk", "compensationRisk", "shareHolderRightsRisk", "overallRisk",
|
| 34 |
-
"governanceEpochDate", "compensationAsOfEpochDate"
|
| 35 |
-
],
|
| 36 |
-
"Trading Information": [
|
| 37 |
-
"open", "previousClose", "dayLow", "dayHigh", "volume", "averageVolume", "averageVolume10days",
|
| 38 |
-
"fiftyTwoWeekChange", "SandP52WeekChange", "currency", "regularMarketDayLow",
|
| 39 |
-
"regularMarketDayHigh", "regularMarketOpen", "regularMarketPreviousClose",
|
| 40 |
-
"regularMarketPrice", "regularMarketVolume", "regularMarketChange", "regularMarketChangePercent"
|
| 41 |
-
],
|
| 42 |
-
"Analyst & Target": [
|
| 43 |
-
"targetMeanPrice", "numberOfAnalystOpinions", "recommendationKey", "recommendationMean"
|
| 44 |
-
]
|
| 45 |
-
}
|
| 46 |
|
| 47 |
-
|
| 48 |
-
|
| 49 |
-
|
| 50 |
-
|
| 51 |
-
|
| 52 |
-
|
| 53 |
-
|
| 54 |
-
|
| 55 |
-
|
| 56 |
-
|
| 57 |
-
|
| 58 |
-
elif isinstance(value, (int, float)):
|
| 59 |
-
if 'percent' in key.lower() or 'ratio' in key.lower() or 'yield' in key.lower() or 'beta' in key.lower() or 'payoutRatio' in key.lower():
|
| 60 |
-
value = f"{value:.2%}"
|
| 61 |
-
elif 'price' in key.lower() or 'dividend' in key.lower() or 'average' in key.lower():
|
| 62 |
-
value = f"{value:.2f}"
|
| 63 |
-
else:
|
| 64 |
-
value = f"{value:,.0f}"
|
| 65 |
-
category_key_value_html += f"<div class='key-value-pair'><h3>{key.replace('_',' ').title()}</h3><p>{value}</p></div>"
|
| 66 |
-
if category_key_value_html:
|
| 67 |
-
categorized_html += f"<h2>{category_name}</h2><div class='card'><div class='card-content-grid'>{category_key_value_html}</div></div>"
|
| 68 |
|
| 69 |
-
|
| 70 |
-
|
| 71 |
-
|
| 72 |
-
|
| 73 |
-
|
| 74 |
-
|
| 75 |
-
|
| 76 |
-
|
| 77 |
-
|
| 78 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
| 79 |
|
| 80 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 81 |
|
| 82 |
-
|
| 83 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 84 |
|
| 85 |
-
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
# ============================
|
| 2 |
+
# info.py — Company Info Page
|
| 3 |
+
# EXACT SAME LOOK AS BEFORE
|
| 4 |
+
# ============================
|
| 5 |
+
|
| 6 |
import yfinance as yf
|
| 7 |
+
import pandas as pd
|
| 8 |
+
import traceback
|
| 9 |
+
|
| 10 |
+
from common import (
|
| 11 |
+
format_number,
|
| 12 |
+
format_large_number,
|
| 13 |
+
make_table,
|
| 14 |
+
html_card,
|
| 15 |
+
html_section,
|
| 16 |
+
html_error,
|
| 17 |
+
clean_df,
|
| 18 |
+
safe_get
|
| 19 |
+
)
|
| 20 |
|
| 21 |
+
|
| 22 |
+
def fetch_info(symbol: str):
|
| 23 |
+
"""
|
| 24 |
+
Fetch full company info and return the SAME layout you used earlier.
|
| 25 |
+
Only internal code updated to use common.py helpers.
|
| 26 |
+
"""
|
| 27 |
try:
|
| 28 |
+
yf_symbol = f"{symbol}.NS"
|
| 29 |
+
tk = yf.Ticker(yf_symbol)
|
| 30 |
+
info = tk.info
|
| 31 |
+
|
| 32 |
if not info:
|
| 33 |
+
return html_error(f"No information found for {symbol}")
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 34 |
|
| 35 |
+
# ===== BASIC DETAILS =====
|
| 36 |
+
basic = {
|
| 37 |
+
"Symbol": symbol,
|
| 38 |
+
"Name": safe_get(info, "longName"),
|
| 39 |
+
"Sector": safe_get(info, "sector"),
|
| 40 |
+
"Industry": safe_get(info, "industry"),
|
| 41 |
+
"Website": safe_get(info, "website"),
|
| 42 |
+
"Employee Count": format_large_number(safe_get(info, "fullTimeEmployees")),
|
| 43 |
+
}
|
| 44 |
+
df_basic = pd.DataFrame(basic.items(), columns=["Field", "Value"])
|
| 45 |
+
basic_html = make_table(df_basic)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 46 |
|
| 47 |
+
# ===== PRICE DETAILS =====
|
| 48 |
+
price_info = {
|
| 49 |
+
"Current Price": format_number(safe_get(info, "currentPrice")),
|
| 50 |
+
"Previous Close": format_number(safe_get(info, "previousClose")),
|
| 51 |
+
"Open": format_number(safe_get(info, "open")),
|
| 52 |
+
"Day High": format_number(safe_get(info, "dayHigh")),
|
| 53 |
+
"Day Low": format_number(safe_get(info, "dayLow")),
|
| 54 |
+
"52W High": format_number(safe_get(info, "fiftyTwoWeekHigh")),
|
| 55 |
+
"52W Low": format_number(safe_get(info, "fiftyTwoWeekLow")),
|
| 56 |
+
"Volume": format_large_number(safe_get(info, "volume")),
|
| 57 |
+
"Avg Volume": format_large_number(safe_get(info, "averageVolume")),
|
| 58 |
+
}
|
| 59 |
+
df_price = pd.DataFrame(price_info.items(), columns=["Field", "Value"])
|
| 60 |
+
price_html = make_table(df_price)
|
| 61 |
|
| 62 |
+
# ===== VALUATION METRICS =====
|
| 63 |
+
valuation = {
|
| 64 |
+
"Market Cap": format_large_number(safe_get(info, "marketCap")),
|
| 65 |
+
"PE Ratio": format_number(safe_get(info, "trailingPE")),
|
| 66 |
+
"EPS": format_number(safe_get(info, "trailingEps")),
|
| 67 |
+
"PB Ratio": format_number(safe_get(info, "priceToBook")),
|
| 68 |
+
"Dividend Yield": format_number(safe_get(info, "dividendYield")),
|
| 69 |
+
"ROE": format_number(safe_get(info, "returnOnEquity")),
|
| 70 |
+
"ROA": format_number(safe_get(info, "returnOnAssets")),
|
| 71 |
+
}
|
| 72 |
+
df_val = pd.DataFrame(valuation.items(), columns=["Field", "Value"])
|
| 73 |
+
val_html = make_table(df_val)
|
| 74 |
|
| 75 |
+
# ===== COMPANY EXTRA DETAILS =====
|
| 76 |
+
extra = {
|
| 77 |
+
"Beta": format_number(safe_get(info, "beta")),
|
| 78 |
+
"Revenue": format_large_number(safe_get(info, "totalRevenue")),
|
| 79 |
+
"Gross Margins": format_number(safe_get(info, "grossMargins")),
|
| 80 |
+
"Operating Margins": format_number(safe_get(info, "operatingMargins")),
|
| 81 |
+
"Profit Margins": format_number(safe_get(info, "profitMargins")),
|
| 82 |
+
"Book Value": format_number(safe_get(info, "bookValue")),
|
| 83 |
+
}
|
| 84 |
+
df_extra = pd.DataFrame(extra.items(), columns=["Field", "Value"])
|
| 85 |
+
extra_html = make_table(df_extra)
|
| 86 |
+
|
| 87 |
+
# ========================
|
| 88 |
+
# Final HTML (Same Layout)
|
| 89 |
+
# ========================
|
| 90 |
+
final_html = (
|
| 91 |
+
html_card("Basic Information", basic_html)
|
| 92 |
+
+ html_card("Price Details", price_html)
|
| 93 |
+
+ html_card("Valuation Metrics", val_html)
|
| 94 |
+
+ html_card("Additional Company Data", extra_html)
|
| 95 |
+
)
|
| 96 |
|
| 97 |
+
return final_html
|
| 98 |
+
|
| 99 |
+
except Exception as e:
|
| 100 |
+
return html_error(f"INFO MODULE ERROR: {e}<br><pre>{traceback.format_exc()}</pre>")
|