from __future__ import annotations from typing import Any, Dict, List, Mapping def search_symbols_catalog(symbols: Mapping[str, Any], query: str) -> Dict[str, Any]: query_lower = query.lower() results: List[Dict[str, Any]] = [] for symbol, config in symbols.items(): score = 0 if query_lower == symbol.lower(): score = 100 elif query_lower in symbol.lower(): score = 80 elif query_lower in config.label.lower(): score = 60 elif query_lower in config.label_en.lower(): score = 50 elif query_lower in config.category.lower(): score = 30 if score > 0: results.append( { "symbol": symbol, "label": config.label, "label_en": config.label_en, "category": config.category, "score": score, } ) results.sort(key=lambda item: -item["score"]) return {"query": query, "count": len(results), "results": results[:20]} def build_market_peer_candidates( symbols: Mapping[str, Any], symbol: str, limit: int, ) -> Dict[str, Any]: if symbol not in symbols: return {"category": "Unknown", "symbol": symbol, "peers": [], "count": 0} config = symbols[symbol] peers = [item for item in symbols.values() if item.category == config.category and item.symbol != symbol] if len(peers) < limit: fallback = [ item for item in symbols.values() if item.symbol not in {symbol, *(peer.symbol for peer in peers)} ] peers.extend(fallback) return { "category": config.category, "symbol": symbol, "peer_configs": peers[:limit], } def assemble_market_peer_payload( category: str, symbol: str, peer_configs: List[Any], peer_results: List[Any], ) -> Dict[str, Any]: peer_data: List[Dict[str, Any]] = [] for peer, result in zip(peer_configs, peer_results): entry = { "symbol": peer.symbol, "name": peer.label, "description": peer.description, "category": peer.category, "price": 0.0, "change_24h": 0.0, } if isinstance(result, Exception): peer_data.append(entry) continue entry["price"] = float(result.get("price", 0.0) or 0.0) entry["change_24h"] = float(result.get("change_pct", result.get("change_24h", 0.0)) or 0.0) peer_data.append(entry) return { "category": category, "symbol": symbol, "peers": peer_data, "count": len(peer_data), }