{"record":{"id":"98b6c70921da72e0","repo":"HKUDS/Vibe-Trading","slug":"coupon-rate-cannot-be-negative-got-rate-r","errorCode":null,"errorMessage":"coupon_rate cannot be negative, got {rate!r}","messagePattern":"coupon_rate cannot be negative, got (.+?)","errorType":"validation","errorClass":"ValueError","httpStatus":null,"severity":"error","filePath":"agent/src/entities/models.py","lineNumber":367,"sourceCode":"\n    def __post_init__(self) -> None:\n        \"\"\"Validate the base fields plus bond-specific ranges and consistency.\n\n        Raises:\n            ValueError: If ``face_value`` is non-positive, ``coupon_rate`` is\n                negative or expressed as a percentage, the coupon frequency\n                contradicts the coupon rate, or maturity precedes inception.\n        \"\"\"\n        super().__post_init__()\n        if self.face_value is not None:\n            face = float(self.face_value)\n            if face <= 0:\n                raise ValueError(f\"face_value must be positive, got {self.face_value!r}\")\n            object.__setattr__(self, \"face_value\", face)\n        if self.coupon_rate is not None:\n            rate = float(self.coupon_rate)\n            if rate < 0:\n                raise ValueError(f\"coupon_rate cannot be negative, got {rate!r}\")\n            if rate > 1.0:\n                raise ValueError(\n                    f\"coupon_rate must be a decimal fraction (0.05 means 5%), \"\n                    f\"got {rate!r}; a value above 1.0 is almost certainly a \"\n                    \"percentage\"\n                )\n            object.__setattr__(self, \"coupon_rate\", rate)\n        frequency = int(self.coupon_frequency)\n        if frequency < 0:\n            raise ValueError(\n                f\"coupon_frequency cannot be negative, got {self.coupon_frequency!r}\"\n            )\n        if self.coupon_rate and frequency == 0:\n            raise ValueError(\n                f\"coupon_frequency=0 marks a zero-coupon bond, but coupon_rate=\"\n                f\"{self.coupon_rate!r} is non-zero\"\n            )\n        object.__setattr__(self, \"coupon_frequency\", frequency)","sourceCodeStart":349,"sourceCodeEnd":385,"githubUrl":"https://github.com/HKUDS/Vibe-Trading/blob/80ffdda44c5c4db0dd84d70e051cca591cea67df/agent/src/entities/models.py#L349-L385","documentation":"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).","triggerScenarios":"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.","commonSituations":"Reusing signed-rate conventions from derivatives pricing; minus signs introduced by spreadsheet formulas or OCR; corrupt rows in vendor files.","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"],"exampleFix":"# before\nBond(instrument_id='b1', coupon_rate=-0.05)\n\n# after\nBond(instrument_id='b1', coupon_rate=0.05)","handlingStrategy":"validation","validationCode":"cr = row.get('coupon_rate')\nif cr is not None:\n    cr = float(cr)\n    if cr < 0:\n        raise ValueError(f'negative coupon_rate {cr} in row {row_id}')\nBond(..., coupon_rate=cr)","typeGuard":"def is_valid_coupon_rate(r) -> bool:\n    return r is None or float(r) >= 0","tryCatchPattern":null,"preventionTips":["Strip signs from rates at ingest and log exceptions","Never reuse signed-derivative conventions for bond static data"],"tags":["python","dataclass","bond","rate-validation"],"backgroundTag":"numeric-sign-validation","analyzedSha":"80ffdda44c5c4db0dd84d70e051cca591cea67df","analyzedAt":"2026-08-28T12:46:38.989Z","schemaVersion":2},"datasetVersion":"2026-08-28T16:17:29.566Z"}