I found this on the next link: Back Testing RSI Divergence Strategy on FX

The author of the post used the exponential moving average for RSI calculation, using this piece of code:

'''
Assuming you have a pandas OHLC Dataframe downloaded from Metatrader 5 historical data. 
'''
# Get the difference in price from previous step
Data = pd.DataFrame(Data)
delta = Data.iloc[:, 3].diff()
delta = delta[1:]

# Make the positive gains (up) and negative gains (down) Series
up, down = delta.copy(), delta.copy()
up[up < 0] = 0
down[down > 0] = 0
roll_up = pd.stats.moments.ewma(up, lookback)
roll_down = pd.stats.moments.ewma(down.abs(), lookback)

# Calculate the SMA
roll_up = roll_up[lookback:]
roll_down = roll_down[lookback:]
Data = Data.iloc[lookback + 1:,].values

# Calculate the RSI based on SMA
RS = roll_up / roll_down
RSI = (100.0 - (100.0 / (1.0 + RS)))
RSI = np.array(RSI)
RSI = np.reshape(RSI, (-1, 1))

Data = np.concatenate((Data, RSI), axis = 1)

At this point we have an array with OHLC data and a fifth column that has the RSI in it. Then added the next two columns:

  1. Column 6: Data[:, 5] will be for the bullish divergences and will have values of 0 or 1 (initiate buy).
  2. Column 7: Data[:, 6] will be for the bearish divergences and will have values of 0 or -1 (initiate short).

using this variables:

lower_barrier = 30
upper_barrier = 70
width = 10

Here is the code:

# Bullish Divergence
for i in range(len(Data)):
   try:
       if Data[i, 4] < lower_barrier:
           for a in range(i + 1, i + width):
               if Data[a, 4] > lower_barrier:
                    for r in range(a + 1, a + width):
                       if Data[r, 4] < lower_barrier and \
                        Data[r, 4] > Data[i, 4] and Data[r, 3] < Data[i, 3]:
                            for s in range(r + 1, r + width): 
                                if Data[s, 4] > lower_barrier:
                                    Data[s + 1, 5] = 1
                                    break
                                else:
                                    continue
                        else:
                            continue
                    else:
                        continue
                else:
                    continue
  except IndexError:
        pass

# Bearish Divergence
for i in range(len(Data)):
   try:
       if Data[i, 4] > upper_barrier:
           for a in range(i + 1, i + width): 
               if Data[a, 4] < upper_barrier:
                   for r in range(a + 1, a + width):
                       if Data[r, 4] > upper_barrier and \
                       Data[r, 4] < Data[i, 4] and Data[r, 3] > Data[i, 3]:
                           for s in range(r + 1, r + width):
                               if Data[s, 4] < upper_barrier:
                                   Data[s + 1, 6] = -1
                                   break
                               else:
                                   continue
                       else:
                           continue
                   else:
                       continue
               else:
                   continue
   except IndexError:
       pass
Answer from robbinc91 on Stack Overflow
Top answer
1 of 4
3

I found this on the next link: Back Testing RSI Divergence Strategy on FX

The author of the post used the exponential moving average for RSI calculation, using this piece of code:

'''
Assuming you have a pandas OHLC Dataframe downloaded from Metatrader 5 historical data. 
'''
# Get the difference in price from previous step
Data = pd.DataFrame(Data)
delta = Data.iloc[:, 3].diff()
delta = delta[1:]

# Make the positive gains (up) and negative gains (down) Series
up, down = delta.copy(), delta.copy()
up[up < 0] = 0
down[down > 0] = 0
roll_up = pd.stats.moments.ewma(up, lookback)
roll_down = pd.stats.moments.ewma(down.abs(), lookback)

# Calculate the SMA
roll_up = roll_up[lookback:]
roll_down = roll_down[lookback:]
Data = Data.iloc[lookback + 1:,].values

# Calculate the RSI based on SMA
RS = roll_up / roll_down
RSI = (100.0 - (100.0 / (1.0 + RS)))
RSI = np.array(RSI)
RSI = np.reshape(RSI, (-1, 1))

Data = np.concatenate((Data, RSI), axis = 1)

At this point we have an array with OHLC data and a fifth column that has the RSI in it. Then added the next two columns:

  1. Column 6: Data[:, 5] will be for the bullish divergences and will have values of 0 or 1 (initiate buy).
  2. Column 7: Data[:, 6] will be for the bearish divergences and will have values of 0 or -1 (initiate short).

using this variables:

lower_barrier = 30
upper_barrier = 70
width = 10

Here is the code:

