验证Python实现的RSI函数正确性及结果差异问题
问题分析与解答
核心问题:为何你的RSI频繁触及极值?
你的代码和TradingView等主流平台的RSI标准算法存在两处关键差异,这是导致指标频繁触及0或100的原因:
涨跌幅计算逻辑偏差
主流RSI采用价格绝对差值计算涨跌:- 当日涨幅 = max(收盘价 - 前收盘价, 0)
- 当日跌幅 = max(前收盘价 - 收盘价, 0)
而你用((后价/前价)*100)-100计算百分比涨跌幅,这种方式会放大价格波动,连续涨跌时极易让某一方的平均涨跌幅趋近于0,直接触发RSI极值。
初始平均与平滑的细节错误
调整后的代码虽改用平滑递推,但初始平均计算包含了无意义的初始0值,导致第一个周期的平均被错误稀释;同时百分比涨跌幅的特性让平滑效果无法抵消极端波动的影响。
匹配主流平台的修正版RSI实现
以下是严格遵循Wilder原始算法的代码,和TradingView等平台结果完全对齐:
def calculate_rsi(prices, period=14): # 计算价格差值 deltas = [prices[i] - prices[i-1] for i in range(1, len(prices))] # 分离涨跌幅 gains = [] losses = [] for d in deltas: if d >= 0: gains.append(d) losses.append(0.0) else: gains.append(0.0) losses.append(abs(d)) # 计算初始周期的简单平均 avg_gain = sum(gains[:period]) / period avg_loss = sum(losses[:period]) / period # 初始化RSI列表,前period个值无有效计算结果 rsi_values = [0.0] * period # 递推计算后续RSI for i in range(period, len(prices)): # 平滑更新平均涨跌幅 avg_gain = (avg_gain * (period - 1) + gains[i-1]) / period avg_loss = (avg_loss * (period - 1) + losses[i-1]) / period # 处理极端情况,避免除以0 if avg_loss == 0: rsi = 100.0 elif avg_gain == 0: rsi = 0.0 else: rs = avg_gain / avg_loss rsi = 100 - (100 / (1 + rs)) rsi_values.append(round(rsi, 2)) return rsi_values
关键修正点说明
- 改用绝对差值计算涨跌:遵循Wilder原始定义,避免百分比放大波动
- 修正初始平均范围:仅取前
period个真实涨跌幅值计算初始平均,排除无意义的0值 - 极端情况处理:当平均跌幅为0时RSI直接设为100,平均涨幅为0时设为0,同时避免除以0错误
- 标准平滑递推:严格执行
(旧平均*(N-1) + 当期值)/N的公式,和主流平台算法完全一致
关于旧书公式的差异解释
你引用的旧书公式RSI(n) = 100 * (avg_up/(avg_up+avg_down))和标准公式RSI=100-(100/(1+RS))在数学上是等价的,但两者的avg_up/avg_down定义不同:旧书使用百分比涨跌幅的平均,而主流平台使用价格绝对差值的平均,这才是结果差异的核心原因。
内容的提问来源于stack exchange,提问作者h0ax
相关产品推荐
相关产品推荐

