nautechsystems/nautilus_trader · error · anyhow::Error

Oracle price required for market orders

Error message

Oracle price required for market orders

What it means

Market orders on dYdV v4 are submitted as limit orders at a worst-case price derived from the oracle price plus a slippage buffer. This error is thrown when the builder has no oracle price set, so the worst-case subticks price cannot be computed.

Source

Thrown at crates/adapters/dydx/src/grpc/order.rs:175

        result
            .to_u64()
            .ok_or_else(|| anyhow::anyhow!("Failed to convert quantity to u64"))
    }

    /// A `round`-like function that quantizes a `value` to the `fraction`.
    fn quantize(value: &Decimal, fraction: &Decimal) -> Decimal {
        (value / fraction).round() * fraction
    }

    /// Compute worst-case subticks for a market order using oracle price + slippage.
    ///
    /// # Errors
    ///
    /// Returns an error if oracle price is not available or conversion fails.
    pub fn market_order_subticks(&self, side: OrderSide) -> Result<u64, anyhow::Error> {
        let oracle = self
            .oracle_price
            .ok_or_else(|| anyhow::anyhow!("Oracle price required for market orders"))?;
        let worst_price = match side {
            OrderSide::Buy => oracle * (Decimal::ONE + DEFAULT_MARKET_ORDER_SLIPPAGE),
            OrderSide::Sell => oracle * (Decimal::ONE - DEFAULT_MARKET_ORDER_SLIPPAGE),
            _ => oracle,
        };
        self.quantize_price(worst_price)
    }

    /// Get orderbook pair id.
    #[must_use]
    pub fn clob_pair_id(&self) -> u32 {
        self.clob_pair_id
    }
}

/// [`Order`] builder.
///
/// Note that the price input to the `OrderBuilder` is in the "common" units of the perpetual/currency,

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Set the oracle price on the builder (or ensure the adapter populates it from the price cache) before building market orders
  2. Wait until a price for the instrument exists (check the cache) and retry
  3. Fall back to a bounded limit order at a manually supplied price if oracle data is unavailable
  4. Verify the instrument id matches the one the oracle publishes for, so the lookup is not silently empty

Example fix

// before
let order = OrderBuilder::new(params)
    .order_type(OrderType::Market)
    .side(OrderSide::Buy)
    .build()?;
// after
let oracle = price_cache.get(params.clob_pair_id)
    .ok_or_else(|| anyhow::anyhow!("no oracle price yet for {}", params.clob_pair_id))?;
let order = OrderBuilder::new(params)
    .order_type(OrderType::Market)
    .side(OrderSide::Buy)
    .oracle_price(oracle)
    .build()?;
Defensive patterns

Strategy: validation

Validate before calling

let oracle = price_cache.get(instrument_id)
    .ok_or_else(|| anyhow::anyhow!("oracle price unavailable for {}", instrument_id))?;
anyhow::ensure!(oracle > Decimal::ZERO, "oracle price must be positive");

Type guard

fn has_oracle_price(b: &OrderBuilder) -> bool {
    b.oracle_price.map(|p| p > Decimal::ZERO).unwrap_or(false)
}

Try / catch

match builder.build() {
    Ok(order) => submit(order).await?,
    Err(e) if e.to_string().contains("Oracle price required") => {
        // defer order until price feed warms up
    }
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling market_order_subticks (or building a Market / StopMarket / MarketIfTouched order via OrderBuilder::build) when OrderBuilder.oracle_price is None.

Common situations: Submitting a market order before subscribing to or fetching the market's oracle/price data; a race where the price feed has not delivered the first update yet; cache miss in the price provider; building an order in a disconnected or cold-start state.

Understand the failure class

Background: "missing required argument" and "the following required arguments were not provided": what required-argument errors mean and how to fix them — this error's family across 20 libraries.

Related errors


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