You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Polars中ewm_mean计算EMA遇版本差异问题及优化需求

Polars中EMA指数移动平均计算问题

测试数据

values = [143.15,143.1,143.06,143.01,143.03,143.09,143.14,143.18,143.2,143.2,143.2,143.31,143.38,143.35,143.34,143.25,143.33,143.3,143.33,143.36]

参考正确实现(Pandas+TA-Lib)

使用Pandas结合TA-Lib可得到预期的EMA结果:

import pandas as pd
import talib as ta

df_pan = pd.DataFrame(
    {
        'value': values
    }
)

df_pan['ema_9'] = ta.EMA(df_pan['value'], timeperiod=9)

旧版Polars(0.19.14)的有效代码

在Polars 0.19.14版本中,以下代码计算出的EMA结果与TA-Lib完全一致:

import polars as pl

df_pol = (
    pl.DataFrame(
        {
            'value': values
        }
    )
    .with_columns(
        pl.when(pl.col('value').cum_count() < 9)
        .then(pl.col('value').head(9).mean())
        .otherwise(pl.col('value'))
        .ewm_mean(span=9, min_periods=9, ignore_nulls=True, adjust=False)
        .alias('ema_9')
    )
)

新版Polars(0.20.21)的问题

升级到Polars 0.20.21后,上述代码的计算结果与预期不符。尝试调整ewm_mean的参数,但由于不了解其底层数学原理,未能解决问题。

自定义低效实现

目前已实现一个基于循环的自定义函数,能得到正确结果,但效率极低:

def add_ema_col(df: pl.DataFrame, column: str, periods: int, smoothing:int = 2) -> pl.DataFrame:
    """为OHLCV数据表添加*EMA*列。"""

    values = df.select(column).to_series().to_list()
    ema = [sum(values[:periods]) / periods]

    nones = [None] * (periods - 1)
    
    for price in values[periods:]:
        ema.append((price * (smoothing / (1 + periods))) + ema[-1] * (1 - (smoothing / (1 + periods))))
    
    final_values = pl.Series(nones + ema)

    return (
        df
        .with_columns(
            final_values
        )
    )

df = (
    pl.DataFrame({'Close': values})
    .pipe(lambda df: add_ema_col(df, 'Close', 9))
)

需求

寻求以下两个方向的解决方案:

  • 调整ewm_mean的参数配置,使其计算结果与TA-Lib的EMA一致
  • 将上述自定义循环函数改写为纯Polars表达式,提升计算效率

已提交相关缺陷报告,暂不考虑转回Pandas+TA-Lib的方案。

内容的提问来源于stack exchange,提问作者HapiDaze

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 09:46:20