"""Symbol normalization and market detection."""
from typing import Optional, Literal
MarketType = Literal["US", "HK", "CN_SH", "CN_SZ", "UNKNOWN"]
def detect_market(symbol: str) -> MarketType:
"""
Detect market from symbol format.
Examples:
AAPL -> US
0700.HK -> HK
600519.SS -> CN_SH (Shanghai)
000001.SZ -> CN_SZ (Shenzhen)
"""
symbol_upper = symbol.upper()
if ".HK" in symbol_upper:
return "HK"
elif ".SS" in symbol_upper:
return "CN_SH"
elif ".SZ" in symbol_upper:
return "CN_SZ"
elif "." not in symbol_upper:
# Assume US if no suffix
return "US"
else:
return "UNKNOWN"
def normalize_symbol_for_yahoo(symbol: str) -> str:
"""
Normalize symbol for Yahoo Finance.
Yahoo uses:
- US: AAPL
- HK: 0700.HK
- Shanghai: 600519.SS
- Shenzhen: 000001.SZ
"""
# Yahoo format is already standard
return symbol.upper()
def normalize_symbol_for_finnhub(symbol: str) -> str:
"""
Normalize symbol for Finnhub.
Finnhub may use different formats for some markets.
For now, we try the same format and let the API handle it.
"""
# Try direct symbol first
return symbol.upper()
def get_market_display_name(market: MarketType) -> str:
"""Get human-readable market name."""
market_names = {
"US": "United States",
"HK": "Hong Kong",
"CN_SH": "Shanghai",
"CN_SZ": "Shenzhen",
"UNKNOWN": "Unknown"
}
return market_names.get(market, "Unknown")
def get_finnhub_exchange(market: MarketType) -> Optional[str]:
"""Get Finnhub exchange code for market."""
exchange_map = {
"US": "US",
"HK": "HK",
"CN_SH": "SS",
"CN_SZ": "SZ",
}
return exchange_map.get(market)