HKUDS/Vibe-Trading · error · ValueError
coupon_rate cannot be negative, got {rate!r}
Error message
coupon_rate cannot be negative, got {rate!r} What it means
Bond.__post_init__ rejects coupon_rate values below zero after float coercion. Negative coupons are treated as data errors (a coupon rate cannot be a cash outflow for the holder).
Source
Thrown at agent/src/entities/models.py:367
def __post_init__(self) -> None:
"""Validate the base fields plus bond-specific ranges and consistency.
Raises:
ValueError: If ``face_value`` is non-positive, ``coupon_rate`` is
negative or expressed as a percentage, the coupon frequency
contradicts the coupon rate, or maturity precedes inception.
"""
super().__post_init__()
if self.face_value is not None:
face = float(self.face_value)
if face <= 0:
raise ValueError(f"face_value must be positive, got {self.face_value!r}")
object.__setattr__(self, "face_value", face)
if self.coupon_rate is not None:
rate = float(self.coupon_rate)
if rate < 0:
raise ValueError(f"coupon_rate cannot be negative, got {rate!r}")
if rate > 1.0:
raise ValueError(
f"coupon_rate must be a decimal fraction (0.05 means 5%), "
f"got {rate!r}; a value above 1.0 is almost certainly a "
"percentage"
)
object.__setattr__(self, "coupon_rate", rate)
frequency = int(self.coupon_frequency)
if frequency < 0:
raise ValueError(
f"coupon_frequency cannot be negative, got {self.coupon_frequency!r}"
)
if self.coupon_rate and frequency == 0:
raise ValueError(
f"coupon_frequency=0 marks a zero-coupon bond, but coupon_rate="
f"{self.coupon_rate!r} is non-zero"
)
object.__setattr__(self, "coupon_frequency", frequency)View on GitHub (pinned to 80ffdda44c)
Solutions
- Pass the unsigned coupon rate
- If negative rates are genuinely required (rare exotic contracts), model them outside this Bond class or extend validation consciously
- Scrub ingest data for negative rates and route them to an exceptions report
Example fix
# before Bond(instrument_id='b1', coupon_rate=-0.05) # after Bond(instrument_id='b1', coupon_rate=0.05)
Defensive patterns
Strategy: validation
Validate before calling
cr = row.get('coupon_rate')
if cr is not None:
cr = float(cr)
if cr < 0:
raise ValueError(f'negative coupon_rate {cr} in row {row_id}')
Bond(..., coupon_rate=cr) Type guard
def is_valid_coupon_rate(r) -> bool:
return r is None or float(r) >= 0 Prevention
- Strip signs from rates at ingest and log exceptions
- Never reuse signed-derivative conventions for bond static data
When it happens
Trigger: Bond(..., coupon_rate=-0.05), or a feed that encodes issuer-paid vs receiver-paid swap-style conventions with signs. A rate of exactly 0 is allowed (zero-coupon) provided coupon_frequency is also 0.
Common situations: Reusing signed-rate conventions from derivatives pricing; minus signs introduced by spreadsheet formulas or OCR; corrupt rows in vendor files.
Related errors
- coupon_rate must be a decimal fraction (0.05 means 5%), got
- management_fee_rate must be a decimal fraction in [0, 1] (0.
- face_value must be positive, got {self.face_value!r}
- coupon_frequency cannot be negative, got {self.coupon_freque
- coupon_frequency=0 marks a zero-coupon bond, but coupon_rate
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/98b6c70921da72e0.
Report an issue: GitHub.