拓冰建站拓冰建站
首页 / 资讯中心 / 正文

NautilusTrader 值类型全解析:Price、Quantity、Money 的定点数设计与实战用法

NautilusTrader 值类型全解析Price、Quantity、Money 的定点数设计与实战用法【免费下载链接】nautilus_traderProduction-grade Rust-native trading engine with deterministic event-driven architecture项目地址: https://gitcode.com/GitHub_Trending/na/nautilus_traderNautilusTrader 是采用确定性事件驱动架构的生产级交易引擎其核心模型层通过Price、Quantity、Money三种专用值类型承载价格、数量与金额等交易概念。本文以 docs/concepts/value_types.md 为骨架结合 crates/model/src/types 下的 Rust 源码与测试系统讲解这三种类型的不变性设计、定点数存储原理、算术运算的类型规则、精度处理机制与典型实战模式帮助你在回测与实盘策略中写出类型安全、结果可复现的交易代码。三种值类型总览类型用途是否允许负数是否带货币Quantity交易数量、订单数量、持仓数量否否Price市场价格、买卖报价、价格档位是否Money货币金额、盈亏PL、账户余额是是从 Rust 源码看三者分别定义于 price.rs、quantity.rs 与 money.rs。模块文档明确给出了各自的领域约束Price可以取负值适用于价差spread、基差交易或部分衍生品场景见 price.rs 模块注释Quantity强制非负用于交易数量、订单量与持仓量见 quantity.rs 模块注释Money同时支持正负值用于扣款、亏损等并在算术运算中强制货币一致性见 money.rs 模块注释。不可变性设计所有值类型都是**不可变immutable**的一旦构造完成便无法修改所有运算都返回新实例而不是原地改动。from nautilus_trader.model import Quantity qty1 Quantity(100, precision0) qty2 Quantity(50, precision0) # 这创建了一个新的 Quantityqty1 与 qty2 保持不变 result qty1 qty2 print(qty1) # 100 print(qty2) # 50 print(result) # 150这一设计带来三方面收益线程安全不可变值可被多个线程安全共享无需同步原语。这对 NautilusTrader 的事件驱动、多 Actor 架构尤为关键——同一价格对象可被策略、风控与执行组件并发引用可预测性值永远不会意外改变调试时无需追踪谁改了这个价格可哈希性不可变类型可作为字典键与集合元素。Rust 侧Hash、Eq、Ord等 trait 的实现让这些值可以直接进入HashSet、BTreeSet等容器fixed_scale.rs 中的测试即验证了跨精度下的哈希与排序一致性。Rust 侧同样遵循该约定三个模块的文档均声明All arithmetic operations return new instances见 price.rs。算术运算与返回类型规则值类型支持标准算术运算符、-、*、/、%、//以及一元运算符-、、abs。返回类型取决于运算符与操作数类型——这一设计是值类型的核心灵魂必须理解清楚。同类型二元运算加减保持类型乘除返回 Decimal同类型值的加减法保持原类型保留领域含义价格加价格仍是价格运算结果Quantity QuantityQuantityQuantity - QuantityQuantityPrice PricePricePrice - PricePriceMoney MoneyMoneyMoney - MoneyMoneyfrom nautilus_trader.model import Price price1 Price(100.50, precision2) price2 Price(0.25, precision2) result price1 price2 # 返回 Price(100.75, precision2) print(type(result)) # class nautilus_trader.model.Price而同类型值之间的乘法、除法、整除与取模则返回Decimal运算结果Price * PriceDecimalPrice / PriceDecimalPrice // PriceDecimalPrice % PriceDecimalQuantity与Money遵循同样的模式。为什么乘除不返回原类型因为结果的量纲dimension已经改变价格乘价格得到价格平方而非价格数量除以数量得到无量纲的比率而非数量。返回Decimal让量纲变化显式化防止把结果误当作带原单位的数值继续参与领域运算。这一点在 price.rs 的算术行为表中也有完整对应Price * Price的 Rust 侧乘法实现同样遵循量纲语义。一元运算一元运算符在结果对原类型合法时保持值类型运算PriceQuantityMoney-x取负PriceDecimalMoneyx取正PriceQuantityMoneyabs(x)PriceQuantityMoneyint(x)intintintfloat(x)floatfloatfloatround(x)DecimalDecimalDecimal特别地Quantity.__neg__返回Decimal而非Quantity因为Quantity是无符号类型无法表示负值——负的数量在领域上没有意义。from nautilus_trader.model import Currency, Money, Price, Quantity USD Currency.from_str(USD) price Price(100.50, precision2) print(-price) # -100.50 print(type(-price)) # class nautilus_trader.model.Price money Money(-50.00, USD) print(abs(money)) # 50.00 USD print(type(abs(money))) # class nautilus_trader.model.Money qty Quantity(10, precision0) print(qty) # 10 print(type(qty)) # class nautilus_trader.model.Quantity混合类型运算遵循 Python 数值塔与int、float、Decimal等数值类型混合运算时返回类型遵循 Python 的数值塔约定运算向更一般的类型拓宽——float运算返回float而int与Decimal运算返回Decimal以保留精度。该规则适用于全部六种二元运算符、-、*、/、//、%且两个方向值 op 标量与标量 op 值都成立左操作数右操作数结果类型值类型intDecimal值类型floatfloat值类型DecimalDecimalint值类型Decimalfloat值类型floatDecimal值类型Decimalfrom decimal import Decimal from nautilus_trader.model import Quantity qty Quantity(100, precision0) # Quantity int - Decimal result1 qty 50 print(type(result1)) # class decimal.Decimal # Quantity float - float result2 qty 50.5 print(type(result2)) # class float # Quantity Decimal - Decimal result3 qty Decimal(50) print(type(result3)) # class decimal.DecimalRust 侧的行为与此严格对应price.rs 的算术表列出了Price Decimal - Decimal、Price f64 - f64等组合Quantity与Money亦然保证 Rust 与 Python 双端结果一致。精度处理机制每个值类型都携带一个精度precision表示小数位数Price与Quantity显式存储precision字段而Money使用其货币的精度。精度在构造时确定且不可变不存在未指定精度的状态。定点数表示底层是整数不是浮点值类型内部以整数形式存储按全局固定精度缩放high-precision 模式下为 10^16标准模式下为 10^9而不是浮点数。精度字段只记录构造时使用的小数位数控制显示格式化与序列化但底层原始值始终使用全局标度。对应的常量定义在 fixed.rs标准模式未启用high-precisionfeature下FIXED_PRECISION 9、FIXED_SCALAR 10^9、底层用 64 位整数PriceRaw i64、QuantityRaw u64、MoneyRaw i64启用high-precisionfeature 后FIXED_PRECISION 16、FIXED_SCALAR 10^16底层切换到 128 位整数i128/u128并在 Arrow 中以FixedSizeBinary(16)表示见 fixed.rs。from nautilus_trader.model import Price p1 Price(1.23, precision2) # 显示为 1.23 p2 Price(1.230, precision3) # 显示为 1.230 p1 p2 # True底层数值相同 str(p1) # 1.23 str(p2) # 1.230精度控制显示而非身份。两个十进制数值相同但精度不同的价格相等。precision字段决定字符串格式化与显示的小数位数但相等性基于底层数值。这是文档强调的核心结论也是 fixed_scale.rs 中大量跨精度比较测试如#[case(1, 1, Ordering::Equal)]等所验证的行为比较与哈希会考虑标度差异而不做四舍五入。行情序列化会携带精度元数据。当行情数据类型quotes、trades、order book deltas写入 Parquet 或 Arrow 格式时精度会存入文件元数据以便正确解码数值。同一文件内的所有行情值必须共享同一精度。:::note 如果某个交易所更改了合约的 tick size从而改变精度变更前后写入的数据文件将具有不同的精度元数据不应合并到同一个文件中。 :::关于合约级精度如何约束合法价格与数量参见 Instruments 指南的 Precision 章节price_precision与size_precision规定了订单价格、触发价格、成交价与订单数量、成交数量的最大小数位数且价格增量tick size的精度必须与price_precision匹配、数量增量的精度必须与size_precision匹配见 instruments/index.md。值得一提的实现细节为兼容 2025 年 12 月 16 日之前 V2 wrangler 写入的旧目录数据其使用int(value * FIXED_SCALAR)引入了浮点误差Arrow 解码路径会通过correct_raw_i64/correct_raw_i128等修正函数把原始值就近舍入到合法的标度倍数见 fixed.rs 模块文档这保证了旧数据的向后兼容。算术精度取操作数的最大精度不同精度的值做算术运算时结果采用操作数中的最大精度。from nautilus_trader.model import Price price1 Price(100.5, precision1) # 1 位小数 price2 Price(0.125, precision3) # 3 位小数 result price1 price2 print(result) # 100.625 print(result.precision) # 3取 1 和 3 的最大值这也与 Rust 侧实现一致price.rs 的算术表注明Price Price的精度取两个操作数的最大值。类型专属约束Quantity非负约束Quantity表示非负数量。尝试构造负数量或用较大的数量减去较小的数量结果为负都会报错from nautilus_trader.model import Quantity # 触发 ValueErrorQuantity 不能为负 qty Quantity(-100, precision0) # 同样触发 ValueError qty1 Quantity(50, precision0) qty2 Quantity(100, precision0) result qty1 - qty2 # 结果为 -50非法Rust 侧对应实现位于 quantity.rs其中Quantity - Quantity在结果可能为负时会触发 panic见 quantity.rs 的算术行为表。Money货币一致性约束Money值携带货币。Money之间的加减运算要求货币匹配from nautilus_trader.model import Currency, Money USD Currency.from_str(USD) EUR Currency.from_str(EUR) usd_amount Money(100.00, USD) eur_amount Money(50.00, EUR) # 合法——同货币 result usd_amount Money(25.00, USD) # 触发 ValueError——货币不匹配 result usd_amount eur_amount从 money.rs 的文档可知Rust 侧货币不匹配的加减会直接 panic且Money的排序行为是Rust 中先按货币代码字典序、再按标度调整后的金额排序不做跨币种换算Python 侧对不同货币代码的比较会直接拒绝。这一点在跨币种账户与组合管理的排序场景中需要特别注意。实战常用模式累加值不可变类型的标准写法由于值类型不可变累加通过重新赋值实现from nautilus_trader.model import Currency, Money USD Currency.from_str(USD) total Money(0.00, USD) amounts [Money(100.00, USD), Money(50.00, USD), Money(25.00, USD)] for amount in amounts: total total amount # 重新绑定到新的 Money 实例 print(total) # 175.00 USD转换为其他类型值类型提供多种转换方法from nautilus_trader.model import Price price Price(123.456, precision3) # 转换为 Decimal保留精度 decimal_value price.as_decimal() # 转换为 float float_value price.as_double() # 转换为字符串 string_value str(price) # 123.456这些方法在 Rust 侧均有对应实现as_decimal()定义于 price.rs底层通过scaled_raw_to_decimal将固定标度原始值还原为Decimalfrom_raw/from_raw_checked见 price.rs则用于从原始整数构造值——注意 fixed.rs 明确要求from_raw的原始值必须是该精度下标度因子的合法倍数典型来源是既有值的.raw字段或 Nautilus 产生的 Arrow 数据否则 debug 构建下会 panicrelease 构建下可能得到错误值。从字符串构造支持从字符串表示解析值类型from nautilus_trader.model import Money, Price, Quantity qty Quantity.from_str(100.5) price Price.from_str(99.95) money Money.from_str(1000.00 USD)Rust 侧通过FromStrtrait 实现impl FromStr for Price位于 price.rsPython 绑定与之一致保证双端解析行为统一。小结NautilusTrader 的Price、Quantity、Money值类型是引擎确定性计算承诺的基石不可变语义带来线程安全与可预测性定点数整数存储配合high-precisionfeature9 位/16 位精度切换消除了浮点误差让跨平台回测结果严格可复现量纲感知的算术类型规则从类型系统层面杜绝了价格平方当价格用这类隐患精度元数据随行情数据写入 Parquet/Arrow保障了数据管道往返无损。对策略开发者而言掌握以下要点即可写出正确高效的代码加减同类型值返回原类型乘除返回Decimal混用标量时让Decimal/int走Decimal、float走float精度不同取最大者Quantity不可为负、Money运算需同币种数据落盘时保证同文件内精度一致。这些规则在 Rust 与 Python 两端行为完全对齐是 NautilusTrader 跨语言一致性的典型体现。【免费下载链接】nautilus_traderProduction-grade Rust-native trading engine with deterministic event-driven architecture项目地址: https://gitcode.com/GitHub_Trending/na/nautilus_trader创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门