当前位置:首页>python>用 Python 玩转自适应均线:MAMA/FAMA 跨资产择时实战

用 Python 玩转自适应均线:MAMA/FAMA 跨资产择时实战

  • 2026-10-11 05:46:57
用 Python 玩转自适应均线:MAMA/FAMA 跨资产择时实战

用 Python 揭秘均值回归策略:你的收益从何而来?

2026年重磅升级已全面落地!欢迎加入专注财经数据与量化投研的【数据科学实战】知识星球!您将获取持续更新的《财经数据宝典》与《量化投研宝典》,双典协同提供系统化指引;星球内含 500 篇以上独有高质量文章,深度覆盖策略开发、因子分析、风险管理等核心领域,内容基本每日更新;同步推出的「量化因子专题教程」系列(含完整可运行代码与实战案例),系统详解因子构建、回测与优化全流程,并实现日更迭代。我们持续扩充独家内容资源,全方位赋能您的投研效率与专业成长。无论您是量化新手还是资深研究者,这里都是助您少走弯路、事半功倍的理想伙伴,携手共探数据驱动的投资未来!

引言

很多刚接触量化交易的朋友,第一个学会的指标往往是 SMA(简单移动平均)或 EMA(指数移动平均)。它们简单好用,但有一个共同的「硬伤」:平滑周期是固定的。市场在快速趋势和横盘震荡之间反复切换时,固定周期的均线要么反应太慢错过行情,要么太敏感产生大量假信号(俗称「打脸」或 whipsaw)。

有没有一种均线能「自己看情况」调整快慢?答案是肯定的——它就是 John Ehlers 提出的 MESA 自适应移动平均线(MAMA,MESA Adaptive Moving Average)。

本文带你完整走一遍:用 Python 构建 MAMA/FAMA 交叉策略,跨股票、债券、商品、加密货币五类资产做回测,再用贝叶斯优化自动调参,最后客观评估它到底能不能跑赢「买入并持有」。结论可能和你想的不太一样。


一、MAMA 到底聪明在哪?

普通均线假设价格是「随机但可平滑」的;而 Ehlers 的思路不同——他把价格看作「带有可变周期的部分周期信号」。

MAMA 的核心做法是:先估计市场当前的主导周期,再据此动态调整平滑速度——快市场里反应更快,慢市场里更平滑。

在量化实践中,MAMA 通常会搭配一条更慢的伴随线 FAMA(Following Adaptive Moving Average)一起使用。最经典的信号规则是:

  • • MAMA 上穿 FAMA → 偏多(看涨)
  • • MAMA 下穿 FAMA → 偏空(看跌)

需要提醒的是:MAMA/FAMA 的设计初衷就是「比传统均线更少打脸」,但没有任何交叉系统能完全消除假信号。所以选对标的同样关键。

补充:为什么要选这几类资产?

文中精心挑选了 5 个标的,各有用意(这也是新手容易忽略的一步):

  • • SPY(标普 500 ETF):流动性极佳、买卖价差小,价格比单只个股平滑,假信号更少。
  • • TLT / IEF(长 / 中期美债 ETF):与股票走势不同,能提供分散化和宏观「体温计」。一般 IEF 假信号更少,TLT 趋势幅度更大。
  • • WTI(原油):与全球经济、通胀、地缘政治强相关,趋势往往强且持久。
  • • BTC-USD(比特币):7×24 小时交易,频繁在趋势与震荡间切换,恰好契合 MAMA 的自适应特性。

二、希尔伯特变换:MAMA 的「发动机」

MAMA 之所以能感知周期,靠的是希尔伯特变换(Hilbert Transform)——一种数字信号处理(DSP)方法,它能把信号做 90 度相位偏移。

简单理解流程是这样的:

价格 → 希尔伯特变换 → 同相分量(I) + 正交分量(Q) → 瞬时相位 → 自适应 Alpha → MAMA/FAMA

有了 I 和 Q 两个分量,就能算出瞬时相位:

而对 MAMA 真正重要的,不是相位本身,而是相位变化率:

  • •  大 → 市场走势果断(快周期)
  • •  小 → 市场盘整、震荡(慢周期)

MAMA 再把相位变化转换成自适应平滑系数 ,并限制在 (通常为 )区间内。 越大,均线反应越快;越小则越平滑。

一句话总结:希尔伯特变换负责「测出市场处于哪个周期」,MAMA 据此动态切换快慢。


三、五步搭建完整策略

下面按照「数据 → 信号 → 回测 → 优化 → 评估」五步走,并附带可运行的核心代码。

第 1 步:加载历史数据

import requests
import
 pandas as pd

API_KEY = "你的 API KEY"
START_DATE = "2015-01-02"
END_DATE = "2026-05-27"

# 数据加载函数:拉取日线 OHLCV 数据

