refactor: name the data layer's date argument as_of_date

- vendor functions and date_window take as_of_date, the date data is served as of; the model-facing tool arguments are unchanged
- build_instrument_context and resolve_instrument_context take trade_date, which is what they receive
This commit is contained in:
Yijia-Xiao
2026-09-24 19:38:41 +00:00
parent 5ac5786d0d
commit 674f1087d1
19 changed files with 165 additions and 165 deletions
+2 -2
View File
@@ -82,7 +82,7 @@ def test_fundamentals_look_ahead_filter_runs_on_json_string(monkeypatch):
# #1115: the payload arrives as a JSON *string*; the old dict-only guard let
# future-dated fiscal periods leak into historical runs.
monkeypatch.setattr(avf, "_make_api_request", lambda fn, params: _FUNDAMENTALS_JSON)
out = avf.get_balance_sheet("AAPL", curr_date="2024-01-01")
out = avf.get_balance_sheet("AAPL", as_of_date="2024-01-01")
assert isinstance(out, str) # callers still receive a str
parsed = json.loads(out)
assert [r["fiscalDateEnding"] for r in parsed["annualReports"]] == ["2023-12-31"]
@@ -98,7 +98,7 @@ def test_fundamentals_no_curr_date_passes_through(monkeypatch):
@pytest.mark.unit
def test_fundamentals_non_json_body_unchanged(monkeypatch):
monkeypatch.setattr(avf, "_make_api_request", lambda fn, params: "not-json")
assert avf.get_cashflow("AAPL", curr_date="2024-01-01") == "not-json"
assert avf.get_cashflow("AAPL", as_of_date="2024-01-01") == "not-json"
# ---------------------------------------------------------------------------
+6 -6
View File
@@ -141,7 +141,7 @@ class FredFormattingTests(unittest.TestCase):
self.assertEqual(len(body_rows), fred.MAX_ROWS)
def test_window_is_lookahead_safe(self):
# observation_end must equal curr_date so a past date never pulls future data.
# observation_end must equal as_of_date so a past date never pulls future data.
captured = {}
def _capture(path, params):
@@ -156,9 +156,9 @@ class FredFormattingTests(unittest.TestCase):
def test_requests_pin_the_data_vintage(self):
# #1275: both the metadata and observations requests must pin the vintage
# to curr_date (clamped to FRED's today), or FRED serves the latest
# to as_of_date (clamped to FRED's today), or FRED serves the latest
# revision and revision-prone series leak future information. A past
# curr_date sits below FRED's today, so it pins through unchanged.
# as_of_date sits below FRED's today, so it pins through unchanged.
captured = {}
def _capture(path, params):
@@ -174,11 +174,11 @@ class FredFormattingTests(unittest.TestCase):
self.assertEqual(captured[path]["realtime_end"], "2025-09-30", path)
def test_future_curr_date_clamps_vintage_to_fred_today(self):
# #1275 regression: on a live run curr_date is the caller's LOCAL date,
# #1275 regression: on a live run as_of_date is the caller's LOCAL date,
# which can be a day ahead of FRED's US-Central clock. Pinning the vintage
# to that future date 400s, and the routing layer then drops macro data
# silently. The pin must clamp to FRED's today; the observation window
# (future bars can't exist yet) stays at curr_date.
# (future bars can't exist yet) stays at as_of_date.
captured = {}
def _capture(path, params):
@@ -192,7 +192,7 @@ class FredFormattingTests(unittest.TestCase):
for path in ("series", "series/observations"):
self.assertEqual(captured[path]["realtime_start"], "2026-08-31", path)
self.assertEqual(captured[path]["realtime_end"], "2026-08-31", path)
# the observation window still tracks curr_date, not the clamped vintage
# the observation window still tracks as_of_date, not the clamped vintage
self.assertEqual(captured["series/observations"]["observation_end"], "2026-09-01")
+5 -5
View File
@@ -10,7 +10,7 @@ FRED (#1275), social (#1220) and memory (#1251) leaks.
Both vendors withhold on one shared rule (``date_window.withhold_live_profile``)
so switching ``fundamental_data`` between them cannot reintroduce the leak. The
statement tools stay point-in-time by filtering on ``curr_date``, and a live run
statement tools stay point-in-time by filtering on ``as_of_date``, and a live run
is unchanged. All API access is mocked.
"""
from __future__ import annotations
@@ -45,19 +45,19 @@ _LEAKY = ("3500000000000", "34.2", "260.1", "391000000000",
"Apple Inc.", "Technology", "Consumer Electronics")
def _yf(curr_date, info=_INFO, today=_TODAY):
def _yf(as_of_date, info=_INFO, today=_TODAY):
with mock.patch.object(date_window, "get_current_date", return_value=today), \
mock.patch.object(yahoo_fundamentals, "yf_retry", lambda fn: info), \
mock.patch.object(yahoo_market.yf, "Ticker"):
return yahoo_fundamentals.get_fundamentals("AAPL", curr_date)
return yahoo_fundamentals.get_fundamentals("AAPL", as_of_date)
def _av(curr_date, today=_TODAY):
def _av(as_of_date, today=_TODAY):
"""Alpha Vantage path; the API call is mocked so a leak would be visible."""
with mock.patch.object(date_window, "get_current_date", return_value=today), \
mock.patch.object(av, "_make_api_request",
return_value="MarketCapitalization: 3500000000000") as req:
return av.get_fundamentals("AAPL", curr_date), req
return av.get_fundamentals("AAPL", as_of_date), req
@pytest.mark.unit
+1 -1
View File
@@ -102,4 +102,4 @@ def test_an_unreachable_yahoo_is_not_reported_as_a_symbol_without_insider_data()
with mock.patch.object(fundamentals.yf, "Ticker", return_value=ticker), \
mock.patch.object(fundamentals, "vendor_reachable", return_value=False), \
pytest.raises(VendorRateLimitError):
fundamentals.get_insider_transactions("AAPL", curr_date="2026-09-21")
fundamentals.get_insider_transactions("AAPL", as_of_date="2026-09-21")
+5 -5
View File
@@ -70,14 +70,14 @@ def test_alpha_vantage_insider_filings_after_the_date_are_dropped():
@pytest.mark.unit
def test_polymarket_withholds_live_odds_from_a_historical_run():
with mock.patch.object(polymarket, "_request", side_effect=AssertionError("must not fetch")):
out = polymarket.get_prediction_markets("Fed rate cut", curr_date="2025-06-01")
out = polymarket.get_prediction_markets("Fed rate cut", as_of_date="2025-06-01")
assert "withheld" in out
@pytest.mark.unit
def test_polymarket_serves_a_current_run():
with mock.patch.object(polymarket, "_request", return_value={"events": []}) as req:
polymarket.get_prediction_markets("Fed rate cut", curr_date=polymarket.get_current_date())
polymarket.get_prediction_markets("Fed rate cut", as_of_date=polymarket.get_current_date())
req.assert_called_once()
@@ -103,7 +103,7 @@ def test_a_historical_run_is_told_the_identity_is_current(monkeypatch):
identity = {"company_name": "Example Corp", "sector": "Technology",
"industry": "Software", "exchange": "NMS"}
historical = build_instrument_context("EXMP", "stock", identity, curr_date="2024-03-14")
historical = build_instrument_context("EXMP", "stock", identity, trade_date="2024-03-14")
assert "Example Corp" in historical
assert "2024-03-14" in historical and "today" in historical.lower()
@@ -114,7 +114,7 @@ def test_a_current_run_is_not_cluttered_with_a_vintage_note(monkeypatch):
from tradingagents.dataflows.date_window import get_current_date
today = build_instrument_context("EXMP", "stock", {"company_name": "Example Corp"},
curr_date=get_current_date())
trade_date=get_current_date())
assert "Example Corp" in today
assert "resolved today" not in today.lower()
@@ -297,7 +297,7 @@ def test_an_unavailable_notice_names_no_date_after_the_run():
coverage_gap([pd.Timestamp(today, tz="UTC")], "2025-01-01", "2025-01-07", "Feed", "news"),
withhold_live_profile("2025-01-07", "AAPL"),
_yf_insider(_insider_frame(today), "2025-01-07"),
build_instrument_context("EXMP", "stock", {"company_name": "Example"}, curr_date="2025-01-07"),
build_instrument_context("EXMP", "stock", {"company_name": "Example"}, trade_date="2025-01-07"),
]
for notice in notices:
assert _dates_after(notice, "2025-01-07") == [], notice