Py学习  »  Python

三种方法过滤市场噪声:McGinley、KAMA 与 Kalman 滤波器的 Python 实现

数据科学实战 • 7 月前 • 347 次点击  

欢迎加入专注于财经数据与量化投研的【数据科学实战】知识星球!在这里,您将获取持续更新的《财经数据宝典》和《量化投研宝典》,这两部宝典相辅相成,为您在量化投研道路上提供明确指引。 我们提供了精选的国内外量化投研的 250+ 篇高质量文章,并每日更新最新研究成果,涵盖策略开发、因子分析、风险管理等核心领域。 无论您是量化投资新手还是经验丰富的研究者,星球社区都能帮您少走弯路,事半功倍,共同探索数据驱动的投资世界!

引言

金融市场天生充满噪声。每一笔交易、对冲、强制清算、套利和算法再平衡,最终都会压缩成一个叫做"价格"的数字。当我们把这个数字绘制在图表上时,它看起来很精确,但精确并不等于清晰。

如何从嘈杂的价格数据中提取有价值的信号?这正是平滑技术存在的意义。本文将介绍三种主流的自适应平滑方法:McGinley Dynamic(麦金利动态指标)、KAMA(考夫曼自适应移动平均线)和 Kalman Filter(卡尔曼滤波器),并通过 Python 代码带你逐一实现。

核心目标:降噪但不破坏结构

所有平滑技术的存在都是因为原始价格往往难以直接使用。它对所有信息都会做出反应,无论这些信息是否有意义。

"过滤"可以有不同的含义:

  • 有时你想减少滞后
  • 有时你想避免对震荡行情做出反应
  • 有时你想要一个明确考虑不确定性的估计值

McGinley Dynamic 专注于响应速度,KAMA 专注于市场状态感知,Kalman 滤波专注于概率估计。

三种方法详解

McGinley Dynamic:修复滞后问题

McGinley Dynamic 的创建是为了解决传统移动平均线(特别是 EMA)的一个具体问题:固定的平滑参数会导致当价格加速时均线严重滞后,而当价格停滞时又会过度反应。

McGinley 的解决方案简单而实用:不以固定速率平滑价格,而是根据价格相对于均线本身的偏离程度来调整速度。

  • 当价格远离均线时,McGinley 加速跟踪
  • 当价格靠近均线时,McGinley 减速

KAMA:响应需要被"赚取"

KAMA(Kaufman Adaptive Moving Average,考夫曼自适应移动平均线)采用了更具选择性的方法。

KAMA 不是对价格与均线之间的距离做出反应,而是衡量价格移动的效率。它比较一段回溯期内的净方向性移动与总移动量。这个比率决定了均线适应的速度。

  • 当价格持续朝一个方向移动且波动较小时,效率高,KAMA 变得更敏感
  • 当价格来回震荡但没有明确方向时,效率下降,KAMA 大幅减慢

Kalman Filter:估计你无法直接观察的东西

Kalman 滤波与 McGinley 和 KAMA 有本质区别。它不是平滑价格,而是估计一个潜在状态。

核心假设是:观察到的价格是某个更深层次事物的嘈杂测量值。滤波器将对该状态的先验信念与新观察结合起来,根据不确定性对各自进行加权。

这引入了两个大多数指标忽略的概念:

  • 过程噪声:反映状态演变的不确定性
  • 测量噪声:反映观察结果的不确定性

Python 实现

环境准备

import numpy as np
import pandas as pd
import yfinance as yf
import matplotlib.pyplot as plt

McGinley Dynamic 实现

def mcginley_dynamic(price, period=14):
    """
    计算 McGinley Dynamic 指标
    
    参数:
        price: 价格序列(pandas Series)
        period: 周期参数,默认为 14
    
    返回:
        McGinley Dynamic 指标序列
    """

    md = np.zeros(len(price))
    md[0] = price.iloc[0]  # 初始值设为第一个价格
    
    for i in range(1, len(price)):
        # 根据价格偏离程度动态调整平滑速度
        md[i] = md[i-1] + (price.iloc[i] - md[i-1]) / (
            period * (price.iloc[i] / md[i-1])**4
        )
    
    return  pd.Series(md, index=price.index)

