3 分钟快速生成代码
输入想法,AI 即刻生成可运行代码
在金融技术分析中,EMA(Exponential Moving Average,指数移动平均)和EXPMA(Exponential Moving Average,指数平滑移动平均)在纯数学理论上确实是同一个指标。它们的计算核心逻辑都是对历史价格进行指数加权,越近的价格权重越大。
然而,在实际的量化平台(如聚宽 JoinQuant)和不同的炒股软件(如同花顺、通达信)中,调用API得到的值往往不同,甚至与你手动计算的值也不同。这主要由以下四个核心原因导致:
在聚宽的因子库(如技术因子)中,很多指标为了消除量纲、方便截面比较,进行了标准化处理。根据聚宽API文档:
5日指数移动均线 / 今日收盘价10日指数移动均线 / 今日收盘价结论:聚宽因子库直接返回的 EMA 因子往往是一个比值(Ratio),而不是绝对的价格数值。如果你手动计算的是绝对价格(比如 15.5 元),而API返回的是 0.98(表示均线在收盘价下方),两者自然完全不同。
EMA 是一个无限脉冲响应(IIR)滤波器,它的当前值依赖于上一期的值:
EMA(今日) = α * 今日收盘价 + (1 - α) * EMA(昨日)
EMA(昨日) 怎么取?talib、pandas.ewm、通达信)在初始值的设定上存在微小差异,这会导致后续计算结果的偏移。由于 EMA 包含历史所有数据的衰减权重,计算时截取的历史数据长度越长,当前的值越精确。
3 * N 到 5 * N 天的历史数据作为“预热期(Warm-up)”来消除初始值带来的误差。聚宽平台默认使用**前复权(pre-adjusted)**数据。如果你在本地手动计算时,使用的是不复权(真实价格)或者后复权数据,遇到股票分红、送转时,计算出的均线数值会产生巨大差异。
如果你需要获取与传统炒股软件一致的、绝对价格数值的 EMA,建议不要直接调用因子库的标准化因子,而是通过获取历史价格后,使用 talib 或 pandas 自行计算:
import pandas as pd
import talib
def handle_data(context, data):
# 1. 获取过去足够长的数据(例如计算12日EMA,获取60天数据作为预热)
prices = attribute_history('000001.XSHE', 60, '1d', ['close'], df=True)
# 2. 使用 talib 计算标准 EMA(绝对价格)
ema_talib = talib.EMA(prices['close'].values, timeperiod=12)
# 3. 或者使用 pandas 计算(adjust=False 接近通达信算法)
ema_pandas = prices['close'].ewm(span=12, adjust=False).mean()
# 打印最新一天的标准 EMA 值
log.info("TA-Lib EMA: %s", ema_talib[-1])
log.info("Pandas EMA: %s", ema_pandas.iloc[-1])
总结:EXPMA 和 EMA 理论上是同一个东西。你遇到的差异主要是因为聚宽因子库对 EMA 做了除以收盘价的标准化处理,以及初始值/数据长度/复权方式的计算细节不同。使用 talib.EMA 结合足够长的历史前复权数据,即可得到你期望的标准绝对值。