NautilusTrader量化交易终极指南-第6章第2节-领域模型-精度就是生命线
2026/9/16 8:53:10 网站建设 项目流程

NautilusTrader量化交易终极指南-第6章第2节-领域模型-精度就是生命线

一句话导读:交易系统里没有"差不多",价格点一位、数量错一位,钱就没了;NautilusTrader 用定点数把精度焊死。

本文导航

  • 为什么不能用 float 算钱
  • Currency / Money:钱的字典与实体
  • Price / Quantity:两个带精度的定点数
  • price_precision / size_precision / make_qty 的正确性细节
  • 一个价格精度错一位的真实事故
  • 小结
  • 下节预告

1. 浮点数的原罪

先做个实验。打开 Python 敲三行:

>>>0.1+0.20.30000000000000004

这就是 IEEE 754 双精度浮点的老毛病——0.1 和 0.2 在二进制里是无限循环小数,凑不齐。平时打印出来看着像 0.3,可一进==比较或者累加成千上万次,误差就滚雪球。

对回测研究来说,这点误差可能无伤大雅;但对拿真金白银去下单的实盘交易,这就是定时炸弹。想一想:你用 float 算买入金额,累加个一千笔,差出来一个价位,成交了,谁来赔?

我见过最离谱的案例(也正是本节的"事故"部分),浮点误差导致的还不是"几毛钱"的问题,而是数量级错误。这点下面细说。总之结论就一条:金融计算,别用 float 当真相源。


2. Currency 与 Money:钱的字典和实体

NautilusTrader 把这套东西建模得很讲究,两张图看全:

定义

被引用

amount + currency

拥有

拥有

定价依据

Currency

code + precision + iso4217

Money

一笔真实的钱

Instrument

price_precision

size_precision

Currency:币种的"字典"

Currency描述一个币种,携带code(如USDEUR)和precision(小数位)。一套系统里同一币种只有一份定义,所以往往用 dict 去重:

fromnautilus_trader.modelimportCurrency usd=Currency.from_str("USD")print(usd.precision)# 2

Currency是"币种是什么",它自己不带具体金额。

Money:带着币种的"一笔钱"

真正算钱要用Money,它把金额和币种绑在一起:

fromnautilus_trader.modelimportMoney cost=Money(299.99,"USD")print(cost.currency.code)# USD

Money的好处是金额永远跟币种绑定,杜绝"计量单位错乱"。比如 USD 和 EUR 不可能被直接相加,因为值不同。这让引擎在跨币种换算、结算时能自动做校验。


3. Price 和 Quantity:两个带精度的定点数

这两个是定点数型的核心。所谓"定点",就是内部不靠二进制浮点存储,而是按最小增量来精确表达。

  • Price:价格,受price_precision约束。
  • Quantity:数量,受size_precision约束,还要求能被size_increment整除。

举外汇对的例子,EUR/USD 的price_precision=5size_precision=0(数量按手为单位,整数)。你构造价格:

fromnautilus_trader.modelimportPrice,Quantity price=Price.from_str("1.08500")# 保留 5 位qty=Quantity.from_str("100000")# 最小变动量对齐

一旦你违反精度约束,比如给 5 位精度的价格填入 6 位小数,引擎会直接抛错,而不是悄悄截断。宁可报错,不可静默失真——这条原则贯穿整个引擎。


4. price_precision / size_precision / make_qty

这三个东西的配合,是精度体系落地的核心。先看它们怎么来:

fromnautilus_trader.modelimportInstrumentId,Symbol,Venue,CurrencyPair,Currency,Price,Quantity pair=CurrencyPair(instrument_id=InstrumentId.from_str("EUR/USD.SIM"),raw_symbol=Symbol("EUR/USD"),base_currency=Currency.from_str("EUR"),quote_currency=Currency.from_str("USD"),price_precision=5,# 价格 5 位小数size_precision=0,# 数量整数手ts_event=0,ts_init=0,)

引擎在构造合约时,会根据刚刚构造出的 price_precision / size_precision 自动对齐并设置内部的最小变动量——你不用手动去设 price_increment / size_increment,那是引擎自己算出来的。

price_precision决定价格数值能精确到小数点后几位;size_precision决定数量能精确到几位。

make_qty:让数量"吐个合法的"

真正下单前,必须把数量规整到能被size_increment整除。make_qty就是干这个的:

fromnautilus_trader.modelimportQuantity# size_precision=0 的合约,数量必须是整数q=Quantity.make_qty(25.7)# 自动对齐到整数print(q)# 25

如果传进来25是合法的,但25.7一眼就不合规,make_qty会把它对齐到引擎认定的最小变动单位。这条在你处理"信号算出的小数数量"时尤其重要——信号可能算出 1.733 手,实际能成交的只有整数手,你就得靠make_qty落地。

示意图理清精度链路:

CurrencyPair 定义

price_precision 5 位

size_precision 0 位

Price 定点 5 位小数

Quantity 定点整数

价格校验 符合最小跳动

make_qty 对齐最小变动量

下单价合法

下单量合法

入库成交

一句话总结这条链:Instrument 定义精度 → Price/Quantity 严格落地 → make_qty 兜底对齐 → 保证下单合法。一环断,交易就失真。


5. 一个价格精度错一位的真实事故

这是我当年帮排查过的案例,至今想起来都脊背发凉。

背景:某个回测策略是从数据文件里读价格下单的。数据文件里 EUR/USD 价格是1.0850(4 位小数),而合约price_precision设的是5。有个同学图省事,直接Price(1.0850)裸构造,没走精度校验。

问题出在哪?在浮点加法上。系统拿1.0850当底层双精度做+0.00005的撮合推进,跑了几十万个 tick 之后,累积的浮点尾差把价格推到了1.085050000000001这种带尾巴的数。打印出来看着没事,但一旦拿去算下单金额:

price=1.085000000000001# 脏浮点qty=100000# 10 万单位notional=price*qtyprint(notional)

这一乘,尾差放大十万倍,几厘钱的误差瞬间变成几块、几十块的偏差。更狠的是,还有个完全相反的例子:有人把price_precision设小了,导致下单金额整体缩水/放大一个数量级——原本该下 1 万的,系统按错误精度解析成了 1 千或 10 万,成交瞬间爆仓风险拉满。

这类事故用 float 写出来的代码,光靠肉眼 Unit-test 根本查不出来——因为它平时都是"看起来对"的。教训就一句话:

凡是参与下单价、下单量、成交金额计算的数值,一律走 NautilusTrader 的Price / Quantity / Money,并由 Instrument 的price_precision / size_precision背书,别自己裸用 float。

我已经把这条写进自己项目的project_rules里当红线了。


6. 小结

  • float 算钱,误差会在高频率累加里滚雪球,实盘会出事。
  • Currency定义币种字典,Money把金额和币种绑定。
  • Price/Quantity是定点数,分别受price_precision/size_precision约束。
  • 引擎靠 Instrument 精度自动推导最小变动量;下单前用make_qty对齐数量。
  • 违反精度宁报错不静默截断,“宁可报错,不可失真”。
  • 真实事故提醒:价格精度错一位,下单金额可差十倍,浮点尾差会乘数量放大。

下节预告

有了合约和精度,接下来该上"数据"了。下一节进第 7 章数据模型,我把引擎最常用的四类数据——QuoteTickTradeTickBarOrderBook——一次性讲透,它们的字段、构造、适用场景对比一张表给你。


如果精度这块点醒了你,点赞、收藏、关注三连,下节数据模型篇见。

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

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

立即咨询