第 2 章 · 02 指数加权 EMA


文档摘要

第 2 章 · 02 指数加权 EMA 本节摘要:本节讲 的第一个改进版—— 。它保留「外推过去」的直觉,但把等权平均换成指数加权移动平均(EWMA):近期收益权重大、远期收益权重按指数衰减。这更符合「一只股票最近三个月的表现,比十年前的表现更能预示未来」的常识。本节拆解它在 里的实现: 参数如何控制衰减速度、几何与算术两种年化模式、与等权均值的对比,以及作者对「该用大 span 还是小 span」的实务建议——默认 500,如果调仓更频繁可适当调小,但极限趋向等权均值。 内容来源:原项目源码 (函数 )、文档 ,汉化并套用体系化模板。 学习目标 阅读完本节,你应当能够: 说清 指数加权 为何比等权平均更贴合近期。 解释 span 参数的数学含义与衰减系数 α 的关系。

第 2 章 · 02 指数加权 EMA

本节摘要:本节讲 mean_historical_return 的第一个改进版——ema_historical_return。它保留「外推过去」的直觉,但把等权平均换成指数加权移动平均(EWMA):近期收益权重大、远期收益权重按指数衰减。这更符合「一只股票最近三个月的表现,比十年前的表现更能预示未来」的常识。本节拆解它在 expected_returns.py 里的实现:span 参数如何控制衰减速度、几何与算术两种年化模式、与等权均值的对比,以及作者对「该用大 span 还是小 span」的实务建议——默认 500,如果调仓更频繁可适当调小,但极限趋向等权均值。

内容来源:原项目源码 pypfopt/expected_returns.py(函数 ema_historical_return)、文档 docs/ExpectedReturns.rst,汉化并套用体系化模板。

学习目标

阅读完本节,你应当能够:

  1. 说清 指数加权 为何比等权平均更贴合近期。
  2. 解释 span 参数的数学含义与衰减系数 α 的关系。
  3. ema_historical_return 计算年化期望收益。
  4. 根据调仓频率选择合适的 span。
  5. 复述作者对 EMA 的实务建议与局限。

一、为什么要指数加权

上一节的 mean_historical_return 把所有历史数据等权对待——2010 年的某天收益和昨天的收益权重一样。这与金融常识相悖:公司的业务、行业格局、宏观环境都在变,近期数据比远期数据更代表「现在这只资产」

指数加权移动平均(EWMA)给每期收益一个随时间指数衰减的权重:

r̂_t = α r_t + (1 - α) r̂_{t-1}

其中 α 是平滑系数(0 < α ≤ 1)。展开看,每期收益的权重是 (1-α)^k(k 是距今的期数)——距今越远,权重越小,且按指数衰减。

二、span 与衰减系数

ema_historical_return 用 pandas 的 ewm(span=...) 实现,它把平滑系数 α 与更直观的 span 关联起来:

α = 2 / (span + 1)
  • span 越大,α 越小,衰减越慢,平均窗口越长——趋向等权均值
  • span 越小,α 越大,衰减越快,只看最近几期——响应更快但更噪
span α 大致等效窗口 行为
500(默认) 0.004 最近约 2 年 平滑,接近等权均值
180 0.011 最近约 9 个月 中等响应
30 0.065 最近 1~2 个月 快速响应,较噪

💡 pandas 的 span 语义:在 pandas 里,ewm(span=N).mean() 给出的是「N 期加权移动平均」,其中最近一期的权重最大、向前指数衰减。这与「N 日简单移动平均」不同——SMA 是硬截断窗口,EWMA 是无限长但权重衰减的窗口。

三、源码逐行解析

打开 pypfopt/expected_returns.py,定位 ema_historical_return(源码 174-223 行):

def ema_historical_return( prices, returns_data=False, compounding=True, span=500, frequency=252, log_returns=False, ): if not isinstance(prices, pd.DataFrame): warnings.warn("prices are not in a dataframe", RuntimeWarning) prices = pd.DataFrame(prices) if returns_data: returns = prices else: returns = returns_from_prices(prices, log_returns) _check_returns(returns) if compounding: return (1 + returns.ewm(span=span).mean().iloc[-1]) ** frequency - 1 else: return returns.ewm(span=span).mean().iloc[-1] * frequency

