{"record":{"id":"beb8908b810237e5","repo":"nautechsystems/nautilus_trader","slug":"polymarket-rebate-rate-must-be-in-0-1","errorCode":null,"errorMessage":"Polymarket rebate rate must be in [0, 1]","messagePattern":"Polymarket rebate rate must be in \\[0, 1\\]","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/adapters/polymarket/src/models.rs","lineNumber":122,"sourceCode":"\n        Money::from_decimal(commission, instrument.quote_currency()).map_err(Into::into)\n    }\n}\n\nfn validate_schedule(schedule: &FeeSchedule) -> anyhow::Result<()> {\n    if schedule.exponent != Decimal::ONE {\n        anyhow::bail!(\n            \"PolymarketFeeModel requires fee schedule exponent 1, was {}\",\n            schedule.exponent\n        );\n    }\n\n    if schedule.rate < Decimal::ZERO {\n        anyhow::bail!(\"Polymarket fee rate must be greater than or equal to zero\");\n    }\n\n    if !(Decimal::ZERO..=Decimal::ONE).contains(&schedule.rebate_rate) {\n        anyhow::bail!(\"Polymarket rebate rate must be in [0, 1]\");\n    }\n\n    if !schedule.taker_only {\n        anyhow::bail!(\"PolymarketFeeModel requires a taker-only fee schedule\");\n    }\n    Ok(())\n}\n\n#[cfg(test)]\nmod tests {\n    use nautilus_core::UnixNanos;\n    use nautilus_execution::models::fee::{FeeModel, FeeModelHandle};\n    use nautilus_model::{\n        enums::{LiquiditySide, OrderSide, OrderType},\n        instruments::{Instrument, InstrumentAny, stubs::audusd_sim},\n        orders::{OrderAny, builder::OrderTestBuilder, stubs::TestOrderStubs},\n        types::{Price, Quantity},\n    };","sourceCodeStart":104,"sourceCodeEnd":140,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/adapters/polymarket/src/models.rs#L104-L140","documentation":"validate_schedule requires the schedule's rebate_rate to be within [0, 1] because it is treated as a proportion. A rebate rate outside this interval is invalid input and would corrupt fee/rebate math, so validation bails.","triggerScenarios":"get_commission on a market whose FeeSchedule.rebate_rate is negative or greater than 1 — typically from misparsed API data (percent vs fraction) or bad fixtures.","commonSituations":"Fee schedule fields given as percentages (e.g. 25 meaning 0.25) by upstream data; corrupted or hand-edited fixtures; parsing errors mapping JSON fields to Decimal.","solutions":["Normalize rebate_rate to a 0–1 fraction (divide percent values by 100) before constructing FeeSchedule.","Verify how the CLOB API encodes rebate_rate and fix the deserialization accordingly.","Validate schedules at instrument construction time to fail fast before trading.","Correct any fixture with rebate_rate outside [0, 1]."],"exampleFix":"// before\nlet schedule = FeeSchedule { rebate_rate: Decimal::from(25), .. }; // percent\n// after\nlet schedule = FeeSchedule { rebate_rate: Decimal::new(25, 2), .. }; // 0.25","handlingStrategy":"validation","validationCode":"if !(Decimal::ZERO..=Decimal::ONE).contains(&schedule.rebate_rate) {\n    return Err(\"rebate_rate must be a fraction in [0,1]\".into());\n}","typeGuard":"fn has_valid_rebate_rate(s: &FeeSchedule) -> bool {\n    (Decimal::ZERO..=Decimal::ONE).contains(&s.rebate_rate)\n}","tryCatchPattern":"match fee_model.get_commission(&order, qty, px, &instrument) {\n    Ok(fee) => fee,\n    Err(e) if e.to_string().contains(\"rebate rate must be in [0, 1]\") => {\n        log::error!(\"rebate_rate out of range — check percent vs fraction\");\n        return Err(e);\n    }\n    Err(e) => return Err(e),\n}","preventionTips":["Normalize percent-encoded schedule fields to fractions on ingestion.","Clamp or reject rebate rates outside [0,1] at deserialization time.","Cross-check schedule values against the CLOB API in integration tests."],"tags":["fees","validation","polymarket","range"],"backgroundTag":"value-out-of-range","analyzedSha":"18893faf8b356be3320add8de2f861b0b647cf06","analyzedAt":"2026-09-08T20:49:34.690Z","contentChangedAt":"2026-09-08T20:49:34.690Z","schemaVersion":2},"datasetVersion":"2026-09-14T05:17:10.506Z"}