{"record":{"id":"7cd38b78d022d987","repo":"nautechsystems/nautilus_trader","slug":"underlying-price-is-required","errorCode":null,"errorMessage":"Underlying price is required","messagePattern":"Underlying price is required","errorType":"exception","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/execution/src/models/fee.rs","lineNumber":563,"sourceCode":"        self.get_commission_with_context(order, fill_quantity, fill_px, instrument, None)\n    }\n\n    fn get_commission_with_context(\n        &self,\n        order: &OrderAny,\n        fill_quantity: Quantity,\n        fill_px: Price,\n        instrument: &InstrumentAny,\n        underlying_px: Option<Price>,\n    ) -> anyhow::Result<Money> {\n        check_option_instrument(instrument, \"CappedOptionFeeModel\")?;\n        let rate = option_fee_rate(order, instrument, self.maker_rate, self.taker_rate)?;\n        let multiplier = instrument.multiplier().as_decimal();\n        let rate_fee = if instrument.is_inverse() {\n            rate\n        } else {\n            let underlying_px =\n                underlying_px.ok_or_else(|| anyhow::anyhow!(\"Underlying price is required\"))?;\n            mul_checked(rate, underlying_px.as_decimal())?\n        };\n        let cap_fee = mul_checked(self.cap, fill_px.as_decimal())?;\n        let fee_per_contract = mul_checked(rate_fee.min(cap_fee), multiplier)?;\n        let total = mul_checked(fee_per_contract, fill_quantity.as_decimal())?;\n        Money::from_decimal(total, commission_currency(instrument)).map_err(Into::into)\n    }\n}\n\n#[derive(Debug, Clone)]\n#[cfg_attr(\n    feature = \"python\",\n    pyo3_stub_gen::derive::gen_stub_pyclass(module = \"nautilus_trader.execution\")\n)]\n#[cfg_attr(\n    feature = \"python\",\n    pyo3::pyclass(\n        module = \"nautilus_trader.execution\",","sourceCodeStart":545,"sourceCodeEnd":581,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/execution/src/models/fee.rs#L545-L581","documentation":"The capped option fee model prices non-inverse option commissions relative to the underlying asset price. When `get_commission_with_context` is called without an underlying price in the context (and the instrument is not inverse), it cannot compute the rate fee and raises this error. Inverse instruments are exempt because their rate already embeds the price.","triggerScenarios":"Calling `get_commission_with_context` for a non-inverse option fee cap model while passing `None` for `underlying_px` in the context; also triggered in tests validating rejection of non-option instruments.","commonSituations":"Wiring a Python/Rust fee model and forgetting to populate the underlying price in the context; using the option fee model on spot/futures (non-option) instruments; inverse-vs-linear instrument misconfiguration.","solutions":["Provide `underlying_px` in the call context when commissioning non-inverse option fills.","Use the plain `get_commission` path (no underlying context) or an appropriate fee model for non-option instruments.","Verify instrument type: only linear options require the underlying price; inverse instruments do not."],"exampleFix":"// before\nlet fee = model.get_commission_with_context(&order, qty, px, &instrument, None)?;\n// after\nlet fee = model.get_commission_with_context(&order, qty, px, &instrument,\n    Some(underlying_price))?;","handlingStrategy":"type-guard","validationCode":"if instrument.is_option() and not instrument.is_inverse():\n    assert underlying_px is not None, \"underlying price required for option fee cap model\"","typeGuard":"fn needs_underlying_px(instrument: &InstrumentAny) -> bool {\n    instrument.is_option() && !instrument.is_inverse()\n}","tryCatchPattern":"let fee = match model.get_commission_with_context(&order, qty, px, &inst, underlying_px) {\n    Ok(f) => f,\n    Err(e) if e.to_string().contains(\"Underlying price is required\") => fetch_underlying_and_retry(),\n};","preventionTips":["Always populate underlying price in the fee context for linear options.","Use the correct fee model per instrument type (option cap model only for options).","Check inverse vs linear instrument classification before choosing the pricing path."],"tags":["fee","option","underlying-price","missing-argument","rust"],"backgroundTag":"missing-required-argument","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"}