def
 get_data(symbol):
    url = f"https://example-data-api.com/api/eod/{symbol}"
    params = {
        "api_token"
: API_KEY,
        "period"
: "d",        # 日线
        "from"
: START_DATE,
        "to"
: END_DATE,
        "fmt"
: "json"
    }
    r = requests.get(url, params=params)
    r.raise_for_status()      # 出错时抛异常,方便调试
    df = pd.DataFrame(r.json())
    df["date"] = pd.to_datetime(df["date"])
    df = df.set_index("date").sort_index()  # 以日期为索引并排序
    return
 df

spy = get_data("SPY")  # 拉取标普 500 ETF 数据

第 2 步:构建 MAMA/FAMA 信号

这里直接用 TA-Lib 计算 MAMA 与 FAMA,并衍生出价差、斜率、波动率等特征。

import numpy as np
import
 pandas as pd
import
 talib

# 计算 MAMA 与 FAMA 两条自适应均线

def
 mama(series, fast=0.5, slow=0.05):
    mama_line, fama_line = talib.MAMA(
        series.values,
        fastlimit=fast,   # 快速上限
        slowlimit=slow    # 慢速下限
    )
    return
 pd.DataFrame(
        {"mama": mama_line, "fama": fama_line},
        index=series.index
    )

def
 build_strategy(df, fast, slow, slope_window, vol_filter):
    df = df.copy()
    ma = mama(df["price"], fast=fast, slow=slow)
    df["mama"] = ma["mama"]
    df["fama"] = ma["fama"]

    # 价差:MAMA 与 FAMA 的相对差距(衡量趋势强度)

    df["spread"] = (df["mama"] - df["fama"]) / df["price"]
    # 斜率:MAMA 的变化(衡量动量方向)

    df["slope"] = df["mama"].diff(slope_window) / df["price"]
    # 波动率:20 日收益率滚动标准差(用于过滤高波动环境)

    df["vol"] = df["price"].pct_change().rolling(20).std()

    # 趋势强度评分:价差与斜率加权

    strength = 5 * df["spread"] + 20 * df["slope"]

    # 仓位引擎:趋势向上且波动可控时满仓,否则降低仓位

    position = np.where((strength > 0) & (df["vol"] < vol_filter), 1.0, 0.25)
    # 强下跌趋势中清空仓位以规避风险

    position = np.where(strength < 0, 0.0, position)

    df["position"] = position
    return
 df

第 3 步:风险调整后的回测引擎

def backtest(df, initial=10000):
    df = df.copy()
    df["ret"] = df["price"].pct_change().fillna(0)  # 标的日收益
    # 用前一日仓位乘以当日收益(避免未来函数)

    df["strategy_ret"] = df["position"].shift(1).fillna(0) * df["ret"]

    # 交易成本:以换手率 × 万分之五计费

    turnover = df["position"].diff().abs().fillna(0)
    df["strategy_ret"] -= turnover * 0.0005

    # 构建权益曲线

    df["equity"] = (1 + df["strategy_ret"]).cumprod() * initial
    df["bh_equity"] = (1 + df["ret"]).cumprod() * initial  # 买入并持有基准

    # 夏普比率(年化)

    sharpe = (df["strategy_ret"].mean() / df["strategy_ret"].std()) * np.sqrt(252)

    strategy_return = df["equity"].iloc[-1] / initial - 1
    bh_return = df["bh_equity"].iloc[-1] / initial - 1
    alpha = strategy_return - bh_return  # 相对基准的超额收益

    # 最大回撤

    peak = df["equity"].cummax()
    max_dd = ((df["equity"] - peak) / peak).min()

    return
 {
        "sharpe"
: sharpe, "return": strategy_return,
        "alpha"
: alpha, "drawdown": max_dd
    }, df

小贴士:position.shift(1) 这一步非常关键。用「前一日仓位」结算「今日收益」,可以避免「今天才知道信号、却假装昨天就建好仓」的未来函数陷阱,这是新手最常犯的回测错误之一。

第 4 步:用 Optuna 做贝叶斯优化

为什么不用网格搜索(Grid Search)?因为交易系统的参数效应往往是非线性的、存在突变和不稳定区域。贝叶斯优化能「从历史试验中学习」,把更多精力放在表现好的参数区域,收敛更快。

import optuna

def
 objective(trial):
    # 让优化器在给定范围内自动取值

    fast = trial.suggest_float("fast", 0.05, 0.95)
    slow = trial.suggest_float("slow", 0.01, 0.5)
    slope_window = trial.suggest_int("slope_window", 2, 10)
    vol_filter = trial.suggest_float("vol_filter", 0.005, 0.05)

    if
 slow >= fast:        # 约束:慢线必须慢于快线
        return
 -999

    df = build_strategy(df_base, fast, slow, slope_window, vol_filter)
    metrics, _ = backtest(df)

    sharpe = metrics["sharpe"]
    alpha = metrics["alpha"]
    dd = abs(metrics["drawdown"])

    # 目标函数:重奖夏普,奖励超额收益,惩罚回撤

    score = sharpe * 4 + alpha * 2 - dd
    if
 sharpe < 1:          # 夏普低于 1 的策略强力扣分
        score -= 100
    return
 score

# 运行优化,最大化得分

