HKUDS/Vibe-Trading · error · ValueError
face_value must be positive, got {self.face_value!r}
Error message
face_value must be positive, got {self.face_value!r} What it means
FixedIncome/Bond.__post_init__ requires face_value, when provided, to be strictly positive after float coercion, since a bond's par value cannot be zero or negative.
Source
Thrown at agent/src/entities/models.py:362
face_value: float | None = None
coupon_rate: float | None = None
coupon_frequency: int = 2
maturity_date: date | None = None
day_count: str = "30/360"
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:View on GitHub (pinned to 80ffdda44c)
Solutions
- Supply the actual positive par amount (commonly 1000 or 100)
- If par is unknown, pass face_value=None rather than 0
- Fix ingestion defaults so absent par fields become None, not zero
Example fix
# before Bond(instrument_id='b1', face_value=0) # after Bond(instrument_id='b1', face_value=1000)
Defensive patterns
Strategy: validation
Validate before calling
face = row.get('face_value')
face = float(face) if face not in (None, '', 0) else None
if face is not None and face <= 0:
raise ValueError(f'bad face_value {face}')
Bond(..., face_value=face) Type guard
def is_valid_face_value(f) -> bool:
return f is None or float(f) > 0 Prevention
- Use None, not 0, for unknown par values
- Sanity-check par magnitudes (typically 100 or 1000) during profiling
When it happens
Trigger: Bond(..., face_value=0), face_value=-1000, or face_value supplied as 0.0 by a default/placeholder. Values are float()-coerced, so '1000' as a string works but 0/-5 does not.
Common situations: Missing par values defaulted to 0 in source files; a percent-of-par convention (0.98) confused with absolute par and multiplied out incorrectly; sign errors from short positions applied to the face field.
Related errors
- coupon_rate cannot be negative, got {rate!r}
- coupon_rate must be a decimal fraction (0.05 means 5%), got
- coupon_frequency cannot be negative, got {self.coupon_freque
- coupon_frequency=0 marks a zero-coupon bond, but coupon_rate
- maturity_date {self.maturity_date} precedes inception_date {
AI-assisted analysis of HKUDS/Vibe-Trading@80ffdda44c (2026-08-28).
Data as JSON: /api/errors/48b89ed1ca4584af.
Report an issue: GitHub.