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
- Ensure the instrument associated with the order is a Polymarket BinaryOption.
- Only install PolymarketFeeModel on executions for Polymarket binary option markets.
- Check the instrument_id on the order maps to an instrument added via parse_gamma_market.
- 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
- Install PolymarketFeeModel only for Polymarket binary option venues.
- Resolve instruments via the adapter cache so types are guaranteed.
- Assert instrument type in test fixtures.
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
- invalid market-buy price {price}: must satisfy 0 < price < 1
- user_pusd_balance {user_pusd_balance} too small to cover fee
- expected Polymarket BinaryOption instrument, found {instrume
- Expected BinaryOption, was {other:?}
- Liquidity side not set
AI-assisted analysis of nautechsystems/nautilus_trader@18893faf8b (2026-09-08).
Data as JSON: /api/errors/51f4d3c1dc81271f.
Report an issue: GitHub.