如何结合SMA初始值与EWM计算Wilders移动平均版RSI指标?
实现基于Wilders移动平均的RSI(结合SMA初始值与EWM递推)
Wilders RSI的核心逻辑是:用前n期涨跌的算术平均(SMA)作为初始值,之后每一期的平均涨跌用递推公式计算——avg_gain = (prev_avg_gain*(n-1) + current_gain)/n,avg_loss同理。这个递推逻辑和alpha=1/n且adjust=False的EWM完全等价,所以我们可以结合SMA初始化+EWM递推来高效实现,不用低效的循环。
具体步骤与代码
假设你的DataFrame已经包含close列,以14期RSI为例:
import pandas as pd # 1. 计算基础涨跌数据 df['change'] = df['close'].diff() df['gain'] = df['change'].where(df['change'] > 0, 0) # 正涨幅保留,负的设为0 df['loss'] = df['change'].where(df['change'] < 0, 0).abs() # 负跌幅取绝对值,正的设为0 # 2. 计算n期初始SMA平均涨跌 n = 14 df['avg_gain'] = df['gain'].rolling(n).mean() df['avg_loss'] = df['loss'].rolling(n).mean() # 3. 用EWM生成递推值,替换初始值之后的行 # Wilders平滑系数对应alpha=1/n,adjust=False保证递推逻辑和公式一致 ewm_gain = df['gain'].ewm(alpha=1/n, adjust=False).mean() ewm_loss = df['loss'].ewm(alpha=1/n, adjust=False).mean() # 从第n行之后(索引从0开始的话是n位置),用EWM结果覆盖SMA的NaN df.loc[df.index[n:], 'avg_gain'] = ewm_gain.iloc[n:] df.loc[df.index[n:], 'avg_loss'] = ewm_loss.iloc[n:] # 4. 计算RSI,处理avg_loss为0的极端情况(避免除零错误) df['rsi'] = 100 - (100 / (1 + df['avg_gain'] / df['avg_loss'].replace(0, float('inf'))))
为什么这个方法有效?
Wilders的递推公式和无调整的EWM完全匹配:ewm(alpha=1/n, adjust=False)的计算逻辑就是新值 = alpha*当前值 + (1-alpha)*旧值,代入alpha=1/n就是新值 = (当前值 + (n-1)*旧值)/n,和Wilders公式一致。我们先用SMA得到第一个有效平均涨跌值,之后的行直接用EWM结果覆盖,完美实现了标准Wilders RSI的计算逻辑,比循环高效得多。
内容的提问来源于stack exchange,提问作者SebastianHeeg
相关产品推荐
相关产品推荐

