TauricResearch/TradingAgents · warning · NoMarketDataError
latest row is {latest.date()}, {stale_days} days before the
Error message
latest row is {latest.date()}, {stale_days} days before the requested {requested.date()} (stale) — refusing to use it What it means
Raised by the staleness guard in tradingagents/dataflows/stockstats_utils.py when the newest OHLCV row (after normalization) is more than max_stale_days before the requested curr_date. It is a NoMarketDataError carrying (symbol, canonical, detail) — the router converts it into the explicit NO_DATA_AVAILABLE sentinel telling the agent not to fabricate values, rather than silently feeding year-old prices into indicators (#1021).
Source
Thrown at tradingagents/dataflows/stockstats_utils.py:123
it like any other "no usable data from this vendor" — try the next vendor,
then emit one clear unavailable signal. Empty frames are left to the
caller's existing no-data handling; this guards only the dangerous case of
present-but-stale rows (a vendor returning a year-old frame that would
otherwise feed wrong prices to the agent, #1021).
"""
if data is None or data.empty:
return
requested = pd.to_datetime(curr_date, errors="coerce")
if pd.isna(requested):
return
requested = requested.normalize()
dates = _coerce_ohlcv_dates(data)
if dates.empty:
return
latest = dates.max().normalize()
stale_days = (requested - latest).days
if stale_days > max_stale_days:
raise NoMarketDataError(
symbol,
canonical,
f"latest row is {latest.date()}, {stale_days} days before the "
f"requested {requested.date()} (stale) — refusing to use it",
)
def _needs_same_day_refresh(data_file, curr_date_dt, today_date) -> bool:
"""Whether a cached frame must be refetched to reflect the requested day.
The cache file is keyed per day, so without this a run started before the
day's bar was final keeps serving that snapshot to every later run (#1150).
Two distinct staleness cases exist for a current-day request: the bar may be
missing entirely, or present but still in progress — Yahoo publishes a
partial daily candle during market hours, whose ``Close`` is not the closing
price. Row inspection cannot tell a partial bar from a final one, so the TTL
governs every current-day cache. Historical requests always reuse the cache,
since those rows are immutable.View on GitHub (pinned to a33fd4c0f1)
Solutions
- Tune the tolerance: pass/raise max_stale_days appropriate to the market calendar (e.g. >= 4 days covers long weekends)
- Refresh the cache for the requested date: delete the symbol's cached CSV so the next call refetches up to curr_date
- Align curr_date to the last actual trading day (e.g. previous business day) instead of a weekend/holiday date
- Handle NoMarketDataError (or the returned NO_DATA_AVAILABLE sentinel string) by skipping or reporting unavailable instead of retrying — it is a data verdict, not a transient failure
Example fix
# before
get_stock_data_indicators_window_sma("HALTED", "2025-06-10", 10, 10)
# -> NoMarketDataError: ... latest row is 2025-05-20, 21 days before the requested 2025-06-10 (stale)
# after
# align to a real trading day and widen tolerance for weekends
get_stock_data_indicators_window_sma("SPY", "2025-06-10", 10, 10, max_stale_days=5)
from tradingagents.dataflows.errors import NoMarketDataError
try: ...
except NoMarketDataError as e: report_unavailable(e.symbol) Defensive patterns
Strategy: validation
Validate before calling
import pandas as pd
from tradingagents.dataflows.stockstats_utils import load_ohlcv, _coerce_ohlcv_dates
def fresh_enough(symbol: str, curr_date: str, max_stale_days: int) -> bool:
data = load_ohlcv(symbol, curr_date)
if data is None or data.empty:
return False
dates = _coerce_ohlcv_dates(data)
if dates.empty:
return False
latest = dates.max().normalize()
return (pd.to_datetime(curr_date).normalize() - latest).days <= max_stale_days Try / catch
from tradingagents.dataflows.errors import NoMarketDataError
try:
out = get_stock_data_indicators_window_sma(sym, curr_date, 10, 10)
except NoMarketDataError as e:
# stale data is a verdict, not a transient error: skip/report, don't retry blindly
log_unavailable(e.symbol, e.detail) Prevention
- Set max_stale_days with the market calendar in mind (weekends, holidays = 3-4+ days)
- Align curr_date to actual trading days in backtests
- Refresh per-day caches when rerunning later dates; don't reuse a morning snapshot for evening runs
When it happens
Trigger: Requesting curr_date=today on a symbol whose cache ends weeks earlier (e.g. a halted/delisted stock); weekend/holiday requests beyond max_stale_days; a cache file written mid-run before the day's bar existed (#1150) being reused for a later date; non-US calendars where the last trading day is far back.
Common situations: Backtests crossing market holidays; symbols with sparse trading (some OTC/ETCs); stale per-day cache files; analysts asking for 'today' data on a long weekend.
Related errors
- No OHLCV rows on or before {curr_date} for {symbol}.
- No OHLCV data available for {symbol}.
- Yahoo Finance returned no rows
AI-assisted analysis of TauricResearch/TradingAgents@a33fd4c0f1 (2026-08-14).
Data as JSON: /api/errors/1d83f2834030076d.
Report an issue: GitHub.