关键点:

  1. 类型保护 + 收益转换:与 mean_historical_return 完全一致,保证两个函数接口统一。
  2. returns.ewm(span=span).mean():对每只资产的日度收益序列算 EWMA,返回一个与原 DataFrame 同形状的对象。
  3. .iloc[-1]:只取最后一期的 EWMA 值——因为 EWMA 是递推公式,最后一期已经包含了所有历史的指数加权信息。
  4. 两种年化模式(关键):
    • 几何模式(compounding=True,默认):(1 + ewma_T)^frequency - 1,即把最后一期 EWMA 当成「日度等价复合收益率」,年化成 CAGR。
    • 算术模式(compounding=False):ewma_T × frequency,直接乘 252。

⚠️ 几何模式的语义:这里 (1 + ewma_T)^frequency - 1 是把「最近一期的指数加权日度收益」当成日度复利基础,再年化。它不是真正的 CAGR(那要对所有历史收益做几何平均),而是「以当前 EWMA 为代表的年化收益」。数值上对近期趋势更敏感。

四、与等权均值的对比

同一份数据,等权均值与 EMA 的差异:

from pypfopt import expected_returns mu_mean = expected_returns.mean_historical_return(df) mu_ema = expected_returns.ema_historical_return(df, span=500) mu_ema_fast = expected_returns.ema_historical_return(df, span=60)

经验上:

  • 平稳期(市场无明确趋势):三者数值接近。
  • 趋势期(某资产最近大涨/大跌):span=60 的 EMA 偏离均值最远,span=500 次之,等权均值最稳。
  • 数据短(少于 span):EWMA 退化为等权——pandas 自动用可用数据。

💡 选 span 的经验:作者在文档里说,默认 500 偏保守;若你调仓更频繁(比如月度或周度),有理由调小 span 以捕捉近期趋势。但 span 太小会让 μ 在市场短期波动里剧烈跳变,反而增加换手与噪声。一般 span ∈ [60, 500] 是合理区间,先用 180 试。

五、用法示例

默认调用(span=500):

mu = expected_returns.ema_historical_return(df)

快速响应版本(span=60):

mu = expected_returns.ema_historical_return(df, span=60)

直接喂优化器:

from pypfopt import EfficientFrontier, risk_models mu = expected_returns.ema_historical_return(df, span=180) S = risk_models.sample_cov(df) ef = EfficientFrontier(mu, S) ef.max_sharpe()

通过统一入口:

expected_returns.return_model(df, method="ema_historical_return", span=180)

六、局限与作者建议

EMA 改进了「对近期不敏感」的问题,但没有解决「外推过去」的根本局限:

  1. 仍是历史外推:不管怎么加权,本质还是「过去的收益代表未来」。若资产基本面发生结构性变化(如并购、转型),历史收益完全失效。
  2. span 难调:太大会退化为等权均值,太小会噪声爆炸;且不同资产可能需要不同 span,统一一个值是粗糙的。
  3. 仍被优化器放大:与等权均值一样,错误的 EMA 在 max_sharpe 里会被最大化成错误权重。

docs/ExpectedReturns.rst 给出的官方建议:

指数移动平均是对均值历史收益的简单改进;它给近期收益更高权重,以提高估计的时效性。一般我会倾向于更高的 span——在极限下它趋向均值历史收益。然而,如果你打算更频繁地调仓,有理由降低 span 以捕捉近期趋势。

💡 何时用 EMA:如果你坚持用历史收益(而非 Black-Litterman 或因子模型),且数据足够长(至少几年),EMA(span ∈ [180, 500])通常比等权均值更合理——它至少承认「最近比久远更重要」。但请把它与一个稳健的风险模型(如 Ledoit-Wolf 收缩)搭配,以减少 μ 错误的放大效应。

本节要点回顾

  1. 直觉:对历史收益做指数加权移动平均,近期权重大、远期权重按指数衰减。
  2. span 与 α:α = 2/(span+1);span 越大越平滑(趋向等权),越小越响应(但更噪)。
  3. 两种年化:compounding=True 几何((1+ewma_T)^freq - 1,默认),False 算术(ewma_T × freq)。
  4. .iloc[-1]:EWMA 是递推式,最后一期已包含所有历史的指数加权信息。
  5. 默认 span=500:偏保守;调仓更频繁可调小,但别太极端。
  6. 根本局限未解:仍是历史外推,被优化器放大;比等权均值好但仍不如 CAPM 或 Black-Litterman。

下一节,我们看 CAPM——一个理论根基最稳、依赖市场 beta 与风险溢价的收益模型。


发布者: 作者: 灏天文库 转发
评论区 (0)
U