Nautilus Trader 期权交易完全指南:Greeks 订阅、期权链聚合与回测实战
【免费下载链接】nautilus_traderProduction-grade Rust-native trading engine with deterministic event-driven architecture项目地址: https://gitcode.com/GitHub_Trending/na/nautilus_trader
Nautilus Trader 对期权交易提供了一流的原生支持,覆盖传统交易所与加密货币市场,包括期权专用工具类型、交易所实时 Greeks 数据流、期权链(Option Chain)聚合,以及用于风险管理的本地 Black-Scholes Greeks 计算器。本文以docs/concepts/options.md为主线,结合crates/data/src/option_chains/下OptionChainManager、OptionChainAggregator、AtmTracker的 Rust 源码实现,系统讲解期权工具类型、Greeks 订阅方式、StrikeRange 行权价过滤、Snapshot/Raw 双模式、期权链回测配置与架构原理,帮助读者从订阅 API 到引擎内部实现建立完整认知。
期权工具类型(Option Instrument Types)
平台定义了五类期权工具,覆盖从传统交易所到加密衍生品的全部场景:
| 工具类型 | 说明 |
|---|---|
OptionContract | 交易所上市的期权合约,带行权价(strike)与到期日(expiry)。 |
OptionSpread | 交易所定义的多元腿(multi-leg)期权策略,作为单一行情行(one line)报价。 |
CryptoOption | 加密期权,以加密货币报价/结算,支持 inverse 或 quanto 风格。 |
CryptoOptionSpread | 加密期权价差组合,带 inverse、结算货币与小数合约规模。 |
BinaryOption | 固定赔付期权,结算结果为 0 或 1。 |
与 Greeks 相关的元数据差异
不同工具类型携带的 Greeks 相关元数据差异显著:
OptionContract、CryptoOption:包含完整的 Greeks 输入,如strike_price、option_kind(CALL/PUT)、expiration_ns、underlying、multiplier。OptionSpread、CryptoOptionSpread:由交易所定义并作为单一可交易工具发布的多元腿策略,具有underlying、expiration_ns和strategy_type(交易所定义代码)。价差本身不携带strike_price或option_kind;当适配器提供腿级细节时,保存在info字段中。订单针对价差作为单一行情行执行。CryptoOptionSpread额外携带is_inverse与settlement_currency,用于 Deribit 等场所。BinaryOption:具有expiration_ns与outcome/description,但没有strike_price、option_kind或underlying。
从源码看,期权链聚合器在解析工具时正是依赖这些元数据做筛选。在 manager.rs 的resolve_instruments中,从缓存中按 venue、underlying、expiration_ns、settlement_currency精确匹配,并只收录具有strike_price()与option_kind()的合约,将其映射为HashMap<InstrumentId, (Price, OptionKind)>存入聚合器——这就是整个期权链按行权价建缓冲(BTreeMap<Price, OptionStrikeData>)的基础。
订阅实时 Greeks
Deribit、Bybit、OKX 等交易所会在期权市场发布实时 Greeks。Nautilus 提供两个订阅层级:
- 单合约 Greeks(Per-instrument):订阅单个期权合约。
- 期权链切片(Option chain slices):订阅整个期权序列(series)的聚合视图。
单合约 Greeks 订阅
在 Actor 或 Strategy 中订阅单个期权合约的交易所 Greeks:
from nautilus_trader.model import ClientId client_id = ClientId("DERIBIT") self.subscribe_option_greeks(instrument_id, client_id=client_id)通过实现on_option_greeks处理器接收更新:
def on_option_greeks(self, greeks) -> None: self.log.info( f"{greeks.instrument_id}: " f"delta={greeks.delta:.4f} gamma={greeks.gamma:.6f} " f"vega={greeks.vega:.4f} theta={greeks.theta:.4f} " f"mark_iv={greeks.mark_iv} underlying={greeks.underlying_price}" )停止接收更新:
self.unsubscribe_option_greeks(instrument_id, client_id=client_id)在引擎内部,每个OptionGreeks事件通过消息总线(msgbus)主题switchboard::get_option_greeks_topic(instrument_id)分发,OptionChainGreeksHandler负责接收并路由给对应系列的聚合器(见 manager.rs)。
期权链订阅
期权链订阅将整个期权序列所有行权价的报价与 Greeks 聚合成OptionChainSlice快照。DataEngine为每个序列创建一个 RustOptionChainManager,并持有其生命周期:创建管理器、路由进入的数据、运行快照定时器、排空线上(wire)订阅变更。
from nautilus_trader.model import OptionSeriesId from nautilus_trader.model import StrikeRange series_id = OptionSeriesId(...) # venue, underlying, settlement currency, expiry # Subscribe to 5 strikes above and below ATM, snapshot every 1000ms strike_range = StrikeRange.atm_relative(strikes_above=5, strikes_below=5) self.subscribe_option_chain( series_id, strike_range=strike_range, snapshot_interval_ms=1000, )实现on_option_chain处理器接收快照:
def on_option_chain(self, chain) -> None: for strike in chain.strikes(): call = chain.get_call(strike) put = chain.get_put(strike) if call and call.greeks: self.log.info(f"Call {strike}: delta={call.greeks.delta:.4f}")引擎侧(manager.rs 的create_and_setup)在收到SubscribeOptionChain后的完整动作是:从缓存解析系列全部工具 → 创建AtmTracker(并按首个行权价精度设置 forward price 精度)→ 创建OptionChainAggregator→ 依据snapshot_interval_ms判断 raw/snapshot 模式 → 为初始活跃集合注册 msgbus 处理器 → 向数据客户端转发「报价 + Greeks + 工具状态」三类订阅 → 按需设置快照定时器。
StrikeRange 行权价过滤
StrikeRange控制链订阅中哪些行权价处于活跃状态:
| 变体 | 说明 | 示例 |
|---|---|---|
Fixed | 订阅一组显式行权价。 | StrikeRange.fixed([...]) |
AtmRelative | ATM 上方 N 档与下方 N 档。 | StrikeRange.atm_relative(5, 5) |
AtmPercent | ATM 价格周围百分比区间内的所有行权价。 | StrikeRange.atm_percent(0.10) |
Delta | call 或 put 的 delta 接近目标值的行权价。 | StrikeRange.delta(0.25, 0.05) |
在 Rust 侧(option_chain.rs),StrikeRange是一个带序列化支持的四变体枚举:Fixed(Vec<Price>)、AtmRelative { strikes_above, strikes_below }、AtmPercent { pct }、Delta { target, tolerance }。其resolve()方法行为如下:
- Fixed:与可用行权价集合取交集后返回。
- AtmRelative:通过二分查找(
binary_search)定位最接近 ATM 的行权价索引,再向两侧各取 N 档,越界处用saturating_sub/saturating_add截断。 - AtmPercent:计算每个行权价与 ATM 的百分比距离
|s - atm| / |atm|,保留距离不超过pct的行权价。 - Delta:模型层无 Greeks 时无法解析,回退为 ATM 两侧各 5 档(
DEFAULT_DELTA_FALLBACK_STRIKES = 5)的 ATM 相对窗口;真正的 Delta 解析由聚合器基于已积累的 Greeks 完成。
动态行权价区间(AtmRelative/AtmPercent/Delta)的订阅会延迟到 ATM 价格确定之后。ATM 来源于OptionGreeks.underlying_price中的交易所参考价。它也可以通过 HTTP 为该序列拉取参考价预先填充,实现实时 WebSocket ticks 到达前的即时引导(instant bootstrap)。随着 ATM 移动,活跃行权价集合会自动再平衡(rebalance)。
Delta 解析细节(见 aggregator.rs 的resolve_delta):
- 依据交易所 Greeks:当某行权价的 call 或 put delta 绝对值(call 为正、put 为负,均按绝对值比较)落在
target ± tolerance区间内时,该行权价激活。典型的虚值(OTM)目标如0.25会在 ATM 两侧各选出一个行权价。 - 在 ATM 参考价未知前,
Delta与其他动态区间一样延迟。 - ATM 已知后,若没有任何活跃行权价的 Greeks 匹配该区间(包括 Greeks 尚未到达时),
Delta回退到 ATM 两侧各 5 档的窗口。 - 从回退窗口切换到选中 Delta 行权价之前,聚合器会等待回退窗口内每个腿都获得 Greeks(
delta_window_ready检查pending_greeks与缓冲中已有 Greeks),避免早期不完整更新导致相邻行权价被错误取消订阅。
快照模式与原始模式(Snapshot vs. Raw mode)
snapshot_interval_ms参数控制发布行为:
- 快照模式(
snapshot_interval_ms=1000):报价与 Greeks 累积在缓冲中,由定时器周期性发布为OptionChainSlice。适合定期组合再平衡或 UI 展示。 - 原始模式(
snapshot_interval_ms=None):活跃工具的每次报价或 Greeks 更新都立即发布切片。适合对单笔更新敏感的延迟敏感型策略。
源码实现(manager.rs)以raw_mode = cmd.snapshot_interval_ms.is_none()区分两种模式:raw 模式下handle_quote()/handle_greeks()在更新聚合器后立即调用publish_slice()(前提是已 bootstrap 且该工具处于活跃集);快照模式则通过setup_timer以OptionChain|{series_id}|{interval_ms}为定时器名,将OptionChainSlicePublisher回调挂到时钟上,周期触发publish_slice()。
回测期权链(Backtesting Option Chains)
期权链回测与实盘订阅走同一套OptionChainManager与OptionChainAggregator路径。前提是 Nautilus Parquet catalog 中已包含期权工具及构建链所需的单合约数据:
- 每个期权合约的
QuoteTick记录,携带回放的最优买卖价(BBO)。 - 每个期权合约的
OptionGreeks记录,携带 delta、隐含波动率、convention 以及用于播种 ATM 的underlying_price。 - 与上述工具 ID 对应的
CryptoOption或OptionContract工具。
Tardis 回放数据满足该契约:期权簿快照或报价写入为QuoteTick,option_summary消息写入为OptionGreeks。回测运行期间不会下载或请求缺失的 catalog 数据。
为序列中的期权工具配置带两条数据流的BacktestNode运行:
data = [ BacktestDataConfig( data_type="QuoteTick", catalog_path="/path/to/catalog", instrument_ids=option_instrument_ids, ), BacktestDataConfig( data_type="OptionGreeks", catalog_path="/path/to/catalog", instrument_ids=option_instrument_ids, ), ]然后在策略中订阅:
strike_range = StrikeRange.delta(0.25, 0.05) self.subscribe_option_chain( series_id, strike_range=strike_range, snapshot_interval_ms=1000, )使用snapshot_interval_ms=None进入 raw 模式(活跃工具每次报价或 Greeks 更新即发布切片);使用整数间隔进入减薄快照(thinned snapshot)模式——按定时器节奏发布整条链,显著降低大链的事件量。
聚合语义:每个OptionChainSlice按工具 ID 关联最新 BBO 与 Greeks,再按行权价与期权方向(call/put)分组。报价可能先于 Greeks 到达,Greeks 也可能先于报价到达;聚合器保持各自最新状态,并在两者齐备时一并挂接(Greeks 先到时暂存于pending_greeks,见 aggregator.rs)。OptionGreeks中的underlying_price驱动 ATM 检测。
选择策略可在订阅区间内完成,也可在策略内部完成:
- 货币性(Moneyness):使用
StrikeRange.atm_relative(...)或StrikeRange.atm_percent(...)。 - Delta:使用
StrikeRange.delta(target, tolerance),或在on_option_chain中检查entry.greeks.delta。 - 行权价:使用
StrikeRange.fixed([...]),或读取chain.get_call(strike)与chain.get_put(strike)。
在 Rust 示例 tardis_option_chain.rs 中可以看到两种策略内选择:select_by_delta遍历slice.calls与slice.puts,计算(greeks.delta.abs() - target).abs()选取距目标最近的合约;select_by_strike则直接通过get_call/get_put取指定行权价。示例以cargo run -p nautilus-backtest --features examples,streaming --example tardis-option-chain运行,SELECTION常量可切换"delta"或"strike"两种选择方式。
撮合语义:期权撮合由报价驱动。市价单与可成交限价单作为 taker 以对手方回放 BBO 成交;被动限价单挂在模拟盘口上,后续 BBO 更新穿越限价时作为 maker 成交。模型不模拟期权的 L2 队列位置。
期权手续费模型在模拟交易所上配置,而非按交易所名称推断:
from decimal import Decimal from nautilus_trader.execution import CappedOptionFeeModel from nautilus_trader.execution import TieredNotionalOptionFeeModel deribit_like = CappedOptionFeeModel( maker_rate=Decimal("0.0003"), taker_rate=Decimal("0.0003"), ) okx_like = TieredNotionalOptionFeeModel( maker_rate=Decimal("0.0002"), taker_rate=Decimal("0.0005"), )将其中任一对象作为fee_model传入BacktestVenueConfig。Rust 侧使用FeeModelAny::CappedOption(CappedOptionFeeModel::new(...))与FeeModelAny::TieredNotionalOption(TieredNotionalOptionFeeModel::new(...))(见 fee.rs 及示例 tardis_option_chain.rs)。两个模型都实现统一的FeeModeltrait,其核心接口get_commission/get_commission_with_context接受订单、成交量、成交价、工具(及可选的基础资产价格上下文)返回Money佣金。
参考示例:examples/backtest/tardis_option_chain.py 与 crates/backtest/examples/tardis_option_chain.rs。
期权链架构(Option Chain Architecture)
期权链系统是事件驱动的,围绕按序列隔离(per-series isolation)构建。DataEngine为每个订阅的期权序列创建一个 RustOptionChainManager。管理器包装OptionChainAggregator与AtmTracker,注册消息总线处理器,发布快照,并将线上订阅变更排入队列供引擎排空。
在 Rust 实现中,DataEngine以AHashMap<OptionSeriesId, Rc<RefCell<OptionChainManager>>>持有每个活跃序列对应的管理器(见 manager.rs),每个管理器自包含聚合器、msgbus 处理器与定时器。
组件职责
DataEngine
每个活跃OptionSeriesId持有一个OptionChainManager。收到SubscribeOptionChain时:从缓存解析工具、为动态行权价区间请求序列参考价、创建管理器、向数据客户端订阅活跃工具、设置快照定时器。每次定时器 tick 时:检查再平衡、发布快照、将线上订阅变更排队供引擎排空。收到UnsubscribeOptionChain或所有工具到期时:拆除管理器、取消定时器、退订线上数据流。
OptionChainManager
围绕OptionChainAggregator与AtmTracker的按序列 Rust 管理器。DataEngine通过handle_quote()与handle_greeks()向它喂入市场数据。快照模式下,定时器回调调用publish_slice();raw 模式下,每个活跃工具的报价或 Greeks 更新立即调用publish_slice()。管理器在首个 ATM 价格到达时在内部引导(bootstrap)活跃工具集——maybe_bootstrap()检查bootstrapped标志与atm_tracker().atm_price(),一旦 ATM 就绪即调用recompute_active_set()计算活跃集、批量注册 msgbus 处理器,并为每个活跃工具排队三条订阅命令(Quotes、OptionGreeks、InstrumentStatus)。
生命周期管理同样完整:teardown()退订活跃工具的 msgbus 处理器并取消定时器;handle_instrument_expired()在工具到期时将其从聚合器移除、注销处理器、排队线上退订,并在整个目录清空时通知引擎拆除管理器(manager.rs)。
OptionChainAggregator
以 keep-latest 语义将报价与 Greeks 累积进 call/put 缓冲(内部为BTreeMap<Price, OptionStrikeData>,天然按行权价有序)。上次快照后未更新的工具仍会出现在后续快照中。Greeks 先于报价到达的暂存于pending_grees缓冲,首个报价到达时挂接。每次snapshot()调用产出不可变OptionChainSlice——快照只过滤活跃行权价并克隆缓冲数据,因此不会破坏 keep-latest 状态(见 aggregator.rs)。
AtmTracker
从进入的OptionGreeks事件中的underlying_price字段响应式推导 ATM 价格(atm_tracker.rs 的update_from_option_greeks将 forward price 以既定精度(默认 2 位,由set_forward_precision覆盖)转为Price)。可通过set_initial_price用 HTTP 参考价预填充,实现无需等待 WebSocket ticks 的即时引导。后续实时更新会正常覆盖该值。
引导与再平衡(Bootstrap and Rebalancing)
对动态行权价区间(AtmRelative、AtmPercent、Delta),活跃工具集在 ATM 价格确定前无法确定,有两条引导路径:
即时引导(参考价可用):
DataEngine收到SubscribeOptionChain,从缓存解析该序列全部工具,并向数据客户端请求参考价。- 参考价响应到达后,引擎以预填充的 ATM 价格创建管理器,管理器在构造期间计算活跃行权价集。
- 引擎立即订阅活跃工具。
延迟引导(无参考价):
- 引擎没有匹配的客户端或缓存期权工具、客户端报告无参考价、请求失败、或请求 30 秒超时。
- 引擎以无初始 ATM 价格创建管理器,活跃集为空。若请求到达了持有缓存样本期权的客户端,引擎订阅该样本的 Greeks 作为引导源;若无客户端或样本,引导仍依赖另一订阅中已流动的相关 Greeks 数据。
- 当引擎通过
handle_greeks()喂入携带underlying_price的OptionGreeks事件时,管理器引导活跃工具集、注册消息总线处理器,并将新的线上订阅排队供引擎排空。样本订阅并入活跃集或释放。
引导完成后,聚合器监控 ATM 漂移。每次快照定时器 tick,管理器调用聚合器的check_rebalance()获取需增删的工具。滞回阈值(hysteresis)与冷却期(cooldown)防止行权价边界附近的频繁抖动(thrashing)。
从源码看再平衡逻辑(aggregator.rs):
Fixed区间永不再平衡。- 无 ATM 价格时返回
None。 - 非 Delta 区间:ATM 最接近行权价未变则返回
None;否则检查滞回——价格须穿过到下一行权价间距的hysteresis比例(默认值来自DEFAULT_REBALANCE_HYSTERESIS)才允许切换。 - 冷却期:距上次再平衡不足
DEFAULT_REBALANCE_COOLDOWN纳秒则跳过。 - Delta 区间:跳过 ATM 位移与滞回门控(其活跃集由 Greeks 解析而非 ATM 窗口),任何解析集变化即再平衡,但仍受冷却期节流;无增删的 no-op 再平衡被抑制以免重置冷却时间戳。
OptionGreeks 数据类型
OptionGreeks携带交易所提供的单一期权合约的敏感度与隐含波动率:
| 字段 | 类型 | 说明 |
|---|---|---|
instrument_id | InstrumentId | 这些 Greeks 适用的期权合约。 |
convention | GreeksConvention | Greeks 的计价(numeraire)惯例。 |
delta | float | 期权价格对每单位基础资产的变动率。 |
gamma | float | delta 对每单位基础资产的变动率。 |
vega | float | 交易所报告的 vega。 |
theta | float | 交易所报告的 theta。 |
rho | float | 交易所报告的 rho;默认为零。 |
mark_iv | float或 None | 标记隐含波动率。 |
bid_iv | float或 None | 买价隐含波动率。 |
ask_iv | float或 None | 卖价隐含波动率。 |
underlying_price | float或 None | 计算时刻的基础资产价格。 |
open_interest | float或 None | 合约未平仓量。 |
ts_event | int | 事件发生的 UNIX 纳秒时间戳。 |
ts_init | int | 初始化时的 UNIX 纳秒时间戳。 |
在 Rust 定义中(option_chain.rs),OptionGreeks为#[repr(C)]结构体,通过Deref到OptionGreekValues直接暴露delta/gamma/vega/theta/rho字段,并实现HasGreeks与Serializable,同时支持 Python 绑定(nautilus_trader.model模块),因而可无缝用于 Python 策略与回测。
OptionChainSlice 数据类型
OptionChainSlice是整个期权序列在某一时刻的快照。
属性:
| 属性 | 类型 | 说明 |
|---|---|---|
series_id | OptionSeriesId | 期权序列标识符。 |
atm_strike | Price或 None | 当前 ATM 行权价(若已确定)。 |
ts_event | int | UNIX 纳秒时间戳。 |
ts_init | int | UNIX 纳秒时间戳。 |
Call 与 put 数据通过方法访问而非直接属性。每个OptionStrikeData(option_chain.rs)包含该行权价的quote(QuoteTick)与可选的greeks(OptionGreeks)。底层OptionChainSlice以BTreeMap<Price, OptionStrikeData>存储 calls 与 puts(option_chain.rs),保证按行权价有序遍历。
方法:
strikes():链中全部唯一行权价。strike_count()、call_count()、put_count():各类计数。get_call(strike)、get_put(strike):完整OptionStrikeData。get_call_greeks(strike)、get_put_greeks(strike):仅 Greeks。get_call_quote(strike)、get_put_quote(strike):仅报价。is_empty():链中无数据时为真。
适配器支持
当前支持期权 Greeks 订阅的适配器:
| 适配器 | 单合约 Greeks | 期权链 |
|---|---|---|
| Deribit | ✓ | ✓ |
| Bybit | ✓ | ✓ |
| OKX | ✓ | - |
延伸阅读
- Greeks —— 本地 Greeks 计算与组合风险管理。
- Data —— 内置数据类型与订阅模型。
- Actors —— 订阅与处理器参考表。
- 期权链核心实现:
crates/data/src/option_chains/下的 manager.rs、aggregator.rs 与 atm_tracker.rs。 - 期权链数据模型:crates/model/src/data/option_chain.rs。
【免费下载链接】nautilus_traderProduction-grade Rust-native trading engine with deterministic event-driven architecture项目地址: https://gitcode.com/GitHub_Trending/na/nautilus_trader
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考