study = optuna.create_study(direction="maximize")
study.optimize(objective, n_trials=300)
print
(study.best_params)    # 输出最优参数组合

第 5 步:最终评估

用最优参数重新回测,对比策略与买入并持有的权益曲线、回撤、滚动夏普、月度收益热力图等。


四、回测结果:它真的赚钱吗?

这是全文最有价值的部分。我们看几个代表性资产的「策略 vs 买入并持有」对比。

SPY(标普 500)

指标
策略
买入并持有
总收益
3.12 倍
3.65 倍
夏普比率
1.09
0.73
最大回撤
-12.8%
-34.1%
年化波动率
9.65%
17.73%

可以看到:策略总收益略输大盘,但夏普更高、回撤几乎砍半、波动率大幅下降。换句话说——它用更小的风险,拿到了接近的收益。

TLT(长期美债)

测试期内恰逢历史级别的债券熊市,买入并持有总收益约 -33%。而策略通过大量时间持币观望(平均仓位仅 26.5%),把回撤从 -51.8% 压到 -11.5%。但代价是年化仅 0.31%,几乎等同于「现金替代品」,夏普接近 0。这也暴露了一个隐患:贝叶斯优化可能「学会了躲避风险」而非「捕捉收益」,存在过拟合嫌疑。

WTI(原油)与 BTC(比特币)

  • • WTI:把恐怖的 -149% 回撤压到 -53.7%,波动率从 108.8% 降到 18.7%(约 6 倍),夏普由 -0.16 转正为 0.36。
  • • BTC:收益与买入并持有几乎持平(CAGR 约 8.6% vs 8.8%),但回撤从 -81% 降到 -24%,夏普从 0.43 提升到 0.62。

一个共同的「警示信号」

几乎所有资产上,策略的胜率都偏低(25%35%),盈利因子(Profit Factor)多在 1.021.18 之间。这说明它是典型的「趋势型系统」——靠少数几段大行情赚钱,大部分时间在小亏或持平。盈利因子越接近 1,统计优势越弱,这一点务必警惕。


五、总结

读完整个研究,最重要的认知是:

  1. 1. MAMA 不是「躺赢神器」。在 SPY、BTC、TLT、IEF、WTI 上,它都没能在「原始总收益」上稳定跑赢买入并持有。
  2. 2. 但它是一流的「风险管理外挂」。几乎在每个资产上,它都显著降低了波动率和最大回撤,提升了夏普、索提诺、卡玛等风险调整后指标。
  3. 3. 正确定位:与其把 MAMA 当成「能替代股票的 alpha 引擎」,不如把它理解为一个「跨资产风险管理叠加层」——用部分上涨参与度,换取更平滑的资金曲线和更强的下行保护。
  4. 4. 务必警惕过拟合。文中多次提到,参数是在历史数据上优化得到的,下一步应做严格的「向前滚动验证」(Walk-Forward Validation),并与现金基准对比,才能判断优势是真实存在还是「事后诸葛亮」。

对学习 Python 量化的朋友来说,这个项目最大的价值,不在于「找到一个赚钱策略」,而在于完整跑通了一条工程化流水线:数据获取 → 信号构建 → 严谨回测 → 自动调参 → 客观评估。把这条链路吃透,比记住任何一个指标都更重要。

如果你想继续深入,可以尝试把 MAMA 与传统均线(SMA、EMA)、快速响应均线(HMA、DEMA、ZLEMA)、其他自适应均线(KAMA、FRAMA)做横向对比,在滞后性、抗噪性、周期适应性三个维度上评估高下。


参考文章

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

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

2026年全面升级已落地!【数据科学实战】知识星球核心权益如下:

  1. 1. 双典系统赋能:获赠《财经数据宝典》与《量化投研宝典》完整文档,凝练多年实战经验,构建系统化知识框架;
  2. 2. 量化因子日更教程(2026重磅新增):每日更新「量化因子专题教程」,配套完整可运行代码与实战案例,深度拆解因子构建、回测与优化全流程;
  3. 3. 量化文章专题教程库:500+篇星球独有高质量教程式文章,系统覆盖策略开发、因子研究、风险管理等核心领域,内容基本每日更新,并配套精选学习资料与实战参考;
  4. 4. 量化投研实战课程:赠送《AKQuant-入门及实战》《PyBroker-入门及实战》视频课程,手把手教学,快速掌握量化策略开发技能;
  5. 5. 财经数据支持:定期更新国内外财经数据,为策略研发提供精准、可靠的数据基础;
  6. 6. 顶尖学者与行业专家分享:年度邀请学术界博士与业界资深专家开展前沿论文精讲与实战案例分享,不少于4场,直击研究前沿与产业实践;
    专家直连答疑:与核心开发者及领域专家实时互动,高效解决投研实战难题;
  7. 7. 专业社群与专属福利:加入高质量交流社群,获取课程折扣及更多独家资源。

星球已沉淀丰富内容生态——涵盖量化文章专题教程库、因子日更系列、高频数据集、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 实现指南

好书推荐

最新文章

随机文章