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:
- Column 6: Data[:, 5] will be for the bullish divergences and will have values of 0 or 1 (initiate buy).
- 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 OverflowI 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:
- Column 6: Data[:, 5] will be for the bullish divergences and will have values of 0 or 1 (initiate buy).
- 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
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
Videos
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 thedata_type='other'input parameter to specify that it is not OHLC data. This function will return a DataFrame with columnsHighs,Lows,LastandTrend. The first three contain the values of the data source at high swings, low swings and the most recent swing, respectively. TheTrendcolumn contains1when there is an implied uptrend, and-1when 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 offind_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 theclassify_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!
Dear all, I would like to use Python to detect bearish and bullish divergences on the price/RSI. In my thought progress the way this could be coded is as follows:
-
Calculate relative maxima and minima.
-
Calculate RSI at those points.
-
For each pair of lows and highs, compare the change in price with the difference in RSI.
Has anyone ever tried coding this? Thanks
I was searching for answers to the same question and came across your question.
After some thought and research, here is the plan I have developed. I will be working in Python.
- Calculate relative maxima and minima with SciPy.
- Calculate RSI at those points using lib-ta.
- For each pair of lows and highs, compare the change in price with the difference in RSI.
I'm completely new to technical analysis, so in case I have made any oversights, feedback would be greatly appreciated. I wanted to ask about your programming language and data format, but don't have enough reputation to comment.
I want to implement exactly same principle in C# and realized that i should start opposite. Start from finding Higher High or Lower Low and then checking RSI. After finding HH or LL checking RSI is trivial task. To find HH or LL you could use ZigZag indicator. At investopedia you could find how to calculate it in more details. Also you could check Python version of it in quantconnect forum. Also, you could find more versions on internet.
» pip install rsi-divergence-detector