nautechsystems/nautilus_trader · error

PolymarketFeeModel requires a binary option instrument

Error message

PolymarketFeeModel requires a binary option instrument

What it means

PolymarketFeeModel::get_commission computes fees only for BinaryOption instruments, since Polymarket's fee schedule applies to binary markets. Passing any other InstrumentAny variant (e.g. a Perpetual or Equity) bails with this error. It is a guard against applying the Polymarket fee formula to unsupported instruments.

Source

Thrown at crates/adapters/polymarket/src/models.rs:61

    feature = "python",
    pyo3::pyclass(
        module = "nautilus_trader.adapters.polymarket",
        extends = PyFeeModel,
        skip_from_py_object
    )
)]
pub struct PolymarketFeeModel;

impl FeeModel for PolymarketFeeModel {
    fn get_commission(
        &self,
        order: &OrderAny,
        fill_quantity: Quantity,
        fill_px: Price,
        instrument: &InstrumentAny,
    ) -> anyhow::Result<Money> {
        let InstrumentAny::BinaryOption(binary) = instrument else {
            anyhow::bail!("PolymarketFeeModel requires a binary option instrument");
        };

        let liquidity_side = match order.liquidity_side() {
            Some(LiquiditySide::Maker) => LiquiditySide::Maker,
            Some(LiquiditySide::Taker) => LiquiditySide::Taker,
            Some(LiquiditySide::NoLiquiditySide) | None => {
                anyhow::bail!("Liquidity side not set")
            }
        };

        let Some(schedule) = binary
            .info
            .as_ref()
            .and_then(|info| info.get("fee_schedule"))
            .map(|value| serde_json::from_value::<FeeSchedule>(value.clone()))
            .transpose()
            .context("invalid Polymarket fee schedule")?
        else {

View on GitHub (pinned to 18893faf8b)

Solutions

  1. Ensure the instrument associated with the order is a Polymarket BinaryOption.
  2. Only install PolymarketFeeModel on executions for Polymarket binary option markets.
  3. Check the instrument_id on the order maps to an instrument added via parse_gamma_market.
  4. Match on InstrumentAny::BinaryOption in caller code before invoking the fee model.

Example fix

// before
let fee = fee_model.get_commission(&order, qty, px, &instrument)?;
// after
let fee = match &instrument {
    InstrumentAny::BinaryOption(_) => fee_model.get_commission(&order, qty, px, &instrument)?,
    _ => Money::zero(instrument.quote_currency()),
};
Defensive patterns

Strategy: type-guard

Validate before calling

let is_binary = matches!(instrument, InstrumentAny::BinaryOption(_));
if !is_binary { /* use default fee model or skip */ }

Type guard

fn is_binary_option(inst: &InstrumentAny) -> bool {
    matches!(inst, InstrumentAny::BinaryOption(_))
}

Try / catch

match fee_model.get_commission(&order, qty, px, &instrument) {
    Ok(fee) => fee,
    Err(e) if e.to_string().contains("requires a binary option") => Money::zero(instrument.quote_currency()),
    Err(e) => return Err(e),
}

Prevention

When it happens

Trigger: Calling get_commission (directly or via the trading engine's commission calculation) with an instrument that is not a BinaryOption while the Polymarket fee model is installed.

Common situations: Configuring the PolymarketFeeModel on a venue/portfolio that also holds non-binary instruments; test fixtures passing a generic instrument; instrument lookup returning the wrong instrument for an order.

Understand the failure class

Background: Type mismatch errors: IllegalArgumentException, TypeError and type guards across 150 open-source libraries — this error's family across 150 libraries.

Related errors


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