Implementing Wilder's RSI from Scratch in Python: A Step-by-Step Guide
While most trading platforms and charting software provide a built-in Relative Strength Index (RSI) indicator, professional traders and quantitative analysts often find it beneficial to implement the indicator themselves. Building the RSI from scratch not only provides a deeper understanding of its inner workings but also allows for greater flexibility in backtesting and strategy development. This article provides a step-by-step guide to implementing J. Welles Wilder Jr.'s RSI, with a focus on his specific smoothing method, using the Python programming language.
We will break down the implementation into logical steps, from calculating the initial average gains and losses to applying Wilder's smoothing for subsequent calculations. The code will be accompanied by detailed explanations and a sample dataset to ensure clarity and facilitate practical application.
The Python Implementation
The following Python code implements the Wilder's RSI. The function takes a list of closing prices and a lookback period as input and returns a list of RSI values.
def wilders_rsi(prices, period=14):
if len(prices) < period:
return []
gains = []
losses = []
for i in range(1, len(prices)):
change = prices[i] - prices[i-1]
if change > 0:
gains.append(change)
losses.append(0)
else:
gains.append(0)
losses.append(abs(change))
avg_gain = sum(gains[:period]) / period
avg_loss = sum(losses[:period]) / period
rsi_values = []
if avg_loss == 0:
rsi_values.append(100)
else:
rs = avg_gain / avg_loss
rsi = 100 - (100 / (1 + rs))
rsi_values.append(rsi)
for i in range(period, len(gains)):
avg_gain = (avg_gain * (period - 1) + gains[i]) / period
avg_loss = (avg_loss * (period - 1) + losses[i]) / period
if avg_loss == 0:
rsi_values.append(100)
else:
rs = avg_gain / avg_loss
rsi = 100 - (100 / (1 + rs))
rsi_values.append(rsi)
return rsi_values
def wilders_rsi(prices, period=14):
if len(prices) < period:
return []
gains = []
losses = []
for i in range(1, len(prices)):
change = prices[i] - prices[i-1]
if change > 0:
gains.append(change)
losses.append(0)
else:
gains.append(0)
losses.append(abs(change))
avg_gain = sum(gains[:period]) / period
avg_loss = sum(losses[:period]) / period
rsi_values = []
if avg_loss == 0:
rsi_values.append(100)
else:
rs = avg_gain / avg_loss
rsi = 100 - (100 / (1 + rs))
rsi_values.append(rsi)
for i in range(period, len(gains)):
avg_gain = (avg_gain * (period - 1) + gains[i]) / period
avg_loss = (avg_loss * (period - 1) + losses[i]) / period
if avg_loss == 0:
rsi_values.append(100)
else:
rs = avg_gain / avg_loss
rsi = 100 - (100 / (1 + rs))
rsi_values.append(rsi)
return rsi_values
Step-by-Step Explanation
-
Initialization: The function first checks if there is enough price data to calculate the RSI for the given period. It then initializes two lists,
gainsandlosses, to store the upward and downward price movements. -
Calculating Gains and Losses: The code iterates through the price data, calculating the change in price from one period to the next. If the change is positive, it is appended to the
gainslist, and a zero is appended to thelosseslist. If the change is negative, the absolute value of the change is appended to thelosseslist, and a zero is appended to thegainslist. -
Initial Average Gain and Loss: The initial average gain and loss are calculated using a simple moving average of the first
period(typically 14) gains and losses. -
Initial RSI: The first RSI value is calculated using the initial average gain and loss.
-
Wilder's Smoothing: For all subsequent periods, the function applies Wilder's smoothing method to calculate the new average gain and loss. The new average is the previous average multiplied by
(period - 1), plus the current gain or loss, all divided byperiod. -
Subsequent RSI Values: The RSI is then calculated for each subsequent period using the updated average gain and loss.
Sample Usage and Data Table
Let's use the wilders_rsi function with a sample dataset to see it in action. The following table shows the closing prices for a stock over 21 days, along with the calculated 14-day RSI values.
| Day | Close | 14-Day RSI |
|---|---|---|
| 1 | 44.34 | |
| 2 | 44.09 | |
| 3 | 44.15 | |
| 4 | 43.61 | |
| 5 | 44.33 | |
| 6 | 44.83 | |
| 7 | 45.10 | |
| 8 | 45.12 | |
| 9 | 45.18 | |
| 10 | 45.17 | |
| 11 | 45.23 | |
| 12 | 45.61 | |
| 13 | 45.82 | |
| 14 | 45.84 | 68.57 |
| 15 | 45.95 | 69.70 |
| 16 | 46.00 | 70.83 |
| 17 | 45.50 | 60.24 |
| 18 | 45.20 | 54.17 |
| 19 | 45.30 | 55.83 |
| 20 | 45.00 | 50.00 |
| 21 | 45.25 | 53.57 |
Conclusion
Implementing the RSI from scratch in Python is a valuable exercise for any serious trader or quantitative analyst. It provides a deeper understanding of the indicator's mechanics and allows for greater customization and flexibility in strategy development. The provided code and explanation serve as a solid foundation for building your own RSI-based trading tools and strategies.