KAMA 实现

def kama(price, er_period=10, fast=2, slow=30):
    """
    计算 KAMA(考夫曼自适应移动平均线)
    
    参数:
        price: 价格序列(pandas Series)
        er_period: 效率比率计算周期,默认为 10
        fast: 快速平滑常数周期,默认为 2
        slow: 慢速平滑常数周期,默认为 30
    
    返回:
        KAMA 指标序列
    """

    # 计算净价格变化(方向性移动)
    change = price.diff(er_period).abs()
    # 计算总波动(所有价格变化之和)
    volatility = price.diff().abs().rolling(er_period).sum()
    
    # 效率比率 = 净变化 / 总波动
    er = change / volatility
    er = er.fillna(0.0)
    
    # 计算平滑常数
    fast_sc = 2 / (fast + 1)  # 快速平滑常数
    slow_sc = 2 / (slow + 1)  # 慢速平滑常数
    
    # 根据效率比率在快慢平滑常数之间插值
    sc = (er * (fast_sc - slow_sc) + slow_sc) ** 2
    
    # 计算 KAMA
    kama_values = np.zeros(len(price))
    kama_values[0] = price.iloc[0]
    
    for i in range(1, len(price)):
        kama_values[i] = kama_values[i-1] + sc.iloc[i] * (price.iloc[i] - kama_values[i-1])
    
    return pd.Series(kama_values, index=price.index)

Kalman Filter 实现

def kalman_filter(price, q=1e-5, r=1e-2):
    """
    一维卡尔曼滤波器实现
    
    参数:
        price: 价格序列(pandas Series)
        q: 过程噪声方差,控制状态演变的不确定性
        r: 测量噪声方差,控制观察值的不确定性
    
    返回:
        滤波后的价格估计序列
    """

    x_hat = np.zeros(len(price))  # 状态估计
    p = np.zeros(len(price))       # 估计误差协方差
    
    # 初始化
    x_hat[0] = price.iloc[0]
    p[0] = 1.0
    
    for k in range(1, len(price)):
        # 预测步骤
        x_pred = x_hat[k-1]        # 状态预测
        p_pred = p[k-1] + q         # 协方差预测
        
        # 更新步骤
        k_gain = p_pred / (p_pred + r)  # 卡尔曼增益
        x_hat[k] = x_pred + k_gain * (price.iloc[k] - x_pred)  # 状态更新
        p[k] = (1 - k_gain) * p_pred    # 协方差更新
    
    return pd.Series(x_hat, index=price.index)

传统均线对比

def sma(price, period=50):
    """简单移动平均线"""
    return price.rolling(period).mean()

def ema(price, period=20):
    """指数移动平均线"""
    return price.ewm(span=period, adjust=False).mean()

绑定绘图

# 下载苹果公司 2025 年的股票数据
data = yf.download("AAPL", start="2025-01-01", end="2025-12-31", progress=False)
price = data["Close"]

# 计算各种指标
md = mcginley_dynamic(price)
kama_line = kama(price)
kalman_line = kalman_filter(price)
sma_50 = sma(price, 50)
ema_20 = ema(price, 20)

# 绑制对比图
plt.figure(figsize=(158))
plt.plot(price, label="价格", alpha=0.5)
plt.plot(sma_50, label="SMA 50", linestyle="--")
plt.plot(ema_20, label="EMA 20", linestyle=":")
plt.plot(md, label="McGinley Dynamic", linewidth=2)
plt.plot(kama_line, label="KAMA", linewidth=2)
plt.plot(kalman_line, label="Kalman Filter", linewidth=2)
plt.title("自适应滤波器 vs 传统移动平均线(AAPL 2025)")
plt.legend()
plt.show()

不同市场状态下的表现

强趋势市场

