The Average Normalization Trading Strategy in Python.
Creating a Contrarian Strategy Based on the Normalized Index.
Combinations of strategies may offer better opportunities. We can combine indicators together or patterns together. In this article, we will see how to use the Normalized Index with a touch of moving average applied to it to smooth out the signals.
I have just published a new book after the success of New Technical Indicators in Python. It features a more complete description and addition of complex trading strategies with a GitHub page dedicated to the continuously updated code. If you feel that this interests you, feel free to visit the below link, or if you prefer the PDF version, you could contact me on LinkedIn.
The Normalized Index
We have to understand two things about technical indicators:
They are price derived. this means that they take the price and decompose it to understand some characteristics. They are therefore not forward looking but backward looking. Our hope is for this backward relationship to continue in the future. For example, if we see a divergence on the RSI, we are hoping it causes exhaustion in prices like it usually does. This divergence does not peek at the future, it is simply a mathematical observation.
They are unlikely to provide a winning strategy on their own. If they did, then why aren’t we all millionaires depending on overbought/oversold zones on the Stochastic indicator? Trading is much more complicated than that and requires a more thorough approach to find profitable trades.
With that being in mind, we should think of indicators as little helpers with our convictions. For example, when we find sufficient information to tell us to go long (buy) an asset, we can check the technical indicators to see whether they confirm this or not. We should also check the current market state to know whether the indicator is going to provide a good signal or not.
The Normalized Index is simply a mathematical calculation that uses the Normalization function. This great technique allows us to trap the values between 0 and 1 (or 0 and 100 if we wish to multiply by 100). The concept revolves around subtracting the minimum value in a certain lookback period from the current value and dividing by the maximum value in the same lookback period minus the minimum value (the same in the nominator).
Let us first code the primal functions that are needed to facilitate data manipulation and modification:
We can try to code this formula in python. The below function normalizes a given time series of the OHLC type:
# The function to add a certain number of columns
def adder(Data, times):
for i in range(1, times + 1):
z = np.zeros((len(Data), 1), dtype = float)
Data = np.append(Data, z, axis = 1)
return Data
# The function to deleter a certain number of columns
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 certain number of rows from the beginning
def jump(Data, jump):
Data = Data[jump:, ]
return Data
def normalizer(Data, lookback, what, where):
for i in range(len(Data)):
try:
Data[i, where] = (Data[i, what] - min(Data[i - lookback + 1:i + 1, what])) / (max(Data[i - lookback + 1:i + 1, what]) - min(Data[i - lookback + 1:i + 1, what]))
except ValueError:
pass
Data[:, where] = Data[:, where] * 100
Data = jump(Data, lookback)
return Data
# Using the function
my_data = adder(my_data, 1)
my_data = normalizer(my_data, 4, 3, 4)
Intuitively, we can understand that when the 4-period Normalized Index is at 100, it means that the current close of the market price is the highest during the last 4 periods.
If you are also interested by more technical indicators and using Python to create strategies, then my best-selling book on Technical Indicators may interest you:
Creating the Strategy
The idea of the strategy is to smooth out the values of the Normalized Index using an exponential moving average. That way, we do not get a lot signals and they get filtered out systematically. The below plot shows a 13-period exponential moving average applied on a 40-period Normalized Index.
To code the transformed indicator, we need to define moving averages first. We can do this through the below code:
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
Then, the next step is to apply the exponential function on the Normalized Index’s column using this syntax:
my_data = ema(my_data, 2, 13, normalized_column, new_column)
Now, it is time to derive the signals from the transformed indicator, we can follow these guidelines:
Go long (Buy) whenever the indicator hits or breaks the 5 level while the previous reading is above 5.
Go short (Sell) whenever the indicator hits or surpasses the 95 level while the previous reading is below 95.
upper_barrier = 95
lower_barrier = 5
def signal(Data, normalized_col, buy, sell):
Data = adder(Data, 10)
Data = rounding(Data, 5)
for i in range(len(Data)):
if Data[i, normalized_col] <= lower_barrier and Data[i - 1, normalized_col] > lower_barrier:
Data[i, buy] = 1
elif Data[i, normalized_col] >= upper_barrier and Data[i - 1, normalized_col] < upper_barrier:
Data[i, sell] = -1
return Data
Depending on the lookback period, you can manage the frequency of the signals. In the above plot, we can see that they are quite rare, and this can be fixed by two means:
Reducing the lookback period from 40 to 20 for example, or even 10.
Tightening the barriers from 95/5 to 90/10 for example, or even 85/15.
The rarity of signals is sometimes a strength as too much signals can hinder the quality. However, we need to find a balance between quality and quantity.
The strategy is optimally used within a range if the lookback period is not very high, otherwise, in trending markets, it can always be useful but extensive back-testing must be done.
Conclusion & Important Disclaimer
Remember to always do your back-tests. You should always believe that other people are wrong. My indicators and style of trading may work for me but maybe not for you.
I am a firm believer of not spoon-feeding. I have learnt by doing and not by copying. You should get the idea, the function, the intuition, the conditions of the strategy, and then elaborate (an even better) one yourself so that you back-test and improve it before deciding to take it live or to eliminate it. My choice of not providing Back-testing results should lead the reader to explore more herself the strategy and work on it more. That way you can share with me your better strategy and we will get rich together.
To sum up, are the strategies I provide realistic? Yes, but only by optimizing the environment (robust algorithm, low costs, honest broker, proper risk management, and order management). Are the strategies provided only for the sole use of trading? No, it is to stimulate brainstorming and getting more trading ideas as we are all sick of hearing about an oversold RSI as a reason to go short or a resistance being surpassed as a reason to go long. I am trying to introduce a new field called Objective Technical Analysis where we use hard data to judge our techniques rather than rely on outdated classical methods.
One Last Word
I have recently started an NFT collection that aims to support different humanitarian and medical causes. The Society of Light is a set of limited collectibles which will help make the world slightly better as each sale will see a percentage of it sent directly to the charity attributed to the avatar. As I always say, nothing better than a bullet list to outline the benefits of buying these NFT’s:
High-potential gain: By concentrating the remaining sales proceedings on marketing and promoting The Society of Light, I am aiming to maximize their value as much as possible in the secondary market. Remember that trading in the secondary market also means that a portion of royalties will be donated to the same charity.
Art collection and portfolio diversification: Having a collection of avatars that symbolize good deeds is truly satisfying. Investing does not need to only have selfish needs even though there is nothing wrong with investing to make money. But what about investing to make money, help others, and collect art?
Donating to your preferred cause(s): This is a flexible way of allocating different funds to your charities.
A free copy of my book in PDF: Any buyer of any NFT will receive a free copy of my latest book shown in the link of the article.