"""Symbol normalization must apply on every yfinance path, not just price fetch. Regression tests for #983 (instrument identity), #984 (reflection returns), and the news path: a broker symbol like XAUUSD must resolve to the same Yahoo symbol (GC=F) that the price path uses, so identity, realized-return, and news lookups hit the right instrument instead of failing/mismatching. """ import pandas as pd import tradingagents.agents.utils.agent_utils as au import tradingagents.dataflows.yfinance_news as ynews import tradingagents.graph.trading_graph as tg from tradingagents.graph.trading_graph import TradingAgentsGraph def test_identity_lookup_normalizes_symbol(monkeypatch): seen = {} class FakeTicker: def __init__(self, symbol): seen["symbol"] = symbol @property def info(self): return {"longName": "Gold Futures", "quoteType": "FUTURE"} monkeypatch.setattr(au.yf, "Ticker", FakeTicker) au.resolve_instrument_identity.cache_clear() identity = au.resolve_instrument_identity("XAUUSD") assert seen["symbol"] == "GC=F" # normalized, not the raw broker symbol assert identity.get("company_name") == "Gold Futures" def test_fetch_returns_normalizes_symbol(monkeypatch): queried = [] class FakeTicker: def __init__(self, symbol): queried.append(symbol) def history(self, *args, **kwargs): return pd.DataFrame({"Close": [100.0, 101.0, 102.0, 103.0, 104.0, 105.0, 106.0]}) monkeypatch.setattr(tg.yf, "Ticker", FakeTicker) # _fetch_returns does not use ``self``; call unbound to avoid building the graph. raw, alpha, days = TradingAgentsGraph._fetch_returns( None, "XAUUSD", "2025-01-02", holding_days=5, benchmark="SPY" ) assert queried[0] == "GC=F" # stock symbol normalized (#984) assert queried[1] == "SPY" # benchmark left as the canonical symbol assert raw is not None and days is not None def test_news_lookup_normalizes_symbol(monkeypatch): seen = {} class FakeTicker: def __init__(self, symbol): seen["symbol"] = symbol def get_news(self, count): return [] monkeypatch.setattr(ynews.yf, "Ticker", FakeTicker) monkeypatch.setattr(ynews, "yf_retry", lambda fn: fn()) out = ynews.get_news_yfinance("XAUUSD", "2025-01-01", "2025-01-10") assert seen["symbol"] == "GC=F" # news queried with the canonical symbol assert "XAUUSD" in out # the user's ticker stays in the report assert "GC=F" in out # provenance noted