HKUDS/Vibe-Trading · error · ValuationError

{model}: {expected_name!r} must be supplied as an Assumption

Error message

{model}: {expected_name!r} must be supplied as an Assumption(name=..., value=..., basis=...) carrying its justification, not a bare {type(value).__name__}. A terminal growth rate or exit multiple chosen without a stated reason is exactly the kind of silent default this package refuses to make on your behalf.

What it means

Terminal-value inputs must be supplied as Assumption(name=..., value=..., basis=...) instances, not bare floats. _require_assumption (used by terminal_value and run_dcf) rejects bare values because an un-justified terminal growth rate or exit multiple is precisely the silent default this package refuses to make.

Source

Thrown at agent/src/quantlib/valuation/dcf.py:210

def _require_assumption(value: Any, expected_name: str, model: str) -> Assumption:
    """Check that a terminal-value driver arrived as a justified Assumption.

    Args:
        value: Candidate supplied by the caller.
        expected_name: The :attr:`Assumption.name` this slot expects.
        model: Name used in the error message.

    Returns:
        ``value``, unchanged.

    Raises:
        ValuationError: If ``value`` is not an :class:`Assumption`, or if its
            ``name`` does not match ``expected_name`` (which usually means two
            assumptions were passed under swapped keys).
    """
    if not isinstance(value, Assumption):
        raise ValuationError(
            f"{model}: {expected_name!r} must be supplied as an Assumption("
            f"name=..., value=..., basis=...) carrying its justification, not "
            f"a bare {type(value).__name__}. A terminal growth rate or exit "
            "multiple chosen without a stated reason is exactly the kind of "
            "silent default this package refuses to make on your behalf."
        )
    if value.name != expected_name:
        raise ValuationError(
            f"{model}: expected an Assumption named {expected_name!r}, got "
            f"{value.name!r}; check that assumptions were not passed under "
            "swapped keys."
        )
    return value


def _require_nonnegative(value: float, name: str, model: str) -> float:
    """Check a value that is a signed formula's magnitude, so must be >= 0.

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Wrap the value: Assumption(name='terminal_growth_rate', value=0.025, basis='<why>').
  2. In wrappers, convert incoming floats to Assumption at the boundary with a documented basis.
  3. If you cannot state a basis, source one (analyst consensus, Damodaran data) before proceeding.

Example fix

# before
run_dcf(inputs, terminal_growth_rate=0.025, exit_multiple=None)

# after
from quantlib.valuation.contracts import Assumption
run_dcf(inputs,
        terminal_growth_rate=Assumption('terminal_growth_rate', 0.025,
                                         basis='long-run nominal GDP proxy'),
        exit_multiple=None)
Defensive patterns

Strategy: type-guard

Validate before calling

from quantlib.valuation.contracts import Assumption
if not isinstance(terminal_growth_rate, Assumption):
    terminal_growth_rate = Assumption('terminal_growth_rate', terminal_growth_rate,
                                      basis='<stated justification>')

Type guard

def is_assumption(v):
    from quantlib.valuation.contracts import Assumption
    return isinstance(v, Assumption)

Try / catch

except ValuationError as e:
    if 'must be supplied as an Assumption' in str(e):
        wrap_and_retry_with_documented_basis()

Prevention

When it happens

Trigger: Calling run_dcf(terminal_growth_rate=0.025, ...) or terminal_value(growth_rate=0.03) with a plain float instead of an Assumption carrying a basis string.

Common situations: Porting code from another DCF library that takes raw floats; quick notebooks; wrapper functions that accept floats from config and forward them unchanged.

Understand the failure class

Background: "Wrong argument type", "must be a string", "expected Array or Prism::Scope": TypeError and ArgumentError when a library receives a value of the wrong type — this error's family across 28 libraries.

Related errors


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