Nautilus Trader BinaryOption 合约模型全解析:从字段设计到预测市场实战
【免费下载链接】nautilus_traderProduction-grade Rust-native trading engine with deterministic event-driven architecture项目地址: https://gitcode.com/GitHub_Trending/na/nautilus_trader
BinaryOption是 Nautilus Trader 中用于表示二元结果类合约的通用工具模型——它以"条件成立与否决定固定赔付"的方式统一刻画预测市场、二元期权以及交易所自定义的 Yes/No 合约。本文以 docs/concepts/instruments/binary_option.md 为骨架,结合nautilus_model的 Rust 核心实现与 Python 绑定源码,系统讲解BinaryOption的全部 25 个字段、行为语义、双语言构造方式、构建期校验规则,以及 Hyperliquid、Polymarket、OKX 三类适配器如何消费这一模型,帮助读者在回测与实盘中将二元合约当作一等公民处理。
BinaryOption 是什么
BinaryOption代表一类"二元结果"工具:合约在到期时依据某个条件是否成立,结算为固定赔付(fixed payoff)。它天然适合建模:
- 预测市场(prediction markets):如 "Will the outcome of this market be 'Yes'?" 这类 Yes/No 合约;
- 二元期权(binary options):交易所自定义的二元结果产品;
- 交易所特定的 Yes/No 合约:不同交易场所提供的同构合约。
从源码看,这一模型被实现为一个#[repr(C)]的结构体,并同时暴露给 Rust 与 Python(通过pyo3的pyclass),定义位于 crates/model/src/instruments/binary_option.rs。它实现了nautilus_model的Instrumenttrait,因此可以无缝进入缓存、回测引擎、风险管理等下游体系。
字段全览
构造一个BinaryOption共涉及 25 个字段,下表完整列出其 Rust 类型、Python 类型、必填性及含义:
| Field | Rust type | Python type | Required/default | Notes |
|---|---|---|---|---|
instrument_id | InstrumentId | InstrumentId | Required | Rust 中存储为id |
raw_symbol | Symbol | Symbol | Required | 交易所原生符号 |
asset_class | AssetClass | AssetClass | Required | 结果市场的资产类别 |
currency | Currency | Currency | Required | 报价与结算货币 |
activation_ns | UnixNanos | int | Required | 合约激活时间戳 |
expiration_ns | UnixNanos | int | Required | 合约到期时间戳 |
price_precision | u8 | int | Required | 价格允许的小数位数 |
size_precision | u8 | int | Required | 订单数量允许的小数位数 |
price_increment | Price | Price | Required | 最小有效价格步长(tick size) |
size_increment | Quantity | Quantity | Required | 最小有效数量步长 |
outcome | Option<Ustr> | str \| None | None | 交易所提供时给出的结果标签 |
description | Option<Ustr> | str \| None | None | 人类可读的市场描述 |
max_quantity | Option<Quantity> | Quantity \| None | None | 最大订单数量 |
min_quantity | Option<Quantity> | Quantity \| None | None | 最小订单数量 |
max_notional | Option<Money> | Money \| None | None | 最大订单名义价值 |
min_notional | Option<Money> | Money \| None | None | 最小订单名义价值 |
max_price | Option<Price> | Price \| None | None | 最大有效报价/订单价格 |
min_price | Option<Price> | Price \| None | None | 最小有效报价/订单价格 |
margin_init | Option<Decimal> | Decimal \| None | 0 | 初始保证金率 |
margin_maint | Option<Decimal> | Decimal \| None | 0 | 维持保证金率 |
maker_fee | Option<Decimal> | Decimal \| None | 0 | Maker 费率,负值表示返佣 |
taker_fee | Option<Decimal> | Decimal \| None | 0 | Taker 费率,负值表示返佣 |
tick_scheme | Option<Ustr> | str \| None | None | 已注册的可变 tick 方案名称 |
info | Option<Params> | dict \| None | None | 适配器附加元数据 |
ts_event | UnixNanos | int | Required | 事件时间戳(纳秒) |
ts_init | UnixNanos | int | Required | 初始化时间戳(纳秒) |
注意:Python 构造参数名为
instrument_id,而 Rust 内部将同一值存储为id。在 Python 侧访问时通过instrument.id属性(pyo3 绑定中#[pyo3(name = "id")]显式重命名),详见 crates/model/src/python/instruments/binary_option.rs。
字段语义要点
raw_symbol承载原生标识:以 Polymarket 为例,其合约 symbol 往往是长哈希串(条件 token ID),如文档示例中的0x12a0cb...-925449...,需原样透传,不得改写。price_precision/size_precision必须与 increment 一致:源码在new_checked中调用check_equal_u8强制price_precision == price_increment.precision、size_precision == size_increment.precision,不一致直接构造失败(见 binary_option.rs)。因此示例中price_increment = 0.001时price_precision = 3,size_increment = 0.01时size_precision = 2。margin_init/margin_maint/maker_fee/taker_fee默认为 0:可选参数不传时经unwrap_or_default()落到Decimal(0)(binary_option.rs)。其中 maker/taker 费率按订单价值百分比计算,负值即返佣。info是适配器元数据容器:以 JSON 可序列化字典形式存放交易所附加信息。Python 侧构造时传入dict,绑定层通过from_pydict转成 Rust 的Params;读取时再经 JSON 反序列化回dict(见 binary_option.rs 与py_info)。
行为特性
BinaryOption在Instrumenttrait 层面具有以下固定行为(全部可由 binary_option.rs 的实现直接验证):
- Instrument class 为
BinaryOption:instrument_class()返回InstrumentClass::BinaryOption,与CurrencyPair、CryptoPerpetual等并列。 - 永不反向(never inverse):
is_inverse()恒为false。 - 乘数与手数均为 1:
multiplier()返回Quantity::from(1),lot_size()返回Some(Quantity::from(1))。 - 无底层资产、无行权价、无期权种类:
underlying()、strike_price()、option_kind()、isin()、exchange()均返回None——二元合约本身就是标的。 - 报价/结算货币一致:
quote_currency()与settlement_currency()都返回currency字段;base_currency()为None。 - 激活与到期时间存在:
activation_ns()与expiration_ns()均返回Some(...)。 - 价格区间由交易所定义:很多交易所把二元结果报价在 0 到 1 之间,但合法价格范围(
min_price/max_price)与 tick size 一律以交易所规定为准,模型本身不做假设。 - 相等性与哈希仅看 ID:
PartialEq、Eq、Hash的实现只比较self.id,同一个合约在不同副本间可正确去重。
单元测试test_trait_accessors对这些行为做了断言(binary_option.rs),例如验证asset_class() == AssetClass::Alternative、!is_inverse()、price_precision() == 3、size_precision() == 2。
Rust 构造示例
Rust 侧推荐使用bon构建器模式(BinaryOption::builder()),必填字段在编译期强制,可选字段可省略并沿用默认值:
use jiff::Timestamp; use nautilus_core::UnixNanos; use nautilus_model::{ enums::AssetClass, identifiers::{InstrumentId, Symbol, Venue}, instruments::BinaryOption, types::{Currency, Price, Quantity}, }; use rust_decimal_macros::dec; use ustr::Ustr; let raw_symbol = Symbol::from( "0x12a0cb60174abc437bf1178367c72d11f069e1a3add20b148fb0ab4279b772b2-92544998123698303655208967887569360731013655782348975589292031774495159624905", ); let expiration: Timestamp = "2024-01-01T00:00:00Z".parse().unwrap(); let yes_outcome = BinaryOption::builder() .instrument_id(InstrumentId::new(raw_symbol, Venue::from("POLYMARKET"))) .raw_symbol(raw_symbol) .asset_class(AssetClass::Alternative) .currency(Currency::from("USDC")) .activation_ns(UnixNanos::default()) .expiration_ns(UnixNanos::from(expiration)) .price_precision(3) .size_precision(2) .price_increment(Price::from("0.001")) .size_increment(Quantity::from("0.01")) .outcome(Ustr::from("Yes")) .description(Ustr::from("Will the outcome of this market be 'Yes'?")) .min_quantity(Quantity::from("5")) .maker_fee(dec!(0)) .taker_fee(dec!(0)) .ts_event(UnixNanos::default()) .ts_init(UnixNanos::default()) .build() .unwrap();构建期校验机制
build()内部走build_checked→new_checked,执行四类正确性检查(binary_option.rs):
- 精度一致性:
check_equal_u8(price_precision, price_increment.precision, ...)与check_equal_u8(size_precision, size_increment.precision, ...); - 正增量:
check_positive_price(price_increment)、check_positive_quantity(size_increment); - tick scheme 合法性:
check_tick_scheme(tick_scheme)验证可变 tick 方案名是否已注册; - 任一检查失败即返回
CorrectnessResult错误,unwrap()会 panic,生产代码建议显式处理。
测试test_new_checked_price_precision_mismatch专门构造了price_precision = 4与price_increment = 0.001(精度 3)的不一致组合,断言构造返回Err;而test_builder_matches_new_checked则验证构建器结果与全位置参数构造结果完全一致,证明两条构造路径共享同一套校验逻辑(binary_option.rs)。
Python 构造示例
Python 侧通过 pyo3 绑定直接调用构造函数。ts_event/ts_init传纳秒整数,时间戳可用pandas.Timestamp(..., tz="UTC").value转换:
from decimal import Decimal import pandas as pd from nautilus_trader.model import AssetClass from nautilus_trader.model import BinaryOption 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 from nautilus_trader.model import Venue raw_symbol = Symbol( "0x12a0cb60174abc437bf1178367c72d11f069e1a3add20b148fb0ab4279b772b2-92544998123698303655208967887569360731013655782348975589292031774495159624905", ) price_increment = Price.from_str("0.001") size_increment = Quantity.from_str("0.01") yes_outcome = BinaryOption( instrument_id=InstrumentId(raw_symbol, Venue("POLYMARKET")), raw_symbol=raw_symbol, asset_class=AssetClass.ALTERNATIVE, currency=Currency.from_str("USDC"), activation_ns=0, expiration_ns=pd.Timestamp("2024-01-01", tz="UTC").value, price_precision=price_increment.precision, size_precision=size_increment.precision, price_increment=price_increment, size_increment=size_increment, min_quantity=Quantity.from_int(5), maker_fee=Decimal(0), taker_fee=Decimal(0), outcome="Yes", description="Will the outcome of this market be 'Yes'?", ts_event=0, ts_init=0, )Python 绑定的构造签名与序列化
Python 构造函数的完整签名定义在 crates/model/src/python/instruments/binary_option.rs:除 12 个必填参数外,outcome、description、max_quantity、min_quantity、max_notional、min_notional、max_price、min_price、margin_init、margin_maint、maker_fee、taker_fee、tick_scheme、info均可选,默认与 Rust 侧一致。绑定层最终仍调用同一套 Rust 构建器,因此price_precision与price_increment.precision不一致时同样会抛出异常。
模型还内置了字典序列化能力:
BinaryOption.to_dict()输出含type、id、raw_symbol、asset_class、currency、margin_init、maker_fee、taker_fee等全部字段的dict(outcome/description/数量/价格等可选字段按None处理,info序列化为嵌套dict);BinaryOption.from_dict(values)反序列化还原对象,test_dict_round_trip验证了往返一致性(binary_option.rs)。
这也意味着BinaryOption可以随 Parquet/Arrow 等持久化链路存储,配合 docs/concepts/event_sourcing.md 实现事件溯源。
适配器中的 BinaryOption
仓库中已有多个实盘适配器创建或消费BinaryOption,是理解该模型真实用法的第一手资料:
- Hyperliquid(二元与预测类市场):在 crates/adapters/hyperliquid/src/http/parse.rs 中通过
BinaryOption::builder()构造,并将结构化元数据暴露为BinaryOption.info(同文件第 92 行注释);解析 HIP-4 标准的 "Yes"/"No" 标签后写入outcome字段(第 1999 行附近)。 - Polymarket(预测市场结果):适配器在多个环节消费
BinaryOption,例如 crates/adapters/polymarket/src/common/models.rs 中if let InstrumentAny::BinaryOption(opt)模式匹配提取合约;行情加载、持仓对账(reconciliation)、订单解析等模块均围绕该模型展开。 - OKX(交易所自定义二元结果产品):在 crates/adapters/okx/src/common/parse.rs 中完成行情到
BinaryOption的映射。
各适配器的完整集成说明见:
- docs/integrations/hyperliquid.md
- docs/integrations/okx.md
- docs/integrations/polymarket.md
相关概念延伸
- docs/concepts/order_book.md:覆盖二元市场的订单簿行为——二元合约同样以标准订单簿驱动,价格区间在 0~1 时 tick 语义由
price_increment决定; - docs/concepts/data/:讲解引用这些合约的市场数据(行情、tick、bar)如何在 Nautilus Trader 中流转;
- docs/concepts/instruments/:
BinaryOption所在的工具族总览,可对照普通期权、期货等模型的差异。
小结
BinaryOption用一个结构体同时覆盖预测市场、二元期权与 Yes/No 合约三类场景,靠的是"通用字段 + 交易所自定义"的设计:通用性由 25 个标准字段与Instrumenttrait 保证,交易所差异则通过raw_symbol、outcome、description、info与价格区间字段吸收。构造侧的精度一致性校验(price_precision/size_precision与 increment 强绑定)从源头杜绝脏数据进入交易链路,而 Rust builder 与 Python 构造函数共享同一套校验实现,确保了双语言行为一致。配合 Hyperliquid、Polymarket、OKX 等适配器的现成实现,开发者可以快速将二元合约纳入回测与实盘策略。
【免费下载链接】nautilus_traderProduction-grade Rust-native trading engine with deterministic event-driven architecture项目地址: https://gitcode.com/GitHub_Trending/na/nautilus_trader
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考