Discover more from All About Trading!
The Alternative RSI — Thinking Outside the Box
Creating the RSI on the Alternative Candlestick Chart
The RSI is a well-known indicator that can be applied on pretty much anything. This article discusses the application of the RSI on a different type of candlestick charting.
I have released a new book called “Contrarian Trading Strategies in Python”. It features a lot of advanced contrarian indicators and strategies with a GitHub page dedicated to the continuously updated code. If you are interested, you could buy the PDF version directly through a PayPal payment of 9.99 EUR.
Please include your email in the note before paying so that you receive it on the right address. Also, once you receive it, make sure to download it through google drive.
K’s Candlestick Chart
Candlestick charting is one of the gems in the world of financial and technical analysis. It uses the totality of the OHLC data to determine the likely direction and market psychology and has since become the norm of looking at charts. Other variations exist such as Heikin-Ashi, Renko, Kagi, and Point & Figure charts. All of them seek to determine the current market state in anticipation of the next likely direction.
In this article, we will see another variation called K’s Candlesticks and apply the RSI on its values which gives us the alternative RSI. These candlestick charts are similar to Heikin-Ashi but have some structural differences that makes them useful on their own. Pattern recognition works very well on K’s Candlesticks which we will later see.
Candlesticks are a quick way to understand OHLC data and detect patterns. It is very straightforward and easy to interpret. A bullish (typically green) candle is when the market closes above its opening price. A bearish (typically red) candle is when the market closes below its opening price.
The below shows an example of a candlestick chart on the EURUSD’s hourly values.
def ohlc_plot_candles(Data, window): Chosen = Data[-window:, ] for i in range(len(Chosen)): plt.vlines(x = i, ymin = Chosen[i, 2], ymax = Chosen[i, 1], color = 'black', linewidth = 1) if Chosen[i, 3] > Chosen[i, 0]: color_chosen = 'green' plt.vlines(x = i, ymin = Chosen[i, 0], ymax = Chosen[i, 3], color = color_chosen, linewidth = 3)
if Chosen[i, 3] < Chosen[i, 0]: color_chosen = 'red' plt.vlines(x = i, ymin = Chosen[i, 3], ymax = Chosen[i, 0], color = color_chosen, linewidth = 3) if Chosen[i, 3] == Chosen[i, 0]: color_chosen = 'black' plt.vlines(x = i, ymin = Chosen[i, 3], ymax = Chosen[i, 0] + 0.00001, color = color_chosen, linewidth = 6) plt.grid()
The above code plots a candlestick chart as shown. It requires an OHLC data array. The window variable refers to how many observations will be shown in the chart.
To create the K’s Candlestick chart, we need to transform the prices using the simple moving average formula. The steps are relatively easy:
Calculate a 2-period simple moving average of the opening price.
Calculate a 2-period simple moving average of the high price.
Calculate a 2-period simple moving average of the low price.
Calculate a 2-period simple moving average of the close price.
Then, we will treat the new four columns as the candlestick data while being careful from using them in trading as they are not real prices, but simple moving averages.
The above charts show the EURUSD charted differently. The period used is 2. We can notice how smoother the K’s candlestick chart is compared to the noisy regular chart. By noisy, the meaning here is on the interpretability of the trend. When successive red or green candles are observed, the trend is easier to be determined.
The Relative Strength Index
The RSI is without a doubt the most famous momentum indicator out there, and this is to be expected as it has many strengths especially in ranging markets. It is also bounded between 0 and 100 which makes it easier to interpret. Also, the fact that it is famous, contributes to its potential.
This is because the more traders and portfolio managers look at the RSI, the more people will react based on its signals and this in turn can push market prices. Of course, we cannot prove this idea, but it is intuitive as one of the basis of Technical Analysis is that it is self-fulfilling.
The RSI is calculated using a rather simple way. We first start by taking price differences of one period. This means that we have to subtract every closing price from the one before it. Then, we will calculate the smoothed average of the positive differences and divide it by the smoothed average of the negative differences. The last calculation gives us the Relative Strength which is then used in the RSI formula to be transformed into a measure between 0 and 100.
To calculate the relative strength index, we need an OHLC array (not a data frame). This means that we will be looking at an array of 4 columns. The function for the Relative Strength Index is therefore:
# The function to add a number of columns inside an array def adder(Data, times): for i in range(1, times + 1): new_col = np.zeros((len(Data), 1), dtype = float) Data = np.append(Data, new_col, axis = 1) return Data
# The function to delete a number of columns starting from an index def deleter(Data, index, times): for i in range(1, times + 1): Data = np.delete(Data, index, axis = 1) return Data # The function to delete a number of rows from the beginning def jump(Data, jump): Data = Data[jump:, ] return Data
# Example of adding 3 empty columns to an array my_ohlc_array = adder(my_ohlc_array, 3)
# Example of deleting the 2 columns after the column indexed at 3 my_ohlc_array = deleter(my_ohlc_array, 3, 2)
# Example of deleting the first 20 rows my_ohlc_array = jump(my_ohlc_array, 20)
# Remember, OHLC is an abbreviation of Open, High, Low, and Close and it refers to the standard historical data file
def ma(Data, lookback, close, where): Data = adder(Data, 1) for i in range(len(Data)): try: Data[i, where] = (Data[i - lookback + 1:i + 1, close].mean()) except IndexError: pass # Cleaning Data = jump(Data, lookback) return Data
def ema(Data, alpha, lookback, what, where): alpha = alpha / (lookback + 1.0) beta = 1 - alpha # First value is a simple SMA Data = ma(Data, lookback, what, where) # Calculating first EMA Data[lookback + 1, where] = (Data[lookback + 1, what] * alpha) + (Data[lookback, where] * beta) # Calculating the rest of EMA for i in range(lookback + 2, len(Data)): try: Data[i, where] = (Data[i, what] * alpha) + (Data[i - 1, where] * beta) except IndexError: pass return Data
def rsi(Data, lookback, close, where): # Adding a few columns Data = adder(Data, 5) # Calculating Differences for i in range(len(Data)): Data[i, where] = Data[i, close] - Data[i - 1, close] # Calculating the Up and Down absolute values for i in range(len(Data)): if Data[i, where] > 0: Data[i, where + 1] = Data[i, where] elif Data[i, where] < 0: Data[i, where + 2] = abs(Data[i, where]) # Calculating the Smoothed Moving Average on Up and Down absolute values lookback = (lookback * 2) - 1 # From exponential to smoothed Data = ema(Data, 2, lookback, where + 1, where + 3) Data = ema(Data, 2, lookback, where + 2, where + 4)
# Calculating the Relative Strength Data[:, where + 5] = Data[:, where + 3] / Data[:, where + 4] # Calculate the Relative Strength Index Data[:, where + 6] = (100 - (100 / (1 + Data[:, where + 5])))
# Cleaning Data = deleter(Data, where, 6) Data = jump(Data, lookback)
Creating the Alternative RSI
The alternative RSI is simply a relative strength index applied on K’s candlestick values. If we choose a 13-period RSI with a 20 lower barrier and a 80 upper barrier, we can have the following trading rules:
A long (Buy) signal is generated whenever the 13-period alternative RSI reaches 20.
A short (Sell) signal is generated whenever the 13-period alternative RSI reaches 80.
Let us try a simplistic back-test using the following conditions:
Whenever the signal is generated, the exit will be upon the next signal only.
No transaction costs will be considered.
The results are mixed between applying the regular and the alternative RSI where on some pairs they switch between outperformance and underperformance. The above table shows that on the EURUSD’s hourly values since 2011, a slight outperformance of the alternative RSI can be seen, however, the strategy is not profitable as it has not been optimized. The recommendation here is to use both types of indicators in a full trading system combined with risk management.
ma_lookback = 2 rsi_lookback = 13
lower_barrier = 20 upper_barrier = 80
def signal(Data, rsi_col, buy, sell): Data = adder(Data, 10) for i in range(len(Data)): if Data[i, rsi_col] < lower_barrier and Data[i - 1, rsi_col] > lower_barrier: Data[i, buy] = 1 if Data[i, rsi_col] > upper_barrier and Data[i - 1, rsi_col] < upper_barrier: Data[i, sell] = -1 return Data
# Creating the K's candlestick charts my_data = k_candlesticks(my_data, 0, 1, 2, 3, ma_lookback, 4)
# Creating the alternative RSI my_data = rsi(my_data, rsi_lookback, 7, 8)
# Creating the signals my_data = signal(my_data, 8, 9, 10)
To sum up, what I am trying to do is to simply contribute to the world of objective technical analysis which is promoting more transparent techniques and strategies that need to be back-tested before being implemented. This way, technical analysis will get rid of the bad reputation of being subjective and scientifically unfounded.
I recommend you always follow the the below steps whenever you come across a trading technique or strategy:
Have a critical mindset and get rid of any emotions.
Back-test it using real life simulation and conditions.
If you find potential, try optimizing it and running a forward test.
Always include transaction costs and any slippage simulation in your tests.
Always include risk management and position sizing in your tests.
Finally, even after making sure of the above, stay careful and monitor the strategy because market dynamics may shift and make the strategy unprofitable.
For the paperback link of the book, you may use the following link: