Fisher 变换是如何计算的?
Fisher 变换是什么(以及为什么公式看起来不同)
Fisher 变换是一种数学变换,旨在将时间序列(通常是价格序列)转换为更像无界振荡器的形式。它被称为“变换”,是因为它使用非线性函数重新映射数值,而不是因为它执行统计预测。
在实际应用中,其核心思想是:
- 使用滚动的高/低范围将输入序列压缩为有界值,
- 应用 Fisher 风格的非线性映射(与对数比率相关),
- 通过递归更新映射值,使指标平滑响应,而非纯粹“逐点”变化。
由于映射是非线性的,且范围是在一个窗口内计算的,因此最终输出的尺度和敏感度强烈依赖于你选择的设置以及输入数据的特性。
核心计算:公式、参数和输入
一种广泛使用的 Fisher 变换计算遵循以下通用结构。不同来源的具体实现细节可能略有差异,但以下机制涵盖了其核心组成部分。
参数和输入
你需要:
- 输入序列:通常是一个衍生的价格值(例如,中间价),在每个时间步提供。
- 回看窗口长度 (N):用于计算滚动最小值和最大值的K线数量。
- 递归/迭代:Fisher 映射使用递归更新,引用先前计算的值。
步骤 1:计算滚动归一化值
对于每个时间步 t(仅在有足够的数据用于回看后开始),计算过去 N 个步骤中输入序列的滚动最小值和最大值:
- 最低值(t) = 窗口内输入的最小值
- 最高值(t) = 窗口内输入的最大值
然后计算一个归一化位置,通常形式为:
- x(t) = 2 × ((\frac{Input(t) - 最低值(t)}{最高值(t) - 最低值(t)})) − 1
这将当前输入映射为一个有界值(概念上在 −1 到 +1 之间),基于其在近期最小/最大范围内的位置。
计算示例的假设:你必须明确定义“Input(t)”是什么,并在复现数值时始终使用相同的 N 和相同的窗口定义(是否包含当前K线)。
步骤 2:应用 Fisher 风格的非线性映射
计算一个中间值,使用对数比率变换将有界归一化值映射到 Fisher 类域。常见模式为:
- f(t) = 0.5 × ln((\frac{1 + x(t)}{1 - x(t)}))
为避免当 x(t) 接近 ±1 时出现奇点(除零或对数为零),实现中通常包含保护机制,例如将 x(t) 限制在略小的区间内(例如,防止恰好等于 −1 和 +1)。
步骤 3:递归更新(通过先前值平滑)
许多 Fisher 变换公式使用先前输出值更新映射值。典型的递归结构为:
- fish(t) = fish(t−1) + f(t)
有时还会引入额外的平滑因子或中间“前值”变量。具体的递归形式决定了指标的响应速度。
步骤 4:可选的舍入或缩放
某些实现会对最终序列进行重新缩放或舍入以提高可读性。这些是显示选择,而非核心数学概念。
可独立验证的示例流程
由于此处不假设实时市场数据,学习该计算最可靠的方法是在一个小的假设数据集上复现它。
示例设置(先定义假设)
- 选择 N = 5。
- 为每个时间步选择 Input(t)(例如,一个中间价序列),并提供数值。
- 决定如何处理前 N 个点(通常仅在窗口完整后才开始生成输出)。
- 决定当范围过小时如何限制 x(t)。
逐步计算中间值
对于每个存在窗口的时间步:
- 从最近 N 个输入值中找出 最低值(t) 和 最高值(t)。
- 使用 (2 × ((Input−最低值)/(最高值−最低值)) − 1) 计算 x(t)。
- 保护 x(t),使其不恰好达到 ±1。
- 计算 f(t) = 0.5 × ln((1 + x)/(1 − x))。
- 使用选定的递归方式更新 fish(t),例如 fish(t) = fish(t−1) + f(t)(其中 fish(t−1) 按你选择的约定初始化)。
如何检查你是否正确实现了它
当你使用相同假设实现相同步骤时,应能匹配:
- 滚动最小/最大值,
- 中间 x(t) 序列,
- Fisher 映射 f(t),
- 以及递归 fish(t) 序列。
如果任何一个中间序列不同,最终输出也会不同。因此,验证的重点应放在复现中间计算上,而不仅仅是最终结果。
局限性和失效模式(什么会导致计算失败)
尽管 Fisher 变换是一个定义明确的公式,其计算输出可能因实现细节和数据行为的不同而大相径庭。
1) 回看窗口中的小范围或平坦范围
如果 最高值(t) − 最低值(t) 变得非常小,归一化 ((Input−最低值)/(最高值−最低值)) 将变得不稳定。这可能导致 x(t) 突然跳向 ±1,从而推动对数映射趋向极端值。
实际影响:你必须为接近零的范围定义保护机制(例如,跳过更新或限制计算比率)。
2) 对数比率变换中的奇点
映射 (ln((1+x)/(1−x))) 在 x = 1 或 x = −1 时无定义。实际数据和舍入仍可能产生非常接近这些边界的值。
实际影响:实现中通常将 x(t) 略微限制在 (−1, +1) 内,以避免无穷大值。
3) 递归初始化和不一致的约定
由于计算通常使用先前输出,初始 fish(0)(或第一个计算的 fish 值)的选择会影响后续值。
实际影响:两个使用相同公式但不同初始约定的实现可能会发散。
4) 输入定义改变一切
如果“Input(t)”是不同的价格度量(收盘价 vs. 中间价 vs. 加权价格),滚动最小/最大值会变化,因此 x(t) 和 Fisher 输出也会变化。
实际影响:你必须将输入序列定义视为计算的一部分,而非外部细节。
5) 数据质量问题
缺失K线、不规则时间戳和重采样数据可能改变滚动最小/最大值窗口。即使没有任何“市场预测”,这些计算机制也可能扭曲指标线。