HKUDS/Vibe-Trading · error · ValueError
ead must be non-negative, got {ead}
Error message
ead must be non-negative, got {ead} What it means
expected_loss computes EL = EAD x PD x LGD. Exposure at default cannot be negative — a negative exposure is a booking or data error, not an economic quantity in this API — so it is rejected before the multiplication.
Source
Thrown at agent/src/quantlib/credit.py:885
def expected_loss(ead: float, pd: float, lgd: float) -> float:
"""Compute regulatory Expected Loss (EL = EAD * PD * LGD).
Args:
ead: Exposure at Default in currency units >= 0.
pd: Probability of Default in [0.0, 1.0].
lgd: Loss Given Default in [0.0, 1.0].
Returns:
Expected loss amount in currency units.
Raises:
ValueError: If ead < 0, pd not in [0, 1], or lgd not in [0, 1].
"""
ead = _require_finite(ead, "ead")
pd = _require_finite(pd, "pd")
lgd = _require_finite(lgd, "lgd")
if ead < 0.0:
raise ValueError(f"ead must be non-negative, got {ead}")
if not (0.0 <= pd <= 1.0):
raise ValueError(f"pd must be in [0.0, 1.0], got {pd}")
if not (0.0 <= lgd <= 1.0):
raise ValueError(f"lgd must be in [0.0, 1.0], got {lgd}")
return float(ead * pd * lgd)
def vasicek_credit_var(
ead: float,
pd: float,
lgd: float,
asset_correlation: float,
confidence: float = 0.999,
) -> dict:
"""Vasicek single-factor asymptotic credit risk portfolio model (Basel II/III capital framework).
Under the Asymptotic Single Risk Factor (ASRF) model, conditional default
probability at confidence level alpha is:View on GitHub (pinned to 80ffdda44c)
Solutions
- Check your exposure aggregation for sign bugs
- If negative values represent short positions/netting, take abs() or handle separately, since this API models gross exposure
- Log and quarantine records with ead < 0 in your data pipeline
Example fix
# before el = expected_loss(ead=-500_000, pd=0.02, lgd=0.6) # after el = expected_loss(ead=500_000, pd=0.02, lgd=0.6)
Defensive patterns
Strategy: validation
Validate before calling
if ead < 0.0:
raise ValueError(f"negative EAD from feed: {ead}")
el = expected_loss(ead, pd, lgd) Type guard
def is_valid_ead(e: float) -> bool:
return math.isfinite(e) and e >= 0.0 Try / catch
try:
el = expected_loss(ead, pd, lgd)
except ValueError as e:
logger.warning("skipping bad exposure record: %s", e)
el = 0.0 Prevention
- Validate exposure feeds for sign before aggregation
- Treat negative exposures as data errors or netting artifacts, not inputs
- Log and quarantine offending records instead of crashing batch jobs
When it happens
Trigger: Calling expected_loss(ead=-1_000_000, ...) or with ead = 0.0-derived negative values from an upstream aggregation.
Common situations: Netting logic that produces negative exposures (which this simple API does not model); sign errors in exposure feeds; passing deltas instead of levels.
Related errors
- pd must be in [0.0, 1.0], got {pd}
- lgd must be in [0.0, 1.0], got {lgd}
- survival_prob must be in (0.0, 1.0], got {survival_prob}
- tenor_years must be strictly positive, got {tenor_years}
- recovery_rate must be in [0.0, 1.0), got {recovery_rate}
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/e11505d2f8d26799.
Report an issue: GitHub.