HKUDS/Vibe-Trading · error · ValuationError

{model}: expected an Assumption named {expected_name!r}, got

Error message

{model}: expected an Assumption named {expected_name!r}, got {value.name!r}; check that assumptions were not passed under swapped keys.

What it means

When an Assumption is supplied but its name does not match the expected parameter name, _require_assumption raises this error — the classic signature of two assumptions passed under swapped keys (e.g. the exit-multiple assumption given to the growth-rate parameter).

Source

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

    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.

    Args:
        value: The candidate magnitude.
        name: Field name for the error message.
        model: Model name for the error message.

    Returns:
        ``value`` as a float.

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Swap the two Assumption objects so each keyword receives the matching name.
  2. Construct assumptions with the exact parameter-name string (terminal_growth_rate / exit_multiple).
  3. Prefer **{'terminal_growth_rate': assumption, ...} keyed by parameter name to avoid drift.

Example fix

# before
run_dcf(inputs,
        terminal_growth_rate=Assumption('exit_multiple', 11.0, 'peer median EV/EBITDA'),
        exit_multiple=Assumption('terminal_growth_rate', 0.02, 'GDP proxy'))

# after
run_dcf(inputs,
        terminal_growth_rate=Assumption('terminal_growth_rate', 0.02, 'GDP proxy'),
        exit_multiple=Assumption('exit_multiple', 11.0, 'peer median EV/EBITDA'))
Defensive patterns

Strategy: validation

Validate before calling

assert terminal_growth_rate.name == 'terminal_growth_rate'
assert exit_multiple.name == 'exit_multiple'

Type guard

def assumption_named(a, name):
    return getattr(a, 'name', None) == name

Try / catch

except ValuationError as e:
    if 'swapped keys' in str(e):
        swap_assumptions_and_retry()

Prevention

When it happens

Trigger: run_dcf(terminal_growth_rate=Assumption('exit_multiple', ...), exit_multiple=Assumption('terminal_growth_rate', ...)); or any Assumption whose name literal differs from the keyword it is passed under.

Common situations: Keyword/positional mixups when refactoring call sites; building an assumptions dict then unpacking with ** under renamed keys; copy-paste of assumption blocks between parameters.

Related errors


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