feat: saxo

This commit is contained in:
OpenSquared
2026-07-18 23:14:16 +02:00
parent d535d0bea1
commit 8fe18a8ff9
3 changed files with 26 additions and 2 deletions

View File

@@ -6169,6 +6169,15 @@ def get_saxo_catalog(asset_type: Optional[str] = None, q: Optional[str] = None,
return [dict(r) for r in rows]
def get_saxo_catalog_by_symbol(symbol: str) -> Optional[Dict[str, Any]]:
conn = get_conn()
row = conn.execute(
"SELECT * FROM saxo_instrument_catalog WHERE symbol = ? COLLATE NOCASE LIMIT 1", (symbol,)
).fetchone()
conn.close()
return dict(row) if row else None
def get_saxo_catalog_summary() -> List[Dict[str, Any]]:
conn = get_conn()
rows = conn.execute("""

View File

@@ -117,6 +117,20 @@ def resolve_instrument(symbol: str, asset_types: str = _OPTION_ASSET_TYPES) -> D
if cache_key in _root_uic_cache:
return _root_uic_cache[cache_key]
# Fast path: exchange-suffixed catalog symbols (e.g. "EUU:XCME", "OG:xcme") are Saxo
# identifiers, not natural-language search terms — Saxo's free-text Keywords search
# isn't reliable for them. If we already cached this exact symbol via a catalog
# refresh, use its known Uic directly instead of re-searching live.
from services.database import get_saxo_catalog_by_symbol
cached_entry = get_saxo_catalog_by_symbol(symbol)
if cached_entry:
result = {
"uic": cached_entry["uic"], "symbol": cached_entry["symbol"],
"description": cached_entry["description"], "asset_type": cached_entry["asset_type"],
}
_root_uic_cache[cache_key] = result
return result
data = _get("/ref/v1/instruments", {"Keywords": symbol, "AssetTypes": asset_types})
items = data.get("Data") or data.get("data") or []
if not items: