NautilusTrader 追踪限价止损单(Trailing-Stop-Limit Order)完全指南:原理、参数与源码实现
2026/9/12 16:08:37 网站建设 项目流程

NautilusTrader 追踪限价止损单(Trailing-Stop-Limit Order)完全指南:原理、参数与源码实现

【免费下载链接】nautilus_traderProduction-grade Rust-native trading engine with deterministic event-driven architecture项目地址: https://gitcode.com/GitHub_Trending/na/nautilus_trader

导读

追踪限价止损单(Trailing-Stop-Limit)是 NautilusTrader 九种标准订单类型中两种"条件追踪"订单之一:它在市场价格朝有利方向移动时,始终让触发价与市场价保持固定偏移,并在触发后释放一张限价单(Limit order),且该限价单的价格同样随市场同步更新。本文以 NautilusTrader 官方概念文档为核心,结合crates/modelcrates/executioncrates/common中的真实源码,系统讲解其订单模型、工厂 API、Rust/Python 双语言创建方法、触发与限价计算算法、校验规则以及实盘/模拟盘中的行为边界,帮助你在策略中正确使用这一订单类型并理解底层执行机制。

什么是 Trailing-Stop-Limit 订单

按照官方概念文档 orders/trailing_stop_limit.md 的定义,Trailing-Stop-Limit 订单具有以下核心特征:

  • 它属于条件订单(Conditional order),在 FIX 协议中对应OrdType <40>=4(Stop Limit)叠加 trailing peg 字段——FIX 没有为追踪止损定义独立的OrdType,因此 NautilusTrader 在 FIX 映射中将其建模为4(Stop Limit)+ trailing peg(参见 orders/index.md 的 FIX OrdType 映射表)。
  • 在订单激活并开始追踪后,其触发价始终与"适用的市场价格"保持一个固定偏移(trailing offset)。当市场价格朝有利方向移动时,触发价随之更新(只朝有利方向收紧,绝不回退);当价格反向穿越触发价时,订单被触发。
  • 触发后释放的不是市价单,而是一张限价单。这张限价单的价格同样由limit_offset相对市场价格计算得出,并随市场移动而更新,直到触发那一刻为止。

与纯 Trailing-Stop-Market(释放市价单)不同,Trailing-Stop-Limit 把"出场执行"限定在指定的最差可接受成交价之上,代价是:在快速反转行情中,释放出的限价单可能无法成交,从而让仓位继续暴露在市场风险之下。这与 Stop-Limit 的固有限制一致——文档 Use cases 一节对此有明确说明。

适用场景:动态追踪保护 + 最差成交价约束

官方文档给出的适用场景非常聚焦:

为仓位提供动态追踪保护,同时限定一个"最差可接受成交价"。

典型用法是保护浮盈仓位:行情上涨时买入止损单(或行情下跌时卖出止损单)的触发价跟随市场抬高/压低,锁定部分利润;而一旦触发,限价单保证你不会在更差的价格成交。需要警惕的是,正如文档与源码都强调的,触发后的限价单在快速反转时可能不成交,这与 stop_limit.md 中 Stop-Limit 的风险一致。若你希望触发后必定成交,应选用 trailing_stop_market.md。

此外,如果目标交易场所(venue)不原生支持追踪止损,NautilusTrader 的OrderEmulator可以在本地模拟该订单类型:设置emulation_trigger后,本地模拟器会在触发条件满足时将其转换为LIMIT订单走正常风控与执行路径(详见 emulated.md 中"可模拟订单类型"表格,TRAILING_STOP_LIMIT的释放类型为LIMIT)。

使用 OrderFactory 创建 Trailing-Stop-Limit 订单

官方文档强调:所有示例订单都应在Strategy上下文中通过工厂创建——Python 端暴露为self.order_factory,Rust 端暴露为self.order()。工厂会自动分配 trader/strategy ID、生成 client order ID 与初始化 ID、记录初始时间戳,并为所选订单类型应用默认值(见 orders/index.md 的 Order factory 一节)。

官方示例:Currenex FX ECN 上的 AUD/USD 买入追踪限价止损

以下示例在 Currenex FX ECN 上以 0.71000 USD 的限价买入 1,250,000 AUD/USD,在 0.72000 USD 处激活,随后以距当前卖价 0.00100 USD 的偏移进行追踪,GTC 永久有效:

use nautilus_model::{ enums::{OrderSide, TimeInForce, TrailingOffsetType, TriggerType}, identifiers::InstrumentId, types::{Price, Quantity}, }; use rust_decimal_macros::dec; use ustr::Ustr; let order = self.order().trailing_stop_limit( InstrumentId::from("AUD/USD.CURRENEX"), OrderSide::Buy, Quantity::from(1_250_000), Price::from("0.71000"), // limit price dec!(0.00050), // limit_offset dec!(0.00100), // trailing_offset Some(TrailingOffsetType::Price), // optional (default PRICE) Some(Price::from("0.72000")), // activation_price None, // trigger_price (materializes from the offset on the first trail) Some(TriggerType::BidAsk), // optional (default DEFAULT) Some(TimeInForce::Gtc), // optional (default GTC) None, // expire_time Some(false), // post_only (default false) Some(true), // reduce_only (default false) None, // quote_quantity (default false) None, // display_qty None, // emulation_trigger None, // trigger_instrument_id None, // exec_algorithm_id None, // exec_algorithm_params Some(vec![Ustr::from("TRAILING_STOP")]), // tags None, // client_order_id );
from decimal import Decimal from nautilus_trader.model import InstrumentId from nautilus_trader.model import OrderSide from nautilus_trader.model import Price from nautilus_trader.model import Quantity from nautilus_trader.model import TimeInForce from nautilus_trader.model import TrailingOffsetType from nautilus_trader.model import TrailingStopLimitOrder from nautilus_trader.model import TriggerType order: TrailingStopLimitOrder = self.order_factory.trailing_stop_limit( instrument_id=InstrumentId.from_str("AUD/USD.CURRENEX"), order_side=OrderSide.BUY, quantity=Quantity.from_int(1_250_000), price=Price.from_str("0.71000"), activation_price=Price.from_str("0.72000"), trigger_type=TriggerType.BID_ASK, # <-- optional (default DEFAULT) limit_offset=Decimal("0.00050"), trailing_offset=Decimal("0.00100"), trailing_offset_type=TrailingOffsetType.PRICE, time_in_force=TimeInForce.GTC, # <-- optional (default GTC) expire_time=None, # <-- optional (default None) reduce_only=True, # <-- optional (default False) tags=["TRAILING_STOP"], # <-- optional (default None) )

工厂签名与参数详解

Rust 侧工厂方法OrderFactory::trailing_stop_limit的完整签名定义于 crates/common/src/factories/order.rs,Python 侧对应类型桩位于 python/nautilus_trader/common/init.pyi。两者参数一一对应,要点如下:

参数类型说明
instrument_idInstrumentId交易品种 ID,如"AUD/USD.CURRENEX"
order_sideOrderSideBUYSELL
quantityQuantity订单数量,必须为正数
pricePrice \| None限价。可省略——若省略,限价会在首次追踪更新时由limit_offset物化生成(详见下文"限价延迟物化")
limit_offsetDecimal限价相对市场价的偏移量,触发前限价随市场同步更新
trailing_offsetDecimal触发价相对市场价的追踪偏移量
trailing_offset_typeTrailingOffsetType \| None偏移量类型,默认PRICE
activation_pricePrice \| None激活价。订单提交后未达到该价格前不启动追踪
trigger_pricePrice \| None初始触发价。通常省略,由首次追踪从偏移量物化
trigger_typeTriggerType \| None触发方法,默认DEFAULT(等效于BID_ASK的报价行为)
time_in_forceTimeInForce \| None默认GTC;若为GTD则必须提供expire_time
expire_timeint \| NoneGTD 到期时间(Unix 纳秒),默认None
post_onlybool \| None默认false
reduce_onlybool \| None默认false,示例中置true用于只减仓
quote_quantitybool \| None默认false
display_qtyQuantity \| None冰山单可见数量,默认None
emulation_triggerTriggerType \| None本地模拟触发类型,设置后走OrderEmulator
trigger_instrument_idInstrumentId \| None跨品种触发时指定被监控的品种
exec_algorithm_id/exec_algorithm_params算法相关附加执行算法
tagsSequence[str] \| None订单标签
client_order_idClientOrderId \| None不传则由工厂生成

TrailingOffsetType:偏移量的四种表达

追踪偏移(以及限价偏移)如何"量纲化"由TrailingOffsetType决定,官方文档 orders/index.md 定义了四种取值:

  • PRICE:以价格差表示(文档示例0.00100USD 即此类);
  • BASIS_POINTS:以基点百分比表示,100 个基点 = 1%;
  • TICKS:以最小价格变动单位(tick)数量表示;
  • PRICE_TIER:venue 特定的价格档位。

注意:文档同时指出,TrailingOffsetType缺失(None)对追踪订单而言是非法的,必须在创建时显式提供。

源码级解析:触发价与限价如何随市场更新

理解 Trailing-Stop-Limit 的行为,最直接的方式是阅读它的核心计算逻辑。crates/execution/src/trailing.rs中的trailing_stop_calculate函数负责在每次市场更新时为追踪止损单计算新的触发价与限价(trailing.rs),其关键语义如下:

  1. 只朝有利方向移动(单向收紧)maybe_move闭包通过better_trigger比较候选价与当前价——OrderSide::Buyc < p才算"更优",OrderSide::Sellc > p才算"更优"。候选价若未改善,则保持原价不动。也就是说,买入追踪止损的触发价只会下移,卖出追踪止损的触发价只会上移,绝不可能反向放松。

  2. 偏移量的换算compute闭包):

    • Price:直接使用偏移量数值;
    • BasisPointsbasis * offset / 10_000(100 基点 = 1%);
    • Ticksoffset * price_increment(以 instrument 的price_increment为 tick 大小);
    • 其他类型(如PriceTier)当前计算路径会直接报错。
  3. 买卖方向的价格基点:买入订单以ask(卖价)为基点并加上偏移得到触发价/限价(basis + offset),卖出订单以bid(买价)为基点并减去偏移(basis - offset)。这与文档示例"以距当前 ask 0.00100 USD 的偏移追踪买入单"完全吻合。

  4. 触发方法决定市场数据源

    • LastPrice/MarkPrice:以最新成交价(或标记价)为基点;
    • Default/BidAsk/LastOrBidAsk:买入以 ask、卖出以 bid 为基点(Default在本地表现为BidAsk报价行为,见 trailing.rs 及测试注释);
    • DoubleLastDoubleBidAskIndexPrice等类型当前不被该计算路径支持。
  5. 触发价缺失时自动物化trigger_price以"当前订单携带的触发价"为种子(只种触发价、绝不使用激活价);若触发价尚未物化(None),首次更新的候选价会直接成为初始触发价——这正是工厂示例中把trigger_priceNone的原因(文档注释:materializes from the offset on the first trail)。

  6. Trailing-Stop-Limit 专属:当订单类型为TrailingStopLimit时,函数还会用limit_offset计算候选限价(与触发价使用同一市场基点),并通过better_limit单向收紧。trailing_stop_calculate返回(new_trigger_price, new_limit_price)二元组,None表示对应价格未改善。

计算函数在两个执行路径中的调用

同一套计算函数被两处核心组件复用(见 crates/execution/src 目录):

  • 模拟撮合引擎crates/execution/src/matching_engine/mod.rsupdate_trailing_stop_order(mod.rs):每次市场数据更新时,用price_increment、订单当前触发价、bid/ask/last调用trailing_stop_calculate;若市场数据尚不齐备导致计算失败,则记录 debug 日志并等待下一次更新;若两个价格均未改善则直接返回;否则通过generate_order_updated生成OrderUpdated事件,把新触发价/限价应用到订单上。这解释了文档所说"限价价格也随市场更新直到触发"的落地方式。
  • 本地订单模拟器crates/execution/src/order_emulator/emulator.rs(emulator.rs 附近):对设置了emulation_trigger的追踪止损单,同样调用trailing_stop_calculate更新本地触发价,并在触发条件满足时将其转换为LIMIT订单释放。

TrailingStopLimitOrder 订单模型与校验规则

订单类型的底层模型定义于 crates/model/src/orders/trailing_stop_limit.rs,TrailingStopLimitOrder结构体包含以下专属字段:

  • activation_price: Option<Price>——激活价;
  • price: Option<Price>——当前限价(触发前随市场更新);
  • trigger_price: Option<Price>——当前触发价;
  • trigger_type: TriggerType——触发方法;
  • limit_offset: Decimaltrailing_offset: Decimaltrailing_offset_type: TrailingOffsetType——两组偏移量及其类型;
  • expire_timeis_post_onlydisplay_qtytrigger_instrument_id——通用执行指令;
  • is_activated: boolis_triggered: boolts_triggered: Option<UnixNanos>——激活/触发状态及触发时间戳。

new_checked(trailing_stop_limit.rs)定义了创建时的完整校验规则,这些规则同样被 Python 与 Rust 工厂路径共用:

  • quantity必须为正数(否则报invalidQuantityfor 'quantity' not positive);
  • display_qty(若提供)不得超过quantity
  • time_in_forceGTDexpire_time必填且不能为零;
  • 订单元数据必须通过OrderInitialized::new_checked的全部不变量。

这些约束都有对应的单元测试佐证(同文件mod tests一节,如test_quantity_zero_errtest_display_qty_gt_quantity_errtest_gtd_without_expire_err)。此外,TryFrom<OrderInitialized>实现要求trigger_typelimit_offsettrailing_offsettrailing_offset_type四项在初始化事件中必须存在,否则视为谓词违反错误——说明这四项对 Trailing-Stop-Limit 而言是强制字段

值得注意的两个行为细节

  • 限价延迟物化has_price()的实现(trailing_stop_limit.rs)注释明确说明:限价在首次追踪更新从limit_offset物化之前可能为None,因此依赖 own-book / 价格的路径必须用has_price()判断而非假定限价存在。测试test_has_price_false_until_limit_materializes验证了这一点。
  • 更新事件应用update方法(trailing_stop_limit.rs)在收到OrderUpdated时同步更新pricetrigger_pricequantityleaves_qtyapply方法在收到Triggered事件时置位is_triggered并记录ts_triggered

订单状态机中的位置

TRIGGERED状态在订单生命周期中专门覆盖"stop-limit、trailing-stop-limit 或 limit-if-touched 订单在 venue 上被触发"这一情形(见 orders/index.md 的 Order status definitions 表)。触发后订单进入TRIGGERED,随后由释放出的限价单继续走ACCEPTED → PARTIALLY_FILLED → FILLED(或CANCELED/EXPIRED)等常规状态流。

实战建议与风险提示

结合官方文档与源码实现,使用 Trailing-Stop-Limit 时有几点值得注意:

  1. 与 Stop-Limit 共享的滑点与不成交风险:触发后释放的是限价单,快速反转行情下可能挂在盘口无法成交,仓位继续保持开放。若"必须离场"优先于"价格保护",请改用 Trailing-Stop-Market。
  2. reduce_only=True是常见的组合用法:示例中即为reduce_only置真,配合SimulatedExchange的行为(仓位归零时自动撤单、按剩余仓位缩减数量),可用于实现只减仓的动态保护逻辑。
  3. 触发方法与偏移类型的搭配要符合 venue 能力:不同 adapter/venue 对条件订单的支持程度不同,adapter 可能在提交前拒绝不支持的请求,或由 venue 直接拒单(见 orders/index.md 的说明)。本地模拟路径目前只接受DEFAULT/BID_ASK/LAST_PRICE作为emulation_trigger(见 emulated.md)。
  4. 触发价/限价可由偏移自动物化:不必同时提供pricetrigger_price与两个偏移量;省略价格、只给偏移,让首次追踪更新自动生成价格,是文档示例推荐的简洁写法。
  5. 追踪只收紧不回退:无论行情如何反复,触发价与限价都只会朝有利方向单向移动,这既是特性也是约束——用它做"移动止损保护",而不是"灵活调整出场价"。

相关指南

  • Orders 总览:订单概念、执行指令、TrailingOffsetType/TriggerType 枚举与 FIX OrdType 映射;
  • Emulated orders:在无原生支持的 venue 上本地模拟追踪止损;
  • Execution 概念:订单如何到达 venue、成交如何处理;
  • Stop-Limit 指南:与本文订单共享"限价触发后可能不成交"的风险模型;
  • Trailing-Stop-Market 指南:释放市价单的追踪止损变体。

延伸阅读:仓库中的关键实现位置

  • 订单模型与校验:crates/model/src/orders/trailing_stop_limit.rs
  • 触发/限价计算算法:crates/execution/src/trailing.rs
  • 模拟撮合引擎中的追踪更新:crates/execution/src/matching_engine/mod.rs
  • 本地模拟器调用:crates/execution/src/order_emulator/emulator.rs
  • Rust 工厂实现:crates/common/src/factories/order.rs
  • Python 类型桩:python/nautilus_trader/common/init.pyi

【免费下载链接】nautilus_traderProduction-grade Rust-native trading engine with deterministic event-driven architecture项目地址: https://gitcode.com/GitHub_Trending/na/nautilus_trader

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询