virattt/ai-hedge-fund · warning · InsufficientData

{ticker} as of {as_of}: only {len(metrics)} filed periods (n

Error message

{ticker} as of {as_of}: only {len(metrics)} filed periods (need {MIN_PERIODS})

What it means

Raised by build_snapshot (hedge_fund/features/snapshot.py:134) when fewer than MIN_PERIODS (=4) filed financial-metrics periods exist for the ticker as of the given date. The point-in-time snapshot needs a multi-period history to compute trends, so thin coverage is a hard stop, not a neutral view. It raises the dedicated InsufficientData (a ValueError subclass) so callers can distinguish 'this stock is too new' from real data failures.

Source

Thrown at hedge_fund/features/snapshot.py:134


def build_snapshot(
    ticker: str,
    as_of: str,
    data_client: DataClient,
    periods: int = 20,
) -> FundamentalsSnapshot:
    """Build the point-in-time snapshot for (ticker, as_of).

    Raises InsufficientData if fewer than MIN_PERIODS filed periods exist.
    Data-layer failures propagate (fail loud) — a broken snapshot must never
    silently become a neutral view.
    """
    metrics = data_client.get_financial_metrics(
        ticker, as_of, period="ttm", limit=periods,
    )
    if len(metrics) < MIN_PERIODS:
        raise InsufficientData(
            f"{ticker} as of {as_of}: only {len(metrics)} filed periods "
            f"(need {MIN_PERIODS})"
        )

    # Market cap comes from the most recent FILED metrics row. Deliberately
    # NOT data_client.get_market_cap(): that prefers company_facts.market_cap,
    # which is latest-only — lookahead in a backtest.
    facts = data_client.get_company_facts(ticker)

    rows = [
        PeriodFundamentals(**m.model_dump(include=set(PeriodFundamentals.model_fields)))
        for m in metrics
    ]

    return FundamentalsSnapshot(
        ticker=ticker,
        as_of=as_of,
        # Sector/industry are slow-moving company attributes; using latest

View on GitHub (pinned to eff8a7320f)

Solutions

  1. Catch InsufficientData per ticker in the pipeline and skip that name for that cycle (treat as TickerSkip), rather than letting it kill the whole run.
  2. Shift the backtest start date to at least 4 quarters after the ticker's first filing.
  3. Remove the thin-coverage ticker from the universe if it will never have history (delisted before the window).
  4. Increase the requested periods or verify coverage first with a direct get_financial_metrics call before adding the ticker to the universe.

Example fix

# before
snap = build_snapshot(data_client, ticker, as_of)  # IPO'd 3 quarters ago -> crashes the cycle

# after
from hedge_fund.features.snapshot import build_snapshot, InsufficientData

try:
    snap = build_snapshot(data_client, ticker, as_of)
except InsufficientData:
    skipped.append(TickerSkip(ticker=ticker, reason="insufficient filing history"))
    continue
Defensive patterns

Strategy: try-catch

Validate before calling

MIN_PERIODS = 4  # keep in sync with hedge_fund.features.snapshot

def has_enough_history(client, ticker: str, as_of: str) -> bool:
    try:
        rows = client.get_financial_metrics(ticker, as_of, period="ttm", limit=20)
    except Exception:
        return False  # let the real error surface later; this is only a pre-check
    return len(rows) >= MIN_PERIODS

Type guard

from hedge_fund.features.snapshot import InsufficientData

def is_insufficient_history(e: BaseException) -> bool:
    return isinstance(e, InsufficientData)

Try / catch

from hedge_fund.features.snapshot import build_snapshot, InsufficientData

try:
    snap = build_snapshot(data_client, ticker, as_of)
except InsufficientData:
    skips.append(TickerSkip(ticker=ticker, reason="insufficient filing history"))
    continue  # skip the name for this cycle, keep the run alive
except FDClientError:
    raise  # data-layer failures are infrastructure: never swallow

Prevention

When it happens

Trigger: Calling data_client.get_financial_metrics(ticker, as_of, period='ttm', limit=periods) for: a recently IPO'd company with <4 quarters filed; a ticker that delisted before as_of; a foreign filer with sparse coverage on the provider; as_of dates earlier than the company's first filings. Note a provider outage would raise FDClientError instead — this error means the API answered with real, but too few, rows.

Common situations: Backtests whose start date predates a company's IPO (e.g. universe includes a 2021 listing but the window starts 2019); SPACs and recent IPOs in the universe; tiny OTC tickers the provider barely covers; survivorship-biased ticker lists containing dead tickers.

Related errors


AI-assisted analysis of virattt/ai-hedge-fund@eff8a7320f (2026-08-15). Data as JSON: /api/errors/450d6016c4cee111. Report an issue: GitHub.