""" Ticker input component for asset selection. Supports stocks, crypto, commodities, and indices. """ from typing import Dict, List, Tuple import gradio as gr from data.providers.base import DataProvider # Common tickers organized by category TICKER_EXAMPLES = { "Stocks": [ "AAPL", "MSFT", "GOOGL", "AMZN", "META", "TSLA", "NVDA", "JPM", "V", "WMT", ], "Crypto": [ "BTC-USD", "ETH-USD", "BNB-USD", "SOL-USD", "ADA-USD", ], "Commodities": [ "GC=F", # Gold "SI=F", # Silver "CL=F", # Crude Oil "NG=F", # Natural Gas ], "Indices": [ "^GSPC", # S&P 500 "^DJI", # Dow Jones "^IXIC", # NASDAQ "^VIX", # Volatility Index ], } def create_ticker_input() -> gr.Textbox: """ Create ticker input component. Returns: Gradio Textbox component for ticker input """ # Flatten examples for display all_examples = [] for category, tickers in TICKER_EXAMPLES.items(): all_examples.extend(tickers[:3]) # Top 3 from each category examples_text = ", ".join(all_examples[:10]) return gr.Textbox( label="Asset Ticker", placeholder="Enter ticker symbol (e.g., AAPL, BTC-USD, ^GSPC)", info=f"Examples: {examples_text}", value="AAPL", ) def create_ticker_examples() -> gr.Examples: """ Create examples component for quick ticker selection. Returns: Gradio Examples component """ # Format examples as list of lists for Examples component examples = [] for category, tickers in TICKER_EXAMPLES.items(): for ticker in tickers[:5]: # Top 5 from each category examples.append([ticker]) return examples def validate_ticker(ticker: str) -> tuple[bool, str]: """ Validate ticker symbol format. Args: ticker: Ticker symbol to validate Returns: Tuple of (is_valid, error_message) """ if not ticker or not ticker.strip(): return False, "Ticker symbol cannot be empty" ticker = ticker.strip().upper() # Basic validation - alphanumeric with some special chars if not all(c.isalnum() or c in ["-", "_", ".", "^", "="] for c in ticker): return False, "Invalid ticker symbol format" if len(ticker) > 20: return False, "Ticker symbol too long" return True, "" def get_ticker_category(ticker: str) -> str: """ Determine ticker category using DataProvider's asset type detection. Args: ticker: Ticker symbol Returns: Category name """ ticker = ticker.upper() # First check if it's in our examples for category, tickers in TICKER_EXAMPLES.items(): if ticker in tickers: return category # Use DataProvider's asset type detection for reliable categorization asset_type = DataProvider.detect_asset_type(ticker) # Map asset types to display categories type_to_category = { "stock": "Stocks", "crypto": "Crypto", "commodity": "Commodities", "index": "Indices", "forex": "Forex", "unknown": "Stocks", # Default to stocks for unknown } return type_to_category.get(asset_type, "Stocks") def create_categorized_ticker_input() -> Tuple[gr.Textbox, gr.Tabs]: """ Create ticker input with categorized examples in tabs. Returns: Tuple of (Textbox component, Tabs component with examples) """ ticker_input = gr.Textbox( label="Asset Ticker", placeholder="Enter ticker symbol (e.g., AAPL, BTC-USD, ^GSPC)", info="Enter any stock, crypto, commodity, or index ticker symbol", value="AAPL", ) with gr.Tabs() as tabs: for category, tickers in TICKER_EXAMPLES.items(): with gr.Tab(category): # Create description based on category if category == "Stocks": description = "Traditional equities (NYSE, NASDAQ, etc.)" elif category == "Crypto": description = "Cryptocurrencies trading 24/7 - use ticker-USD format (e.g., BTC-USD)" elif category == "Commodities": description = ( "Futures contracts - use =F suffix (e.g., GC=F for Gold)" ) elif category == "Indices": description = ( "Market indices - use ^ prefix (e.g., ^GSPC for S&P 500)" ) else: description = f"{category} assets" gr.Markdown(f"**{description}**") # Create clickable examples examples_buttons = [] for ticker in tickers: btn = gr.Button( ticker, size="sm", variant="secondary", ) examples_buttons.append(btn) # Connect button to update ticker input btn.click( fn=lambda t=ticker: t, outputs=ticker_input, ) return ticker_input, tabs def get_asset_info(ticker: str) -> Dict[str, str]: """ Get asset type information for display. Args: ticker: Ticker symbol Returns: Dictionary with asset type, category, and characteristics """ asset_type = DataProvider.detect_asset_type(ticker) asset_characteristics = DataProvider.get_asset_characteristics(asset_type) category = get_ticker_category(ticker) return { "ticker": ticker.upper(), "asset_type": asset_type, "category": category, "market_hours": asset_characteristics.get("market_hours", "Unknown"), "volatility": asset_characteristics.get("volatility", "Unknown"), "has_fundamentals": str(asset_characteristics.get("has_fundamentals", False)), }