3. 量化基础
在金融模型量化与精度性能权衡的实践中,第一步不是选框架,也不是调参,而是理解“数在计算机里到底怎么存”。很多看似正确的定价、风控与回测结果,偏差并非来自模型逻辑,而是来自数值表示本身。本节从浮点与定点两种基本表示出发,梳理量化误差的来源,并落到金融计算中哪些环节对精度最敏感。
一、核心原理:浮点表示与定点表示的本质差异
计算机无法精确表示所有实数。IEEE 754 浮点数用“符号位 + 指数位 + 尾数位”表示一个数,其形式为 (-1)^s × 1.m × 2^e。以常见的 FP32 为例:1 位符号、8 位指数、23 位尾数;FP64 则是 1 位符号、11 位指数、52 位尾数。尾数决定有效数字位数,指数决定可表示范围。这意味着浮点数的“绝对精度”随数值大小变化:数值越大,相邻可表示数之间的间隔越大。
定点数则相反,它固定小数点的位置,用整数存储并按比例缩放。例如用 64 位整数表示“以 0.0001 元为单位”的价格,则 12345678 实际代表 1234.5678 元。定点数的绝对精度恒定,但可表示范围有限,且需要人为管理缩放因子与溢出。
二、量化误差的四大来源
量化误差不是单一现象,而是多种机制叠加的结果。理解来源,才能在模型设计时对症下药。
- 表示误差(Representation Error):十进制小数如 0.1、0.2 在二进制浮点中无法精确表示,只能近似。0.1 的 FP64 实际值约为 0.10000000000000000555。
- 舍入误差(Rounding Error):每次运算结果都要舍入到最近的可表示数,误差随运算次数累积。累加一万次微小误差,可能放大到不可忽略。
- 截断误差(Truncation Error):量化到低精度格式(如 FP32、FP16、INT8)时,尾数位减少,直接丢弃低位信息。
- 灾难性抵消(Catastrophic Cancellation):两个相近的大数相减,有效数字大量丢失。例如 1.0000001 - 1.0000000 在低精度下可能直接得到 0。
三、金融计算中的精度敏感性场景
并非所有金融计算都对精度同等敏感。下表梳理了典型场景的敏感度与推荐策略。
| 场景 | 精度敏感度 | 主要风险 | 推荐策略 |
|---|---|---|---|
| 账户余额、清算金额 | 极高 | 分位误差导致对账不平 | 定点/十进制,禁用二进制浮点 |
| 期权定价(BSM、蒙特卡洛) | 高 | 希腊值偏差、路径依赖累积 | FP64 为主,关键路径可混合精度 |
| 协方差矩阵求逆 | 极高 | 条件数大时结果完全失真 | FP64 + 正则化,避免 FP32 |
| 回测收益率累乘 | 中高 | 长期复利误差累积 | FP64,定期校准基准 |
| 特征工程、因子标准化 | 中 | 排序稳定性、阈值抖动 | FP32 可接受,注意比较容差 |
| 深度学习推理打分 | 中低 | 排序微变,通常不影响决策 | FP16/INT8 量化,需校准 |
四、案例与复盘:一次回测收益偏差的定位
某团队用 FP32 实现日频回测,策略逻辑正确,但三年累计收益比 FP64 基准高出约 0.7%。排查发现:每日收益率在 FP32 下累乘,单日误差约 1e-7,三年约 750 个交易日,误差在复利下被放大;同时部分收益率接近 0 时发生灾难性抵消,符号判断出现抖动。
# 误差复现示意(Python)
import numpy as np
r = np.float32(0.000123456)
acc32 = np.float32(1.0)
acc64 = np.float64(1.0)
for _ in range(750):
acc32 *= (1 + r)
acc64 *= (1 + r)
print("FP32 累计:", acc32)
print("FP64 累计:", acc64)
print("相对偏差:", abs(acc32 - acc64) / acc64)
# 输出示例:相对偏差约 1e-5 ~ 1e-4 量级,长期复利下不可忽略
复盘结论有三点:其一,涉及资金曲线累乘的核心链路必须用 FP64 或更高精度;其二,比较浮点数时应使用容差而非等号;其三,量化到低精度前,必须做误差传播评估,而不是只看单步误差。
掌握数值表示与误差来源,是后续所有量化与性能权衡决策的基础。只有先明确“哪些数不能动、哪些数可以压”,才能在精度与性能之间做出有依据的取舍。