nautechsystems/nautilus_trader · error

Cash account cannot trade futures or perpetuals

Error message

Cash account cannot trade futures or perpetuals

What it means

A cash (non-margin) account cannot hold derivatives like futures, perpetuals, or crypto perpetual/future instruments, since they imply leverage and margin. add_instrument on the exchange bails when such an instrument is added to a cash-account venue.

Source

Thrown at crates/backtest/src/exchange.rs:459

    /// # Panics
    ///
    /// Panics if the instrument cannot be added to the exchange.
    pub fn add_instrument(&mut self, instrument: InstrumentAny) -> anyhow::Result<()> {
        check_equal(
            &instrument.id().venue,
            &self.id,
            "Venue of instrument id",
            "Venue of simulated exchange",
        )
        .expect_display(FAILED);

        if self.account_type == AccountType::Cash
            && (matches!(instrument, InstrumentAny::CryptoPerpetual(_))
                || matches!(instrument, InstrumentAny::CryptoFuture(_))
                || matches!(instrument, InstrumentAny::FuturesContract(_))
                || matches!(instrument, InstrumentAny::PerpetualContract(_)))
        {
            anyhow::bail!("Cash account cannot trade futures or perpetuals")
        }

        let price_protection = if self.price_protection_points == 0 {
            None
        } else {
            Some(self.price_protection_points)
        };

        let matching_engine_config = OrderMatchingEngineConfig::builder()
            .bar_execution(self.bar_execution)
            .bar_adaptive_high_low_ordering(self.bar_adaptive_high_low_ordering)
            .trade_execution(self.trade_execution)
            .liquidity_consumption(self.liquidity_consumption)
            .reject_stop_orders(self.reject_stop_orders)
            .support_gtd_orders(self.support_gtd_orders)
            .support_contingent_orders(self.support_contingent_orders)
            .use_position_ids(self.use_position_ids)
            .use_random_ids(self.use_random_ids)

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Set the venue account_type to Margin (or Betting) in SimulatedVenueConfig when trading derivatives
  2. Use spot instruments only on cash-account venues
  3. Validate instrument types against account type before adding them

Example fix

// before
config.account_type = AccountType::Cash; // with perp instruments
// after
config.account_type = AccountType::Margin; // required for futures/perpetuals
Defensive patterns

Strategy: validation

Validate before calling

use nautilus_model::enums::AccountType;
let is_derivative = matches!(
    instrument,
    InstrumentAny::CryptoPerpetual(_)
        | InstrumentAny::CryptoFuture(_)
        | InstrumentAny::FuturesContract(_)
        | InstrumentAny::PerpetualContract(_)
);
anyhow::ensure!(
    !(is_derivative && config.account_type == AccountType::Cash),
    "cash account venue cannot trade derivative instruments"
);

Type guard

fn is_derivative(instrument: &InstrumentAny) -> bool {
    matches!(
        instrument,
        InstrumentAny::CryptoPerpetual(_)
            | InstrumentAny::CryptoFuture(_)
            | InstrumentAny::FuturesContract(_)
            | InstrumentAny::PerpetualContract(_)
    )
}

Try / catch

match exchange.add_instrument(instrument) {
    Err(e) if e.to_string() == "Cash account cannot trade futures or perpetuals" => {
        eprintln!("use a Margin account venue for derivatives");
    }
    other => other?,
}

Prevention

When it happens

Trigger: Configuring a venue with account_type Cash and then adding a CryptoPerpetual, CryptoFuture, FuturesContract, or PerpetualContract instrument via add_instrument (directly or through data processing paths).

Common situations: Reusing a cash account venue config for a perp dataset; default account_type Cash left in venue config when backtesting perpetual futures.

Understand the failure class

Background: "Must be a positive integer", "Invalid value", "Unsupported": the invalid-argument-value error family, when a library rejects the value you pass — this error's family across 35 libraries.

Related errors


AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08). Data as JSON: /api/errors/6c3043565ed946a1. Report an issue: GitHub.