Representing Venue-Listed Crypto Futures Spreads as Instruments
Summary
This reference explains how to model an exchange-defined crypto futures spread as one tradable instrument. It lists required metadata such as the underlying asset, quote and settlement currencies, venue symbol, strategy type, activation and expiration times, price and size precision, and increments. Optional fields capture limits, margin rates, tick schemes, and adapter-specific information. The instrument can represent calendar spreads and may use linear, inverse, or quanto conventions depending on its currencies.
A key operational detail is that spread prices may be zero or negative, which the described risk engine accepts for this instrument class except for inverse spreads. The examples show construction in Rust and Python, and the note identifies Deribit and OKX as representative adapters. This is instrument-model documentation rather than a trading method: it gives no pricing model, execution procedure, backtest, or evidence about spread profitability. Correct handling depends on venue-provided contract specifications, especially leg details stored in adapter metadata, and on applying the relevant currency, sizing, and price conventions.
Key ideas
- A venue can publish a crypto futures spread as a single instrument with its own symbol and contract specifications.
- The model records currencies, strategy type, validity dates, precision, increments, and optional trading limits.
- Depending on its currency setup, the spread may be linear, inverse, or quanto.
- Zero and negative spread prices are supported except for inverse spreads.
- Venue-specific leg information may need to be retained in adapter metadata.
Tags
Full text
# Crypto Futures Spread
# Crypto Futures Spread
`CryptoFuturesSpread` represents an exchange-defined spread strategy over crypto
futures. The venue publishes the strategy as a single instrument with its own symbol,
strategy type, precision, increments, and expiration.
Examples include listed crypto futures calendar spreads.
## Fields
| Field | Rust type | Python type | Required/default | Notes |
| --------------------- | ------------------ | ------------------ | ---------------- | ---------------------------------------- |
| `instrument_id` | `InstrumentId` | `InstrumentId` | Required | Stored as `id` in Rust. |
| `raw_symbol` | `Symbol` | `Symbol` | Required | Native venue symbol. |
| `underlying` | `Currency` | `Currency` | Required | Crypto asset the strategy tracks. |
| `quote_currency` | `Currency` | `Currency` | Required | Currency used to quote the price. |
| `settlement_currency` | `Currency` | `Currency` | Required | Currency used to settle PnL and fees. |
| `is_inverse` | `bool` | `bool` | Required | True when sizing/costing is inverse. |
| `strategy_type` | `Ustr` | `str` | Required | Venue strategy type, such as calendar. |
| `activation_ns` | `UnixNanos` | `int` | Required | Strategy activation timestamp. |
| `expiration_ns` | `UnixNanos` | `int` | Required | Strategy expiration timestamp. |
| `price_precision` | `u8` | `int` | Required | Decimal places allowed for prices. |
| `size_precision` | `u8` | `int` | Required | Decimal places allowed for order sizes. |
| `price_increment` | `Price` | `Price` | Required | Smallest valid price step. |
| `size_increment` | `Quantity` | `Quantity` | Required | Smallest valid size step. |
| `multiplier` | `Quantity` | `Quantity` | `1` | Strategy multiplier. |
| `lot_size` | `Quantity` | `Quantity` | `1` | Rounded lot or board size. |
| `max_quantity` | `Option<Quantity>` | `Quantity \| None` | `None` | Maximum order quantity. |
| `min_quantity` | `Option<Quantity>` | `Quantity \| None` | `None` | Minimum order quantity. |
| `max_notional` | `Option<Money>` | `Money \| None` | `None` | Maximum order notional value. |
| `min_notional` | `Option<Money>` | `Money \| None` | `None` | Minimum order notional value. |
| `max_price` | `Option<Price>` | `Price \| None` | `None` | Maximum valid quote or order price. |
| `min_price` | `Option<Price>` | `Price \| None` | `None` | Minimum valid quote or order price. |
| `margin_init` | `Option<Decimal>` | `Decimal \| None` | `0` | Initial margin rate. |
| `margin_maint` | `Option<Decimal>` | `Decimal \| None` | `0` | Maintenance margin rate. |
| `tick_scheme` | `Option<Ustr>` | `str \| None` | `None` | Registered variable tick scheme name. |
| `info` | `Option<Params>` | `dict \| None` | `None` | Adapter metadata. |
| `ts_event` | `UnixNanos` | `int` | Required | Event timestamp in nanoseconds. |
| `ts_init` | `UnixNanos` | `int` | Required | Initialization timestamp in nanoseconds. |
*Note: Python constructors use `instrument_id`; Rust stores the same value as `id`.*
## Behavior
- `CryptoFuturesSpread` has asset class `Cryptocurrency` and instrument class
`FuturesSpread`.
- The venue publishes the spread as a single tradable instrument.
- The strategy can be linear, inverse, or quanto, depending on the currency set.
- Spread prices can be zero or negative, and the `RiskEngine` accepts non-positive prices
for this instrument class, except for inverse spreads.
- Store venue-specific leg details in `info` when the adapter provides them.
## Example
```rust tab="Rust"
use jiff::Timestamp;
use nautilus_core::UnixNanos;
use nautilus_model::{
identifiers::{InstrumentId, Symbol},
instruments::CryptoFuturesSpread,
types::{Currency, Price, Quantity},
};
use ustr::Ustr;
let activation: Timestamp = "2026-05-12T00:00:00Z".parse().unwrap();
let expiration: Timestamp = "2026-05-19T08:00:00Z".parse().unwrap();
let btc_spread = CryptoFuturesSpread::builder()
.instrument_id(InstrumentId::from("BTC-FS-19MAY26_PERP.DERIBIT"))
.raw_symbol(Symbol::from("BTC-FS-19MAY26_PERP"))
.underlying(Currency::from("BTC"))
.quote_currency(Currency::from("USD"))
.settlement_currency(Currency::from("BTC"))
.is_inverse(false)
.strategy_type(Ustr::from("FS"))
.activation_ns(UnixNanos::from(activation))
.expiration_ns(UnixNanos::from(expiration))
.price_precision(1)
.size_precision(0)
.price_increment(Price::from("0.5"))
.size_increment(Quantity::from("1"))
.multiplier(Quantity::from("10"))
.lot_size(Quantity::from("1"))
.min_quantity(Quantity::from("1"))
.ts_event(UnixNanos::default())
.ts_init(UnixNanos::default())
.build()
.unwrap();
```
```python tab="Python"
import pandas as pd
from nautilus_trader.model import CryptoFuturesSpread
from nautilus_trader.model import Currency
from nautilus_trader.model import InstrumentId
from nautilus_trader.model import Price
from nautilus_trader.model import Quantity
from nautilus_trader.model import Symbol
BTC = Currency.from_str("BTC")
USD = Currency.from_str("USD")
btc_spread = CryptoFuturesSpread(
instrument_id=InstrumentId.from_str("BTC-FS-19MAY26_PERP.DERIBIT"),
raw_symbol=Symbol("BTC-FS-19MAY26_PERP"),
underlying=BTC,
quote_currency=USD,
settlement_currency=BTC,
is_inverse=False,
strategy_type="FS",
activation_ns=pd.Timestamp("2026-05-12T00:00:00", tz="UTC").value,
expiration_ns=pd.Timestamp("2026-05-19T08:00:00", tz="UTC").value,
price_precision=1,
size_precision=0,
price_increment=Price.from_str("0.5"),
size_increment=Quantity.from_int(1),
multiplier=Quantity.from_int(10),
lot_size=Quantity.from_int(1),
min_quantity=Quantity.from_int(1),
ts_event=0,
ts_init=0,
)
```
## Adapters
Representative adapters that create or consume `CryptoFuturesSpread` instruments include:
- [Deribit](../../integrations/deribit.md) for crypto futures combos.
- [OKX](../../integrations/okx.md) for crypto futures spread markets.
## Related guides
- [Crypto Future](crypto_future.md) covers single-leg dated crypto futures.
- [Futures Spread](futures_spread.md) covers non-crypto futures spreads.Shown in full with attribution under the source's licence. Licence: LGPL-3.0
This summary was written by Stratmill's research agent from the original; it is not a copy of the source.