Files
tradingagents/tests/test_symbol_normalization_paths.py
Yijia-Xiao 8db41f6bca fix(memory): gate past-context lessons to point-in-time in backtests
- get_past_context returned every resolved lesson regardless of the run date, so
  a historical run could learn from an outcome that had not happened yet
- record each resolved entry's resolution date (the last price bar used) and
  filter get_past_context(as_of=trade_date) on it for a historical run; a
  current-date run passes None so live behavior and pre-migration entries (no
  stored resolution date, conservatively excluded from backtests) are unaffected #1251
2026-08-30 07:03:06 +00:00

79 lines
2.7 KiB
Python

"""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):
prices = [100.0, 101.0, 102.0, 103.0, 104.0, 105.0, 106.0]
idx = pd.date_range(start="2025-01-02", periods=len(prices), freq="D")
return pd.DataFrame({"Close": prices}, index=idx)
monkeypatch.setattr(tg.yf, "Ticker", FakeTicker)
# _fetch_returns does not use ``self``; call unbound to avoid building the graph.
raw, alpha, days, resolved = 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
assert resolved == "2025-01-07" # resolution date recorded (#1251)
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