# Bullish Divergence
for i in range(len(Data)):
   try:
       if Data[i, 4] < lower_barrier:
           for a in range(i + 1, i + width):
               if Data[a, 4] > lower_barrier:
                    for r in range(a + 1, a + width):
                       if Data[r, 4] < lower_barrier and \
                        Data[r, 4] > Data[i, 4] and Data[r, 3] < Data[i, 3]:
                            for s in range(r + 1, r + width): 
                                if Data[s, 4] > lower_barrier:
                                    Data[s + 1, 5] = 1
                                    break
                                else:
                                    continue
                        else:
                            continue
                    else:
                        continue
                else:
                    continue
  except IndexError:
        pass

# Bearish Divergence
for i in range(len(Data)):
   try:
       if Data[i, 4] > upper_barrier:
           for a in range(i + 1, i + width): 
               if Data[a, 4] < upper_barrier:
                   for r in range(a + 1, a + width):
                       if Data[r, 4] > upper_barrier and \
                       Data[r, 4] < Data[i, 4] and Data[r, 3] > Data[i, 3]:
                           for s in range(r + 1, r + width):
                               if Data[s, 4] < upper_barrier:
                                   Data[s + 1, 6] = -1
                                   break
                               else:
                                   continue
                       else:
                           continue
                   else:
                       continue
               else:
                   continue
   except IndexError:
       pass
2 of 4
3

I changed above code a bit hope this helps:

lower_barrier = 30
upper_barrier = 70
width = 5
#Bullish Divergence
for i in range(len(Data)):

   try:
     if Data.iloc[i, 4] < lower_barrier:
         for a in range(i + 1, i + width):
             if Data.iloc[a, 4] > lower_barrier:
                  for r in range(a + 1, a + width):
                     if Data.iloc[r, 4] < lower_barrier and Data.iloc[r, 4] > Data.iloc[i, 4] and Data.iloc[r, 3] < Data.iloc[i, 3]:
                         for s in range(r + 1, r + width): 
                            if Data.iloc[s, 4] > lower_barrier:
                                print('Bullish above',Data.iloc[s+1,1])
                                Data.iloc[s + 1, 5] = 1
                                break
                            else:
                                continue
                    else:
                        continue
            else:
                continue
    else:
        continue
except IndexError:
    pass
#Bearish Divergence
for i in range(len(Data)):
try:
    if Data.iloc[i, 4] > upper_barrier:
        for a in range(i + 1, i + width): 
            if Data.iloc[a, 4] < upper_barrier:
                for r in range(a + 1, a + width):
                    if Data.iloc[r, 4] > upper_barrier and Data.iloc[r, 4] < Data.iloc[i, 4] and Data.iloc[r, 3] > Data.iloc[i, 3]:
                        for s in range(r + 1, r + width):
                            if Data.iloc[s, 4] < upper_barrier:
                                print('Bearish below',Data.iloc[s+1,2])
                                Data.iloc[s + 1, 6] = -1
                                break
                            else:
                                continue
                    else:
                        continue
                else:
                    continue
            else:
                continue
except IndexError:
    pass
🌐
GitHub
github.com › AmirRezaFarokhy › RSI-Divergence
GitHub - AmirRezaFarokhy/RSI-Divergence
Finding the divergence of the gold market(XAUUSD) based on the RSI indicator. It is one of the trading strategies. Tested and obtained percentage: 75% winning rate. ... # install numpy pip install numpy # install matplotlib pip install matplotlib # install pandas pip install pandas ... The pandas helps to Implementation of mathematics and algorithms. The numpy it makes it easy to do math and work with matrices. The matplotlib Python ...
Starred by 16 users
Forked by 9 users
Languages   Jupyter Notebook 98.3% | Python 1.7% | Jupyter Notebook 98.3% | Python 1.7%
🌐
GitHub
github.com › SpiralDevelopment › RSI-divergence-detector
GitHub - SpiralDevelopment/RSI-divergence-detector: RSI divergence detector finds regular and hidden bullish and bearish divergences
March 22, 2022 - sample_tg_poster.py - Gets the ohlc data from local database and checks if the last candle has RSI divergence
Starred by 110 users
Forked by 39 users
Languages   Python 100.0% | Python 100.0%
🌐
YouTube
youtube.com › watch
RSI Divergence Automated In Python | Algorithmic Trading - YouTube
The RSI Divergence Detection is programmed in python as an automated indicator for algorithmic trading, the Jupyter notebook file is available from the link:...
Published   November 12, 2021
🌐
Reddit
reddit.com › r/algotrading › i created a divergence indicator (python)
r/algotrading on Reddit: I created a divergence indicator (Python)
November 12, 2021 -

TLDR: I developed a divergence indicator in Python. Source code on my GitHub here.

Hi, I thought I would share a divergence indicator I have developed in Python. It can be used to detect divergence between any two datasets, whether that be price and an indicator, or two indicators.

