HKUDS/Vibe-Trading · error · MissingInputError

peers

Error message

peers

What it means

run_comps raises MissingInputError(('peers',), 'comps.run_comps') when the peers sequence is empty — a comp analysis with no comparables has no statistics to compute, which is treated as a missing input rather than a numeric error.

Source

Thrown at agent/src/quantlib/valuation/comps.py:1174

            the peers themselves were not missing, only their multiples were
            not computable.
        ValuationError: If `calendarisation_policy` is not recognised, if
            two peers share a name, or if peers/target do not all declare
            the same `eps_basis` (mixing GAAP and adjusted EPS across the
            comp set would skew the P/E distribution by whatever one-time
            items the adjustment removes, the same kind of silent distortion
            the calendarisation-policy rule exists to prevent).
        MissingInputError: (propagated from `calendarise_metric`) if any
            peer's or the target's fiscal-period data lacks a field
            `calendarisation_policy` needs.
    """
    if calendarisation_policy not in CALENDARISATION_POLICIES:
        raise ValuationError(
            f"comps.run_comps: unknown calendarisation_policy {calendarisation_policy!r}, "
            f"must be one of {CALENDARISATION_POLICIES}"
        )
    if len(peers) == 0:
        raise MissingInputError(("peers",), "comps.run_comps")

    names = [peer.name for peer in peers]
    if len(set(names)) != len(names):
        raise ValuationError(f"comps.run_comps: duplicate peer names in {names}")

    all_bases = {peer.eps_basis for peer in peers} | {target.eps_basis}
    if len(all_bases) > 1:
        raise ValuationError(
            "comps.run_comps: mixed eps_basis across the comp set "
            f"{sorted(all_bases)} -- every peer and the target must declare the "
            "same EPS basis, or the P/E distribution mixes GAAP and adjusted "
            "earnings"
        )

    peer_multiples = tuple(peer_multiple_set(peer, calendarisation_policy) for peer in peers)
    distributions = {
        name: multiple_distribution(name, peer_multiples) for name in MULTIPLE_NAMES
    }

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Check len(peers) before calling and surface a domain-level 'no comparables matched' message.
  2. Loosen or review the screening filters that produced the empty set.
  3. Fetch/validate peer data earlier so an empty universe is caught at data-load time.

Example fix

# before
result = run_comps(target, peers=filtered_peers)

# after
if not filtered_peers:
    raise ValueError('no peers survived screening; widen filters')
result = run_comps(target, peers=filtered_peers)
Defensive patterns

Strategy: validation

Validate before calling

if not peers:
    raise ValueError('no comparable peers available after screening')

Type guard

def has_peers(peers):
    return len(peers) > 0

Try / catch

from quantlib.valuation.contracts import MissingInputError
try:
    run_comps(target, peers)
except MissingInputError as e:
    if 'peers' in e.missing:
        return build_empty_report(reason='no peers')

Prevention

When it happens

Trigger: Calling run_comps(target, peers=[]) or peers=() — e.g. a screening filter excluded every candidate peer before the call.

Common situations: Over-aggressive peer filters (liquidity, listing exchange, negative-EBITDA exclusion) emptying the peer set; upstream data fetch returning zero rows; empty watchlist in config.

Related errors


AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28). Data as JSON: /api/errors/3c82a5cab352fd7e. Report an issue: GitHub.