{"record":{"id":"5fd1c32b25d284d3","repo":"nautechsystems/nautilus_trader","slug":"probabilitypricefeemodel-requires-a-binary-option","errorCode":null,"errorMessage":"ProbabilityPriceFeeModel requires a binary option instrument","messagePattern":"ProbabilityPriceFeeModel requires a binary option instrument","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/execution/src/models/fee.rs","lineNumber":453,"sourceCode":"    feature = \"python\",\n    pyo3::pyclass(\n        module = \"nautilus_trader.execution\",\n        extends = PyFeeModel,\n        skip_from_py_object\n    )\n)]\npub struct ProbabilityPriceFeeModel;\n\nimpl FeeModel for ProbabilityPriceFeeModel {\n    fn get_commission(\n        &self,\n        order: &OrderAny,\n        fill_quantity: Quantity,\n        fill_px: Price,\n        instrument: &InstrumentAny,\n    ) -> anyhow::Result<Money> {\n        if !matches!(instrument, InstrumentAny::BinaryOption(_)) {\n            anyhow::bail!(\"ProbabilityPriceFeeModel requires a binary option instrument\");\n        }\n\n        let fill_price = fill_px.as_decimal();\n        if !(Decimal::ZERO..=Decimal::ONE).contains(&fill_price) {\n            anyhow::bail!(\"ProbabilityPriceFeeModel requires a fill price in [0, 1]\");\n        }\n\n        let fee_rate = match order.liquidity_side() {\n            Some(LiquiditySide::Maker) => instrument.maker_fee(),\n            Some(LiquiditySide::Taker) => instrument.taker_fee(),\n            Some(LiquiditySide::NoLiquiditySide) | None => anyhow::bail!(\"Liquidity side not set\"),\n        };\n\n        let one_minus_p = Decimal::ONE - fill_price;\n        let commission = mul_checked(fill_quantity.as_decimal(), fee_rate)\n            .and_then(|v| mul_checked(v, fill_price))\n            .and_then(|v| mul_checked(v, one_minus_p))\n            .map(|v| v.round_dp(5))?;","sourceCodeStart":435,"sourceCodeEnd":471,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/execution/src/models/fee.rs#L435-L471","documentation":"ProbabilityPriceFeeModel prices fees using the fill price as a probability, which is only meaningful for binary options. The constructor of get_commission checks the instrument type and bails if it is not a BinaryOption, because for other instruments the [0,1] price-as-probability math is invalid.","triggerScenarios":"Calling `ProbabilityPriceFeeModel::get_commission` (or its `new` via get_commission dispatch) passing any InstrumentAny other than InstrumentAny::BinaryOption, e.g. a CurrencyPair, FuturesContract, or CryptoOption.","commonSituations":"Wiring the wrong fee model in a backtest config for a non-binary market; reusing a fee model across instruments in a portfolio; copy-pasting a binary-option backtest setup for spot/perp trading.","solutions":["Use MakerTakerFeeModel or a fixed/perpetual fee model for non-binary-option instruments","Restrict the ProbabilityPriceFeeModel to venues/accounts trading binary options","Add an instrument-type check in config loading to pick the correct fee model automatically"],"exampleFix":"// before\nlet fee_model = FeeModelAny::ProbabilityPrice(ProbabilityPriceFeeModel::new(...)?); // used for FX pair\n// after\nlet fee_model = if matches!(instrument, InstrumentAny::BinaryOption(_)) {\n    FeeModelAny::ProbabilityPrice(ProbabilityPriceFeeModel::new(...)?)\n} else {\n    FeeModelAny::MakerTaker(MakerTakerFeeModel::new(...)?)\n};","handlingStrategy":"validation","validationCode":"if !matches!(instrument, InstrumentAny::BinaryOption(_)) {\n    // choose a different fee model for this instrument\n}","typeGuard":"fn is_binary_option(i: &InstrumentAny) -> bool { matches!(i, InstrumentAny::BinaryOption(_)) }","tryCatchPattern":"match fee_model.get_commission(&order, qty, px, &instrument) {\n    Ok(fee) => fee,\n    Err(e) if e.to_string().contains(\"binary option instrument\") => return Err(e.into()),\n    Err(e) => return Err(e),\n}","preventionTips":["Pair fee models with matching instrument types in config","Add a startup check mapping each instrument to a compatible fee model","Document model-instrument compatibility in strategy templates"],"tags":["rust","fee-model","instrument-type","binary-option"],"backgroundTag":"invalid-argument-value","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"}