diff --git a/tests/test_news_lookahead.py b/tests/test_news_lookahead.py index c55f2ed8d..367566edc 100644 --- a/tests/test_news_lookahead.py +++ b/tests/test_news_lookahead.py @@ -11,6 +11,7 @@ from datetime import datetime, timezone import pytest import tradingagents.dataflows.yfinance_news as ynews +from tradingagents.dataflows.date_window import in_window def _epoch(date_str): @@ -36,16 +37,16 @@ def test_window_excludes_future_and_undated_in_backtest(): end = datetime(2025, 5, 9) # historical window (well in the past) inside = datetime(2025, 5, 5) future = datetime(2025, 6, 1) - assert ynews._in_news_window(inside, start, end) is True - assert ynews._in_news_window(future, start, end) is False # look-ahead blocked - assert ynews._in_news_window(None, start, end) is False # undated -> excluded in backtest + assert in_window(inside, start, end) is True + assert in_window(future, start, end) is False # look-ahead blocked + assert in_window(None, start, end) is False # undated -> excluded in backtest @pytest.mark.unit def test_window_keeps_undated_in_live_window(): # Live window (reaches today): undated articles can't be "future", so keep them. now = datetime.now(timezone.utc) - assert ynews._in_news_window(None, now, now) is True + assert in_window(None, now, now) is True @pytest.mark.unit @@ -56,8 +57,8 @@ def test_upper_bound_is_exclusive(): end = datetime(2025, 5, 9) midnight_after = datetime(2025, 5, 10, 0, 0, 0, tzinfo=timezone.utc) last_moment = datetime(2025, 5, 9, 23, 59, 59, tzinfo=timezone.utc) - assert ynews._in_news_window(midnight_after, start, end) is False - assert ynews._in_news_window(last_moment, start, end) is True + assert in_window(midnight_after, start, end) is False + assert in_window(last_moment, start, end) is True @pytest.mark.unit @@ -67,7 +68,7 @@ def test_offset_aware_timestamp_is_converted_not_truncated(): start = datetime(2025, 5, 1) end = datetime(2025, 5, 9) aware = datetime.fromisoformat("2025-05-10T01:00:00+05:00") - assert ynews._in_news_window(aware, start, end) is True + assert in_window(aware, start, end) is True @pytest.mark.unit diff --git a/tradingagents/dataflows/yfinance_news.py b/tradingagents/dataflows/yfinance_news.py index ac036148a..9891d7947 100644 --- a/tradingagents/dataflows/yfinance_news.py +++ b/tradingagents/dataflows/yfinance_news.py @@ -60,11 +60,6 @@ def _extract_article_data(article: dict) -> dict: } -def _in_news_window(pub_date, start_dt, end_dt) -> bool: - """Look-ahead-safe article-window check; see dataflows.date_window.in_window.""" - return in_window(pub_date, start_dt, end_dt) - - def get_news_yfinance( ticker: str, start_date: str, @@ -105,7 +100,7 @@ def get_news_yfinance( data = _extract_article_data(article) # Keep only articles within the requested window (look-ahead safe). - if not _in_news_window(data["pub_date"], start_dt, end_dt): + if not in_window(data["pub_date"], start_dt, end_dt): continue news_str += f"### {data['title']} (source: {data['publisher']})\n" @@ -192,7 +187,7 @@ def get_global_news_yfinance( # Extract uniformly (flat + nested) and apply the same look-ahead-safe # window filter, so flat articles can't leak future news (#1007). data = _extract_article_data(article) - if not _in_news_window(data["pub_date"], start_dt, curr_dt): + if not in_window(data["pub_date"], start_dt, curr_dt): continue news_str += f"### {data['title']} (source: {data['publisher']})\n" if data["summary"]: diff --git a/tradingagents/graph/signal_processing.py b/tradingagents/graph/signal_processing.py index 09b43f6bb..57f72178c 100644 --- a/tradingagents/graph/signal_processing.py +++ b/tradingagents/graph/signal_processing.py @@ -21,10 +21,10 @@ class SignalProcessor: """Read the 5-tier rating out of a Portfolio Manager decision.""" def __init__(self, quick_thinking_llm: Any = None): - # The LLM argument is accepted for backwards compatibility but no - # longer used: the PM's structured output guarantees the rating is - # parseable from the rendered markdown without a second LLM call. - self.quick_thinking_llm = quick_thinking_llm + # The LLM argument is accepted for backwards compatibility but ignored: + # the PM's structured output guarantees the rating is parseable from the + # rendered markdown without a second LLM call, so it is not stored. + pass def process_signal(self, full_signal: str) -> str: """Return one of Buy / Overweight / Hold / Underweight / Sell, or REVIEW.