HKUDS/Vibe-Trading · error · ValueError

management_fee_rate must be a decimal fraction in [0, 1] (0.

Error message

management_fee_rate must be a decimal fraction in [0, 1] (0.02 means 2%), got {self.management_fee_rate!r}

What it means

Fund.__post_init__ validates management_fee_rate as a decimal fraction in [0, 1] — 0.02 means 2%. A rate outside that interval (typically 2.0 meaning 2%) is rejected to prevent hundred-fold fee errors.

Source

Thrown at agent/src/entities/models.py:322

            raise ValueError(
                f"unknown structure {self.structure!r}; expected one of: {valid}"
            ) from exc
        if self.vintage_year is not None and not 1800 <= int(self.vintage_year) <= 2200:
            raise ValueError(
                f"vintage_year={self.vintage_year!r} is outside the plausible "
                "range 1800-2200"
            )
        if self.commitment is not None:
            if float(self.commitment) < 0:
                raise ValueError(
                    f"commitment must be non-negative (it is a size, not a signed "
                    f"cash flow), got {self.commitment!r}"
                )
            object.__setattr__(self, "commitment", float(self.commitment))
        if self.management_fee_rate is not None:
            rate = float(self.management_fee_rate)
            if not 0.0 <= rate <= 1.0:
                raise ValueError(
                    f"management_fee_rate must be a decimal fraction in [0, 1] "
                    f"(0.02 means 2%), got {self.management_fee_rate!r}"
                )
            object.__setattr__(self, "management_fee_rate", rate)


@dataclass(frozen=True)
class Bond(Instrument):
    """A debt instrument paying scheduled coupons and returning principal.

    Attributes:
        face_value: Redemption amount per unit, in ``currency``. Positive.
        coupon_rate: Annual coupon as a decimal fraction (``0.05`` means 5%),
            not a percentage. Zero marks a zero-coupon bond.
        coupon_frequency: Coupon payments per year. Zero is only valid for a
            zero-coupon bond.
        maturity_date: Redemption date, when known.
        day_count: Day-count convention label, e.g. ``"30/360"`` or

View on GitHub (pinned to 80ffdda44c)

Solutions

  1. Divide percentages by 100 before passing: 2% -> 0.02
  2. If the value is in basis points, divide by 10_000
  3. Add a UI/ingest conversion step so the model always receives the decimal fraction

Example fix

# before
Fund(instrument_id='f1', management_fee_rate=2.0)  # meant 2%

# after
Fund(instrument_id='f1', management_fee_rate=0.02)
Defensive patterns

Strategy: validation

Validate before calling

rate = row.get('management_fee_rate')
if rate is not None:
    rate = float(rate)
    if rate > 1.0:
        rate /= 100.0  # percent -> fraction
Fund(..., management_fee_rate=rate)

Type guard

def is_valid_fee_rate(r) -> bool:
    return r is None or 0.0 <= float(r) <= 1.0

Prevention

When it happens

Trigger: Fund(..., management_fee_rate=2.0) (percentage instead of fraction), management_fee_rate=150 (basis points), or a negative rate. Values like 0.02 pass; 2 fails only if >1.0, negatives fail the lower bound.

Common situations: User input or vendor data expressing fees in percent; basis-point values (200 bp) passed raw; mixing conventions between a UI showing '2%' and the model expecting 0.02.

Related errors


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