Moving averages can have infinite combinations of strategies. This article discusses a strategy on the SSL, a special type of moving averages that are used in breakout techniques.
I have just released a new book after the success of my previous one “The Book of Trading Strategies”. It features advanced trend-following indicators and strategies with a GitHub page dedicated to the continuously updated code. Also, this book features the original colors after having optimized for printing costs. If you feel that this interests you, feel free to visit the below Amazon link, or if you prefer to buy the PDF version, you could contact me on LinkedIn.
The SSL Indicator
The SSL indicator is a short-term simple moving average combined to both highs and lows. It serves as a moving zone that when surpassed or broken, confirms the breakout move. We generally use a 30-period SSL to trade the new implied trends.
# 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
lookback_ma = 30
my_data = ma(my_data, lookback_ma, 1, 4)
my_data = ma(my_data, lookback_ma, 2, 5)
Creating the Strategy
The strategy is all about a full reversal to confirm a new trend and for that, we need the following strict rules:
A long (Buy) signal is generated whenever the current close is higher than the current SSL high value while the previous close is lower than the previous SSL low value.
A short (Sell) signal is generated whenever the current close is lower than the current SSL low value while the previous close is higher than the previous SSL high value.
This means that we will be detecting strong moves and assuming that they are persistent. This is of course just an assumption. Let us take a look at a sample of the results below.
def signal(data, close, ma_column_high, ma_column_low, buy, sell):
data = adder(data, 10)
for i in range(len(data)):
if data[i, close] > data[i, ma_column_high] and data[i - 1, close] < data[i - 1, ma_column_low]:
data[i + 1, buy] = 1
elif data[i, close] < data[i, ma_column_low] and data[i - 1, close] > data[i - 1, ma_column_high]:
data[i + 1, sell] = -1
return data
If we perform a simple back-test on the EURUSD, we will find the following results:
These are not very impressive results. The below is the latest signal chart that represents them.
What if we reverse the strategy and turn it into a reversal one that exploits strong moves to fade them? The new trading rules will be as follows:
A long (Buy) signal is generated whenever the current close is lower than the current SSL low value while the previous close is higher than the previous SSL high value.
A short (Sell) signal is generated whenever the current close is higher than the current SSL high value while the previous close is lower than the previous SSL low value.
We can clearly see a huge improvement when we use this strategy in reverse. This is why we should not be contained with theoretical rules. Obviously, this is not a profitable strategy yet because it is lacking many pillars of a solid strategy such as risk management and transaction costs, but it is better than the original version.
def signal(data, close, ma_column_high, ma_column_low, buy, sell):
data = adder(data, 10)
for i in range(len(data)):
if data[i, close] > data[i, ma_column_high] and data[i - 1, close] < data[i - 1, ma_column_low]:
data[i + 1, sell] = -1
elif data[i, close] < data[i, ma_column_low] and data[i - 1, close] > data[i - 1, ma_column_high]:
data[i + 1, buy] = 1
return data
If you are also interested by more technical indicators and strategies, then my book might interest you:
Conclusion
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 specific Back-testing results should lead the reader to explore more herself the strategy and work on it more.
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.