在清晰的趋势中,McGinley 通过减少滞后优于传统移动平均线。KAMA 在这种条件下表现通常更好,高效率使其快速响应同时仍能过滤小幅回撤。Kalman 滤波器调参得当时,能产生平滑的趋势估计且滞后最小。

震荡市场

这是差异变得明显的地方。McGinley 会反复对偏差做出反应,产生频繁的小幅调整。KAMA 在这里表现出色,低效率迫使平滑常数下降,使线条变平,传达了一个重要信息:市场没有提供有意义的方向。

突然的趋势转换

在急剧反转或突破期间,McGinley 会滞后直到价格移动足够远才触发加速。KAMA 只在效率提高后才响应,这意味着它避免了虚假反转但牺牲了早期入场。Kalman 滤波器如果过程噪声设置允许,可以平滑适应。

交易者常忽略的关键洞察

自适应不等于智能:McGinley 和 KAMA 会适应,但它们不会推理。将这些工具当作会思考的实体会导致误用。

平坦的指标也是信息:平坦的 KAMA 或稳定的 Kalman 估计告诉你价格行为缺乏值得行动的结构。忽略这个信息是交易者最常犯的错误之一。

噪声不可避免,误解是可选的

  • McGinley 信任移动
  • KAMA 信任一致性
  • Kalman 信任概率平衡

如何选择

  • 如果你进行主观交易并想要更清晰的趋势而不需要复杂性,McGinley 是一个实用的升级
  • 如果你想要市场状态感知和更少的虚假信号,KAMA 值得关注
  • 如果你构建系统、研究信号或动态管理风险,Kalman 滤波打开了不同级别的控制

总结

从固定移动平均线到自适应平均线再到概率滤波器的演进,反映了市场分析的更广泛转变。首先我们减少了滞后,然后我们尊重市场状态,现在我们承认不确定性。

未来的工具可能会建立在不确定性感知框架之上,无论是通过 Kalman 滤波器、贝叶斯模型,还是在信号旁边估计置信度的混合系统。优势将来自更好的估计。

不要寻找单一的最佳工具,把这些方法看作是不同的透镜,每一个都能帮助你从不同角度理解市场。

参考文章

加入专注于财经数据与量化投研的知识星球【数据科学实战】,获取本文完整研究解析、代码实现细节。

财经数据与量化投研知识社区

核心权益如下:

  1. 赠送《财经数据宝典》完整文档,汇集多年财经数据维护经验
  2. 赠送《量化投研宝典》完整文档,汇集多年量化投研领域经验
  3. 赠送《PyBroker-入门及实战》视频课程,手把手学习量化策略开发
  4. 每日分享高质量量化投研文章(已更新 180+篇)、代码和相关资料
  5. 定期更新高频财经数据
  6. 参与年度不少于 10 次专属直播与录播课程
  7. 与核心开发者直接交流,解决实际问题
  8. 获取专业微信群交流机会和课程折扣

星球已有丰富内容积累,包括量化投研论文、财经高频数据、 PyBroker 视频教程、定期直播、数据分享和答疑解难。适合对量化投研和财经数据分析有兴趣的学习者及从业者。欢迎加入我们!

好文推荐

1. 用 Python 打造股票预测系统:Transformer 模型教程(一)

2. 用 Python 打造股票预测系统:Transformer 模型教程(二)

3. 用 Python 打造股票预测系统:Transformer 模型教程(三)

4. 用 Python 打造股票预测系统:Transformer 模型教程(完结)

5. 揭秘隐马尔可夫模型:因子投资的制胜武器

6. YOLO 也能预测股市涨跌?计算机视觉在股票市场预测中的应用

7. 金融 AI 助手:FinGPT 让你轻松掌握市场分析

8. 量化交易秘籍:为什么专业交易员都在用对数收益率?

9. Python 量化投资利器:Ridge、Lasso 和 Elastic Net 回归详解

10. 掌握金融波动率模型:完整 Python 实现指南

好书推荐



Python社区是高质量的Python/Django开发社区
本文地址:http://www.python88.com/topic/192166