Skip to content

refactor: compute_rsi uses simple rolling mean instead of Wilder's EMA smoothing #58

@Codex-Crusader

Description

@Codex-Crusader

Summary

The RSI implementation in pulseengine/core/price.py uses a simple rolling().mean() for gain/loss averaging, not Wilder's original exponential smoothing (EMA). The standard RSI formula, as described in Wilder's original paper and used by most charting platforms, uses an exponential moving average:

Avg Gain = (Prev Avg Gain * (period - 1) + current gain) / period

The current implementation:

avg_gain = gain.rolling(period).mean().iloc[-1]
avg_loss = loss.rolling(period).mean().iloc[-1]

This is equivalent to a Simple Moving Average (SMA) over period bars, which produces different RSI values than the Wilder EMA approach used by TradingView, Bloomberg, and most financial platforms. This means RSI values displayed in PulseEngine may not match what users see on other charting tools, reducing trust in the signals.

Impact

  • RSI readings from PulseEngine will diverge from industry-standard RSI, especially on longer series
  • Signal labels (overbought/oversold) may fire at different thresholds than expected

Proposed fix

Replace the rolling mean with Wilder's EWM smoothing:

avg_gain = gain.ewm(com=period - 1, min_periods=period).mean().iloc[-1]
avg_loss = loss.ewm(com=period - 1, min_periods=period).mean().iloc[-1]

com=period-1 maps to Wilder's smoothing factor alpha = 1/period.

Tests

Add a test case in tests/test_core.py comparing RSI output against known reference values from a standard RSI calculator.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions