{"record":{"id":"8bf9b23f075ff0b7","repo":"nautechsystems/nautilus_trader","slug":"bettingaccount-requires-a-sports-betting-instrumen","errorCode":null,"errorMessage":"BettingAccount requires a sports betting instrument","messagePattern":"BettingAccount requires a sports betting instrument","errorType":"validation","errorClass":null,"httpStatus":null,"severity":"error","filePath":"crates/model/src/accounts/betting.rs","lineNumber":202,"sourceCode":"        }\n\n        if event.is_reported {\n            self.balances_locked.clear();\n        }\n\n        self.base_apply(event);\n        Ok(())\n    }\n\n    fn calculate_balance_locked(\n        &self,\n        instrument: &InstrumentAny,\n        side: OrderSide,\n        quantity: Quantity,\n        price: Price,\n        use_quote_for_inverse: Option<bool>,\n    ) -> anyhow::Result<Money> {\n        anyhow::ensure!(\n            instrument.instrument_class() == InstrumentClass::SportsBetting,\n            \"BettingAccount requires a sports betting instrument\"\n        );\n        anyhow::ensure!(\n            use_quote_for_inverse != Some(true),\n            \"`use_quote_for_inverse` is not applicable for betting accounts\"\n        );\n\n        let locked = match side {\n            OrderSide::Sell => quantity.as_decimal(),\n            OrderSide::Buy => quantity.as_decimal() * (price.as_decimal() - Decimal::ONE),\n        };\n\n        Ok(Money::from_decimal(locked, instrument.quote_currency())?)\n    }\n\n    fn calculate_pnls(\n        &self,","sourceCodeStart":184,"sourceCodeEnd":220,"githubUrl":"https://github.com/nautechsystems/nautilus_trader/blob/18893faf8b356be3320add8de2f861b0b647cf06/crates/model/src/accounts/betting.rs#L184-L220","documentation":"BettingAccount's balance-locking calculation is only defined for sports betting instruments; its locked-balance math (settling at odds) does not apply to conventional asset classes. The guard rejects any instrument whose instrument_class is not SportsBetting.","triggerScenarios":"Calling BettingAccount.calculate_balance_locked with a regular instrument (forex, crypto, equity) instead of a sports betting instrument.","commonSituations":"Configuring a betting account but routing fills/orders for standard instruments, or reusing a betting account type in a conventional trading setup.","solutions":["Use a standard account type (e.g. MarginAccount/CashAccount) for non-betting instruments","Ensure the instrument passed is an actual sports betting instrument matching the market data","Check account factory/registration so betting accounts are only used with betting venues"],"exampleFix":null,"handlingStrategy":"type-guard","validationCode":"if instrument.instrument_class() != InstrumentClass.SPORTS_BETTING:\n    raise ValueError(f\"{instrument.id} is not a sports betting instrument\")","typeGuard":"def is_betting_instrument(instrument) -> bool:\n    return instrument.instrument_class() == InstrumentClass.SPORTS_BETTING","tryCatchPattern":"try:\n    locked = betting_account.calculate_balance_locked(instrument, side, qty, px, None)\nexcept Exception as e:\n    log.error(f\"betting balance lock failed: {e}\")","preventionTips":["Match account type to instrument class in config","Only route betting venue data to BettingAccount","Check instrument registration in the cache before calculations"],"tags":["rust","betting","instrument-class"],"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-14T00:17:10.932Z"}