Can we benefit from the position of the moving average relative to the price? Yes, in many ways as we have seen in previous articles. In this article, we will once again see another technique which seems to be better suited. The plan of attack is to go through once again moving averages and the RSI before introducing the Relative Average Distance in details.
Moving Averages
Moving averages come in all shapes and types. The most basic type is the simple moving average which is simply the sum divided by the quantity. The next mathematical representation shows how to calculate a simple mean given a dataset:
Therefore, the simple moving average is the sum of the values divided by their number. In technical analysis, you generally use moving averages to understand the underlying trend and to find trading signals. Check the next Figure which shows a 60-period simple moving average applied on hourly values of Ethereum versus USD.
Assume you have an OHLC data array imported in Python (which I have shown how to do many times in previous articles). Write the below primal functions that allow you to better manipulate data:
def add_column(data, times):
for i in range(1, times + 1):
new = np.zeros((len(data), 1), dtype = float)
data = np.append(data, new, axis = 1)
return data
def delete_column(data, index, times):
for i in range(1, times + 1):
data = np.delete(data, index, axis = 1)
return data
def delete_row(data, number):
data = data[number:, ]
return data
Then, to code a simple moving average, write the below function:
def ma(data, lookback, close, position):
data = add_column(data, 1)
for i in range(len(data)):
try:
data[i, position] = (data[i - lookback + 1:i + 1, close].mean())
except IndexError:
pass
data = delete_row(data, lookback)
return data
The Relative Strength Index
First introduced by J. Welles Wilder Jr., the RSI is one of the most popular and versatile technical indicators. Mainly used as a contrarian indicator where extreme values signal a reaction that can be exploited. Typically, we use the following steps to calculate the default RSI:
Calculate the change in the closing prices from the previous ones.
Separate the positive net changes from the negative net changes.
Calculate a smoothed moving average on the positive net changes and on the absolute values of the negative net changes.
Divide the smoothed positive changes by the smoothed negative changes. We will refer to this calculation as the Relative Strength — RS.
Apply the normalization formula shown below for every time step to get the RSI.
The above chart shows the hourly values of the GBPUSD in black with the 13-period RSI. We can generally note that the RSI tends to bounce close to 25 while it tends to pause around 75. To code the RSI in Python, we need an OHLC array composed of four columns that cover open, high, low, and close prices.
def smoothed_ma(data, alpha, lookback, close, position):
lookback = (2 * lookback) - 1
alpha = alpha / (lookback + 1.0)
beta = 1 - alpha
data = ma(data, lookback, close, position)
data[lookback + 1, position] = (data[lookback + 1, close] * alpha) + (data[lookback, position] * beta)
for i in range(lookback + 2, len(data)):
try:
data[i, position] = (data[i, close] * alpha) + (data[i - 1, position] * beta)
except IndexError:
pass
return data
def rsi(data, lookback, close, position):
data = add_column(data, 5)
for i in range(len(data)):
data[i, position] = data[i, close] - data[i - 1, close]
for i in range(len(data)):
if data[i, position] > 0:
data[i, position + 1] = data[i, position]
elif data[i, position] < 0:
data[i, position + 2] = abs(data[i, position])
data = smoothed_ma(data, 2, lookback, position + 1, position + 3)
data = smoothed_ma(data, 2, lookback, position + 2, position + 4)
data[:, position + 5] = data[:, position + 3] / data[:, position + 4]
data[:, position + 6] = (100 - (100 / (1 + data[:, position + 5])))
data = delete_column(data, position, 6)
data = delete_row(data, lookback)
return data
Make sure to focus on the concepts and not the code. You can find the codes of most of my strategies in my books. The most important thing is to comprehend the techniques and strategies.
You can also check out my other newsletter The Weekly Market Sentiment Report that sends tactical directional views every weekend to highlight the important trading opportunities using a mix between sentiment analysis (COT reports, Put-Call ratio, Gamma exposure index, etc.) and technical analysis.
The Relative Average Distance Indicator
The idea is to measure the distance of the price from its moving average and then to calculate a reversal to the mean based on the distance. The way to measure this mean-reversion is by applying the formula of the RSI on the price-average differences. Let us do this step-by-step.
Now, the first step is to calculate by default an 8-period simple moving average on the market price. Therefore, having defined all the above functions, we can simply write the following:
# Adding 2 columns to be populated by the moving averages
my_data = add_column(my_data, 2)
# Calculating the 8-period moving average
my_data = ma(my_data, 8, 3, 4)
Then, we need to calculate the difference between the current price and the 8-period moving average. We can code it in the following way:
# Subtracting the moving average column from the price column
my_data[:, 5] = my_data[:, 3] - my_data[:, 4]
Remember that in an OHLC data array, the column indexed at 3 refers to the closing price. The column indexed at 4 is the moving average calculation we have found in the previous step. This is because Python starts indexing at zero, therefore, when we want to refer to the seventh column in Python, we have to look at index 6.
The next step is to simply apply a 5-period RSI onto the previous results. This calculates the RSI of the price-average differences. It should gives another view on momentum. This can be done in the following way:
# Calculating the Relative Strength Index on the previous results
my_data = rsi(my_data, lookback, where + 1, 0)
Now, we can easily group the indicator into one function so that we do not always have to write many lines to generate it. The abbreviation for the Relative Average Distance Indicator is simply RAD.
def relative_average_distance(Data, lookback, ma_lookback, what, where):
# Adding the necessary columns
Data = add_column(Data, 2)
# Calculating the Moving Average of closing price
Data = ma(Data, ma_lookback, what, where)
# Calculating the difference between the closing price and its Moving Average
Data[:, where + 1] = Data[:, what] - Data[:, where]
# Deleting useless rows
Data = delete_row(Data, ma_lookback)
# Calculating the Relative Strength Index on the differences
Data = rsi(Data, lookback, where + 1, 0)
# Cleaning up rows/columns
Data = delete_column(Data, where, 2)
return Data
The conditions are as expected:
Long (Buy) whenever the RAD reaches 25 with the two previous values above 25.
Short (Sell) whenever the RAD reaches 75 with the two previous values below 75.
Summary
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.
You can also check out my other newsletter The Weekly Market Analysis Report that sends tactical directional views every weekend to highlight the important trading opportunities using technical analysis that stem from modern indicators. The newsletter is free.
If you liked this article, do not hesitate to like and comment, to further the discussion!