TauricResearch/TradingAgents · error · NoMarketDataError

no fundamental fields returned

Error message

no fundamental fields returned

What it means

NoMarketDataError raised by get_fundamentals when ticker.info is truthy but every interesting field (Name, Sector, PE, EPS, ...) is None. yfinance returns a stub dict like {'trailingPegRatio': None} for unknown symbols, so a bare truthiness check on info is insufficient. Treating 'no usable fields' as no data prevents emitting a bare header the agent might fabricate around.

Source

Thrown at tradingagents/dataflows/y_finance.py:328

            ("Return on Equity", info.get("returnOnEquity")),
            ("Return on Assets", info.get("returnOnAssets")),
            ("Debt to Equity", info.get("debtToEquity")),
            ("Current Ratio", info.get("currentRatio")),
            ("Book Value", info.get("bookValue")),
            ("Free Cash Flow", info.get("freeCashflow")),
        ]

        lines = []
        for label, value in fields:
            if value is not None:
                lines.append(f"{label}: {value}")

        # yfinance returns a stub dict (e.g. {"trailingPegRatio": None}) for
        # unknown symbols, so `info` is truthy but every field is empty. Treat
        # "no usable fields" as no data rather than emitting a bare header the
        # agent might fabricate around.
        if not lines:
            raise NoMarketDataError(ticker, canonical, "no fundamental fields returned")

        header = f"# Company Fundamentals for {canonical}\n"
        header += f"# Data retrieved on: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}\n\n"

        return header + "\n".join(lines)

    except NoMarketDataError:
        raise
    except Exception as e:
        return f"Error retrieving fundamentals for {ticker}: {str(e)}"


def get_balance_sheet(
    ticker: Annotated[str, "ticker symbol of the company"],
    freq: Annotated[str, "frequency of data: 'annual' or 'quarterly'"] = "quarterly",
    curr_date: Annotated[str, "current date in YYYY-MM-DD format"] = None
):
    """Get balance sheet data from yfinance."""

View on GitHub (pinned to a33fd4c0f1)

Solutions

  1. Validate the symbol has a real profile first (e.g. check that yf.Ticker(sym).info contains 'longName' or 'sector').
  2. Handle NoMarketDataError at the call site and mark fundamentals as unavailable instead of retrying.
  3. Upgrade yfinance if field-name drift is suspected — keys like trailingPE/marketCap occasionally change.

Example fix

# before
report = get_fundamentals('ZZZZ.ZY')

# after
from tradingagents.dataflows.errors import NoMarketDataError
try:
    report = get_fundamentals('ZZZZ.ZY')
except NoMarketDataError:
    report = None  # stub profile; no usable fundamentals
Defensive patterns

Strategy: try-catch

Validate before calling

import yfinance as yf

def fundamentals_are_usable(symbol: str) -> bool:
    info = yf.Ticker(symbol).info or {}
    return any(info.get(k) is not None for k in ('longName', 'sector', 'marketCap', 'trailingPE'))

Try / catch

from tradingagents.dataflows.errors import NoMarketDataError

try:
    report = get_fundamentals(symbol)
except NoMarketDataError:
    report = None  # stub profile — treat as unavailable, don't retry

Prevention

When it happens

Trigger: Calling get_fundamentals on a symbol where Yahoo returns a stub info dict — all mapped fields are None, `lines` stays empty, and the check raises. Distinct from error 23, which fires when info itself is empty.

Common situations: Unknown-but-not-404 symbols (mutual funds, dead tickers, some international listings) where Yahoo returns a skeleton profile; API version changes that rename info keys so all gets return None.

Related errors


AI-assisted analysis of TauricResearch/TradingAgents@a33fd4c0f1 (2026-08-14). Data as JSON: /api/errors/a16829bd5ad4860b. Report an issue: GitHub.