Files
All-in-one-Financial-Analysis/atlas-terminal/server/utils/ticker_utils.py
T
shawnkim1997 38c56a5a43 feat: deliver multi-asset analytics, OCR exchange selection, and heatmap UX
Add asset-type aware market/overview flows, portfolio OCR reverse-engineering with exchange overrides, and interactive index heatmap features. Update README with recent updates and wire backend/frontend APIs for FX matrix, exchange options, and improved portfolio editing flows.

Made-with: Cursor
2026-03-21 17:08:00 +00:00

184 lines
7.0 KiB
Python

"""Ticker formatting, market inference, and company/sector reference data.
Centralises the mapping logic that converts bare ticker symbols into
Yahoo Finance-compatible identifiers with the correct market suffix,
and provides the static lookup tables for companies and sectors.
"""
from enum import Enum
from typing import List, Tuple
# ---------------------------------------------------------------------------
# Company reference data
# ---------------------------------------------------------------------------
COMPANY_LIST: List[Tuple[str, str]] = [
("NVIDIA Corporation", "NVDA"), ("Apple Inc.", "AAPL"), ("Microsoft Corporation", "MSFT"),
("Amazon.com Inc.", "AMZN"), ("Alphabet Inc.", "GOOGL"), ("Meta Platforms Inc.", "META"),
("AMD", "AMD"), ("Intel Corporation", "INTC"), ("Qualcomm Inc.", "QCOM"), ("Tesla Inc.", "TSLA"),
("Berkshire Hathaway", "BRK.B"), ("JPMorgan Chase", "JPM"), ("Visa Inc.", "V"),
("UnitedHealth", "UNH"), ("Procter & Gamble", "PG"), ("Exxon Mobil", "XOM"),
("Johnson & Johnson", "JNJ"), ("Mastercard", "MA"), ("Chevron", "CVX"),
("Home Depot", "HD"), ("Merck", "MRK"), ("AbbVie", "ABBV"), ("Costco", "COST"),
("PepsiCo", "PEP"), ("Coca-Cola", "KO"), ("Pfizer", "PFE"), ("Walmart", "WMT"),
("Netflix", "NFLX"), ("Adobe", "ADBE"), ("Salesforce", "CRM"), ("Comcast", "CMCSA"),
("Cisco", "CSCO"), ("Oracle", "ORCL"), ("American Express", "AXP"),
("Bank of America", "BAC"), ("Wells Fargo", "WFC"), ("Verizon", "VZ"),
("AT&T", "T"), ("Walt Disney", "DIS"), ("Nike", "NKE"), ("McDonald's", "MCD"),
("Starbucks", "SBUX"), ("Goldman Sachs", "GS"), ("Morgan Stanley", "MS"),
("Target", "TGT"), ("Boeing", "BA"), ("IBM", "IBM"),
]
COMPANY_OPTIONS: List[str] = [f"{t} - {n}" for n, t in COMPANY_LIST]
"""Pre-formatted ``'TICKER - Company Name'`` strings for dropdowns."""
COMPANY_TICKER_MAP: dict[str, str] = {t: n for n, t in COMPANY_LIST}
"""Mapping from ticker symbol to full company name."""
MARKET_OPTIONS: List[str] = [
"US (S&P/Dow/Nasdaq)",
"South Korea (KOSPI/KOSDAQ)",
"Japan (Nikkei)",
"UK (LSE)",
]
class AssetType(str, Enum):
EQUITY = "equity"
ETF = "etf"
COMMODITY_FUTURE = "commodity_future"
CRYPTO = "crypto"
INDEX = "index"
COMMODITY_FUTURES: dict[str, str] = {
"GC=F": "Gold", "SI=F": "Silver", "PL=F": "Platinum", "PA=F": "Palladium",
"CL=F": "Crude Oil (WTI)", "BZ=F": "Brent Crude", "NG=F": "Natural Gas",
"HO=F": "Heating Oil", "RB=F": "Gasoline",
"ZC=F": "Corn", "ZS=F": "Soybeans", "ZW=F": "Wheat",
"KC=F": "Coffee", "CT=F": "Cotton", "SB=F": "Sugar",
"CC=F": "Cocoa", "OJ=F": "Orange Juice",
"LE=F": "Live Cattle", "HE=F": "Lean Hogs",
"HG=F": "Copper", "ALI=F": "Aluminum",
}
POPULAR_COMMODITY_ETFS: dict[str, str] = {
"GLD": "SPDR Gold Trust", "IAU": "iShares Gold Trust", "SLV": "iShares Silver Trust",
"PPLT": "abrdn Platinum ETF", "USO": "United States Oil Fund", "UNG": "United States Natural Gas Fund",
"XLE": "Energy Select Sector SPDR", "VDE": "Vanguard Energy ETF", "DBC": "Invesco DB Commodity Tracking",
"GSG": "iShares S&P GSCI Commodity", "PDBC": "Invesco Optimum Yield Diversified Commodity",
"COM": "Direxion Auspice Broad Commodity", "DBA": "Invesco DB Agriculture Fund",
"WEAT": "Teucrium Wheat Fund", "CORN": "Teucrium Corn Fund", "SOYB": "Teucrium Soybean Fund",
"SPY": "S&P 500 ETF", "QQQ": "Nasdaq 100 ETF", "IWM": "Russell 2000 ETF",
"EEM": "Emerging Markets ETF", "VWO": "Vanguard FTSE Emerging Markets",
"TLT": "20+ Year Treasury Bond ETF", "HYG": "High Yield Corporate Bond ETF",
"LQD": "Investment Grade Corporate Bond ETF", "ARKK": "ARK Innovation ETF",
"XLK": "Technology Select Sector SPDR", "XLF": "Financial Select Sector SPDR",
"XLV": "Health Care Select Sector SPDR",
}
# ---------------------------------------------------------------------------
# Sector / industry peer groups (top-down analysis)
# ---------------------------------------------------------------------------
SECTORS: dict[str, List[str]] = {
"Semiconductors & Hardware": ["NVDA", "AMD", "INTC", "TSM", "AVGO"],
"Software & Cloud": ["MSFT", "ADBE", "CRM", "PANW", "CRWD"],
"Consumer Retail": ["AMZN", "SBUX", "MCD", "WMT", "HD"],
"Financial Services": ["JPM", "BAC", "GS", "MS", "V"],
"Healthcare": ["LLY", "UNH", "JNJ", "ABBV", "MRK"],
}
# ---------------------------------------------------------------------------
# Ticker helpers
# ---------------------------------------------------------------------------
def get_global_ticker(ticker: str, market: str) -> str:
"""Append the correct Yahoo Finance suffix based on the selected market.
US tickers are returned as-is. If the ticker already carries a known
suffix (``.KS``, ``.KQ``, ``.T``, ``.L``) it is returned unchanged
regardless of the *market* argument.
Parameters
----------
ticker:
Raw ticker string entered by the user.
market:
One of the values in :data:`MARKET_OPTIONS`.
Returns
-------
str
The ticker with an appropriate suffix (or unchanged for US).
"""
if not (ticker or "").strip():
return (ticker or "").strip()
t = (ticker or "").strip()
if t.upper().endswith((".KS", ".KQ", ".T", ".L")):
return t
m = (market or "").strip()
if "US" in m or not m:
return t
if "Korea" in m or "KOSPI" in m or "KOSDAQ" in m:
return t + ".KS"
if "Japan" in m or "Nikkei" in m:
return t + ".T"
if "UK" in m or "LSE" in m:
return t + ".L"
return t
def infer_market_from_ticker(ticker: str) -> str:
"""Guess the market label from a ticker's suffix.
Useful when the caller has a fully-qualified ticker (e.g. ``005930.KS``)
but no explicit market selection.
Parameters
----------
ticker:
A ticker string that may include a market suffix.
Returns
-------
str
The best-matching entry from :data:`MARKET_OPTIONS`.
"""
if not (ticker or "").strip():
return MARKET_OPTIONS[0]
t = (ticker or "").strip().upper()
if t.endswith(".KS") or t.endswith(".KQ"):
return "South Korea (KOSPI/KOSDAQ)"
if t.endswith(".T"):
return "Japan (Nikkei)"
if t.endswith(".L"):
return "UK (LSE)"
return "US (S&P/Dow/Nasdaq)"
def detect_asset_type(ticker: str) -> AssetType:
"""Detect asset type by ticker pattern and quoteType fallback."""
t = (ticker or "").strip().upper()
if not t:
return AssetType.EQUITY
if t.endswith("=F") or t in COMMODITY_FUTURES:
return AssetType.COMMODITY_FUTURE
if t.endswith("-USD") or t.endswith("-KRW"):
return AssetType.CRYPTO
if t.startswith("^"):
return AssetType.INDEX
try:
import yfinance as yf
info = yf.Ticker(t).info or {}
quote_type = str(info.get("quoteType", "")).upper()
if quote_type in {"ETF", "MUTUALFUND"}:
return AssetType.ETF
except Exception:
pass
if t in POPULAR_COMMODITY_ETFS:
return AssetType.ETF
return AssetType.EQUITY