I started by looking at indicators available on TradingView for inspiration and found their built-in divergence indicator, which uses pivot points to locate local turning points in price/indicators. My idea was to use a different method for this, which has turned out to be more responsive and hence less lagging. To do so, I apply a 2-period EMA to hl2 data and detected a new price level when the gradient of the ema changes. The chart below illustrates this idea. The same concept can be applied to indicators.

Dashed lines appear when a new 'support' or 'resistance' level is detected. The sensitivity of this indicator can be controlled by the period of the EMA.

Since this method will sometimes detect new levels due to noise, I filter for 'strong' levels by only accepting levels which last greater than (for example) 2 candles. Now it is possible to detect higher-highs, lower-lows, lower-highs and higher-lows. An example of this is shown in the chart below, where lower-lows in price are detected.

Detection of lower-lows using price levels.

Now the same process can be applied to indicators instead of price data: instead of taking the EMA of price, passing the indicator data straight in is sufficient. This will work for RSI, Stochastics, MACD, or any other data source.

As an example, I have applied it the RSI. As per the definition, regular bullish divergence occurs when price makes a lower-low at the same time an indicator makes a higher-low. By comparing the levels detected in price to the levels detected in the indicator, divergence between them can be detected. The chart below shows an example of regular bullish divergence being detected.

An example of regular bullish divergence being detected.

For comparison, the screenshot below shows TradingView's divergence indicator on the same instrument (EUR/USD on D) at the same time. Although the bullish tag appears earlier on the chart, the signal will not actually appear until the candle I have highlighted with a vertical line (try using the replay function to see this for yourself - it is a bit misleading when the signal would be received live). In this (admittedly cherry-picked) example, the indicator I have developed picks up the signal 3 candles before the TradingView indicator, which equals approximately 100 pips.

TradingView's divergence indicator.

The source code for the indicator can be found on my GitHub (link at the top of this post). The module containing the code is actually a part of my entire trading project, but using the indicators from that module is easy enough.

Note that I have split the processes above into three indicators. There are some parameters which can be used to tune the sensitivity of each, but I will just give a brief overview of how to use them to reproduce the results above. They are also commented in the code itself. The indicators are:

  • find_swings(): to detect the reversal levels. This function accepts OHLC data and indicator data sources. If you pass in the data from an indicator (ie. a 1D array), use the data_type='other' input parameter to specify that it is not OHLC data. This function will return a DataFrame with columns Highs, Lows, Last and Trend. The first three contain the values of the data source at high swings, low swings and the most recent swing, respectively. The Trend column contains 1 when there is an implied uptrend, and -1 when there is an implied downtrend.

  • classify_swings(): to classify the swing levels as higher-highs, lower-lows, lower-highs and higher-lows. The main input to this function is the DataFrame output of find_swings(). The output is another DataFrame with columns "HH", "LL", "LH" and "HL".

  • detect_divergence(): to compare the classified swings of two data sources (for example, price data and RSI). This function requires two "classified swings" DataFrames as inputs, as outputted from the classify_swings() function. It will then return a DataFrame with True/False columns titled 'regularBull', 'regularBear', 'hiddenBull', and 'hiddenBear', corresponding to the regular and hidden divergences detected.

I have also wrapped all of the indicators above into a single indicator, autodetect_divergence. The inputs to this functions are the OHLC data and the indicator data. It will return the same thing as detect_divergence, described above.

Hopefully this post was interesting and maybe gave someone some ideas. Please let me know if you have any suggestions or questions. Thanks for reading!

🌐
Raposa
raposa.trade › blog › test-and-trade-rsi-divergence-in-python
Test and Trade RSI Divergence in Python — Raposa
July 26, 2021 - This is only a short, 7-month window so we can clearly see the moves of both the price and RSI, so there is only one divergence visible. We see confirmation of higher lows in mid-June on the RSI chart (orange, upward pointing triangle) in the midst of a long series of lower lows in the price chart (blue, downward pointing triangles).
Find elsewhere
🌐
PyPI
pypi.org › project › rsi-divergence-detector
rsi-divergence-detector · PyPI
A tool to detect RSI divergences in price data. ... Lightweight, tested Python library & CLI for detecting RSI divergences (regular & hidden) on time‑series price data.
      » pip install rsi-divergence-detector
    
