feat: ticker validation + SLV/USO/WEAT/CORN/TUR added to ETFs watchlist
Backend:
- GET /api/market/validate?symbol= — validates ticker against yfinance,
returns {valid, name, price} or {valid: false, reason: 'helpful message'}
- Added SLV, USO, WEAT, CORN, TUR to ETFs WATCHLIST category
Frontend:
- validateTicker() async helper exported from useApi.ts
- InstrumentPicker (PatternLab): custom ticker field now validates before selecting
Shows spinner while checking, red error message if not found on yfinance
- InstrumentLens (PatternExplorer): same validation on Go button + Enter key
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -39,6 +39,24 @@ def watchlist():
|
||||
return WATCHLIST
|
||||
|
||||
|
||||
@router.get("/validate")
|
||||
def validate_ticker(symbol: str = Query(..., description="Ticker to validate against yfinance")):
|
||||
"""Check if a ticker is fetchable. Returns valid=True + live price/name, or valid=False + reason."""
|
||||
from services.data_fetcher import get_quote
|
||||
import yfinance as yf
|
||||
symbol = symbol.strip().upper()
|
||||
q = get_quote(symbol)
|
||||
if q and q.get("price"):
|
||||
# Try to get a display name
|
||||
try:
|
||||
info = yf.Ticker(symbol).fast_info
|
||||
name = getattr(info, "long_name", None) or getattr(info, "short_name", None) or symbol
|
||||
except Exception:
|
||||
name = symbol
|
||||
return {"valid": True, "symbol": symbol, "name": name, "price": q["price"], "change_pct": q.get("change_pct")}
|
||||
return {"valid": False, "symbol": symbol, "reason": f"Ticker '{symbol}' not found on yfinance — check the symbol (e.g. GC=F for Gold, ^GSPC for S&P 500)"}
|
||||
|
||||
|
||||
@router.get("/macro-regime")
|
||||
def macro_regime(force: bool = False):
|
||||
"""Macro gauge values + 5-scenario scoring. Cached 15 min."""
|
||||
|
||||
@@ -56,24 +56,29 @@ WATCHLIST: Dict[str, List[Dict[str, str]]] = {
|
||||
{"symbol": "^VIX", "name": "VIX Volatility", "currency": "USD"},
|
||||
],
|
||||
"etfs": [
|
||||
{"symbol": "SPY", "name": "S&P 500 ETF (SPY)", "currency": "USD"},
|
||||
{"symbol": "QQQ", "name": "NASDAQ 100 ETF (QQQ)", "currency": "USD"},
|
||||
{"symbol": "IWM", "name": "Russell 2000 ETF (IWM)", "currency": "USD"},
|
||||
{"symbol": "TLT", "name": "20Y Treasury ETF (TLT)", "currency": "USD"},
|
||||
{"symbol": "IEF", "name": "7-10Y Treasury ETF (IEF)","currency": "USD"},
|
||||
{"symbol": "HYG", "name": "High Yield Bond (HYG)", "currency": "USD"},
|
||||
{"symbol": "GLD", "name": "Gold ETF (GLD)", "currency": "USD"},
|
||||
{"symbol": "EEM", "name": "EM ETF (EEM)", "currency": "USD"},
|
||||
{"symbol": "FXI", "name": "China Large Cap (FXI)", "currency": "USD"},
|
||||
{"symbol": "EWG", "name": "Germany ETF (EWG)", "currency": "USD"},
|
||||
{"symbol": "EWJ", "name": "Japan ETF (EWJ)", "currency": "USD"},
|
||||
{"symbol": "EWU", "name": "UK ETF (EWU)", "currency": "USD"},
|
||||
{"symbol": "EWZ", "name": "Brazil ETF (EWZ)", "currency": "USD"},
|
||||
{"symbol": "XLF", "name": "Financials ETF (XLF)", "currency": "USD"},
|
||||
{"symbol": "SMH", "name": "Semiconductors (SMH)", "currency": "USD"},
|
||||
{"symbol": "KWEB", "name": "China Internet (KWEB)", "currency": "USD"},
|
||||
{"symbol": "UUP", "name": "US Dollar ETF (UUP)", "currency": "USD"},
|
||||
{"symbol": "BIL", "name": "T-Bill 1-3M (BIL)", "currency": "USD"},
|
||||
{"symbol": "SPY", "name": "S&P 500 ETF (SPY)", "currency": "USD"},
|
||||
{"symbol": "QQQ", "name": "NASDAQ 100 ETF (QQQ)", "currency": "USD"},
|
||||
{"symbol": "IWM", "name": "Russell 2000 ETF (IWM)", "currency": "USD"},
|
||||
{"symbol": "TLT", "name": "20Y Treasury ETF (TLT)", "currency": "USD"},
|
||||
{"symbol": "IEF", "name": "7-10Y Treasury ETF (IEF)", "currency": "USD"},
|
||||
{"symbol": "HYG", "name": "High Yield Bond (HYG)", "currency": "USD"},
|
||||
{"symbol": "GLD", "name": "Gold ETF (GLD)", "currency": "USD"},
|
||||
{"symbol": "SLV", "name": "Silver ETF (SLV)", "currency": "USD"},
|
||||
{"symbol": "USO", "name": "Oil ETF (USO)", "currency": "USD"},
|
||||
{"symbol": "EEM", "name": "EM ETF (EEM)", "currency": "USD"},
|
||||
{"symbol": "FXI", "name": "China Large Cap (FXI)", "currency": "USD"},
|
||||
{"symbol": "EWG", "name": "Germany ETF (EWG)", "currency": "USD"},
|
||||
{"symbol": "EWJ", "name": "Japan ETF (EWJ)", "currency": "USD"},
|
||||
{"symbol": "EWU", "name": "UK ETF (EWU)", "currency": "USD"},
|
||||
{"symbol": "EWZ", "name": "Brazil ETF (EWZ)", "currency": "USD"},
|
||||
{"symbol": "XLF", "name": "Financials ETF (XLF)", "currency": "USD"},
|
||||
{"symbol": "SMH", "name": "Semiconductors (SMH)", "currency": "USD"},
|
||||
{"symbol": "KWEB", "name": "China Internet (KWEB)", "currency": "USD"},
|
||||
{"symbol": "UUP", "name": "US Dollar ETF (UUP)", "currency": "USD"},
|
||||
{"symbol": "BIL", "name": "T-Bill 1-3M (BIL)", "currency": "USD"},
|
||||
{"symbol": "TUR", "name": "Turkey ETF (TUR)", "currency": "USD"},
|
||||
{"symbol": "WEAT", "name": "Wheat ETF (WEAT)", "currency": "USD"},
|
||||
{"symbol": "CORN", "name": "Corn ETF (CORN)", "currency": "USD"},
|
||||
],
|
||||
"equities": [
|
||||
{"symbol": "XOM", "name": "Exxon Mobil", "currency": "USD"},
|
||||
|
||||
Reference in New Issue
Block a user