Published   Aug 11, 2025
Version   0.1.0
🌐
YouTube
youtube.com › watch
CODING RSI DIVERGENCES - YouTube
In this video, I will teach you how to code the RSI divergence in Python.Here is the link to the code:https://www.technicallysorted.com/products/Coding-an-RS...
Published   June 28, 2023
🌐
YouTube
youtube.com › watch
How to Detect RSI Divergence in Pine Script - YouTube
🚩 My Socials & More Free Content: https://theartoftrading.com🚩 FREE Pine Script Basics Course: https://courses.theartoftrading.com/courses/pine-script-basi...
Published   July 28, 2023
🌐
Kaggle
kaggle.com › code › chandrimad31 › forex-trading-momentum-analysis-rsi-divergence
Forex Trading Momentum Analysis: RSI Divergence | Kaggle
May 29, 2022 - Explore and run machine learning code with Kaggle Notebooks | Using data from EUR/USD Forex Trading Data 4 Hrs Gap (2003-2021)
🌐
PyPI
pypi.org › project › ta-py
ta-py · PyPI
data = [74,83,66,78,69,70,84,73,74,73,83]; rsi_length = 5; rsi_function = ta.wrsi; # default (the tradingview rsi indicator) ta.rsi_divergence(data, rsi_length, rsi_function); # output (array) # 1 = RSI is in divergence # 0 = RSI is not in divergence # [0, 0, 1, 0, 1, 0] (better to quantify if needed) data1 = [48,34,43,54,56,64,43]; data2 = [76,74,43,55,34,32,45,47]; ta.divergence(data1, data2); # output (array) # 1 = RSI is in divergence # 0 = RSI is not in divergence # [0, 0, 1, 1, 0, 1] (better to quantify if needed) data = [8,7,8,9,7,8,9,6,7,8,6,8,10,8,7,9,8,7,9,6,7,9]; # defaults shown ja
      » pip install ta-py
    
Published   Jan 15, 2023
Version   1.6.0
🌐
Medium
medium.com › raposa-technologies › test-and-trade-rsi-divergence-in-python-34a11c1c4142
Test and Trade RSI Divergence in Python | by Raposa.Trade | Raposa Technologies | Medium
February 2, 2022 - Technical traders track these visually — but it can be difficult to replicate because it isn’t always clear what exactly makes a “peak.” We provide an algorithmic way to detect peaks and troughs for trading, which we’ll leverage below as we get into the details of building an RSI divergence strategy.
🌐
GitHub
github.com › je-suis-tm › quant-trading › blob › master › RSI Pattern Recognition backtest.py
quant-trading/RSI Pattern Recognition backtest.py at master · je-suis-tm/quant-trading
Python quantitative trading strategies including VIX Calculator, Pattern Recognition, Commodity Trading Advisor, Monte Carlo, Options Straddle, Shooting Star, London Breakout, Heikin-Ashi, Pair Trading, RSI, Bollinger Bands, Parabolic SAR, Dual Thrust, Awesome, MACD - quant-trading/RSI Pattern Recognition backtest.py at master · je-suis-tm/quant-trading
Author   je-suis-tm
🌐
GitHub
github.com › SpiralDevelopment › RSI-divergence-detector › blob › main › rsi_divergence_finder.py
RSI-divergence-detector/rsi_divergence_finder.py at main · SpiralDevelopment/RSI-divergence-detector
RSI_COLUMN = 'rsi' BASE_COLUMN = 'C' TIME_COLUMN = 'T' ANGLE_LIMIT = 45.0 # Limit for angle of divergence lines · · · def calc_percentage_increase(original, new): increase = (new - original) / original · return increase * 100 · · · # cur_candle_idx - index of the candle to which we compare candles in the past to find divergences ·
Author   SpiralDevelopment
🌐
QuantInsti
blog.quantinsti.com › rsi-indicator
RSI Indicator Formula and Calculation: Trading Strategies and Python Implementation
March 5, 2025 - Learn how the RSI indicator works, from its formula and calculation to trading strategies and backtesting. Explore Python implementation with real-world examples and visualizations.
🌐
YouTube
youtube.com › watch
Python Trading Strategy: RSI Divergence Backtest
Enjoy the videos and music you love, upload original content, and share it all with friends, family, and the world on YouTube.
🌐
AlphaSquawk
alphasquawk.com › alphasquawk | knowledge for traders › strategy › relative strength index: trading strategies, rsi divergence and python
Relative Strength Index: Trading Strategies, RSI Divergence and Python
February 25, 2025 - You could expand this code to develop an RSI indicator screener. Note to the right of the chart bearish RSI divergence from price as it makes lower highs while the price increases which is a bearish signal.
🌐
Medium
medium.com › @trading.dude › spotting-market-turning-points-how-to-detect-bullish-and-bearish-divergence-with-python-b0c44df25461
Spotting Market Turning Points: How to Detect Bullish and Bearish Divergence with Python | by Trading Dude | Medium
May 12, 2025 - While the price makes higher highs, the RSI doesn’t; a sign that current trend cools off. ... AAPL daily chart — very clear indications! ... These divergences can be detected accross different asset classes. Let’s get practical. Below is a Python script that detects both bullish and bearish divergences between price and an indicator.