Combining the Countdown Indicator With the Fibonacci Moving Averages in a Trading Strategy.

Can the Countdown Indicator and Fibonacci Moving Averages Provide Good Signals Together?

Sofien Kaabar
Apr 8 · 12 min read
www.pxfuel.com

The Countdown Indicator is a contrarian indicator that I have developed for mostly discretionary trading. In parallel, moving averages can also hint at a possible market inflection through their dynamic support/resistance levels. What if we try to combine the two together to give us a timely signal of when a reaction should occur. This means that we will use signals from the Countdown Indicator and the Fibonacci moving average. The first two parts will introduce the indicators and the third part will present the strategy. The research is as always done in Python.

If you are also interested in more technical indicators and using Python to create strategies, then my latest book may interest you:

The Fibonacci Moving Average

Moving averages help us confirm and ride the trend. They are the most known technical indicator and this is because of their simplicity and their proven track record of adding value to the analyses. We can use them to find support and resistance levels, stops and targets, and to understand the underlying trend. This versatility makes them an indispensable tool in our trading arsenal.

EURUSD hourly values with the 200-period simple moving average.

As the name suggests, this is your plain simple mean that is used everywhere in statistics and basically any other part in our lives. It is simply the total values of the observations divided by the number of observations. Mathematically speaking, it can be written down as:

We can see that the moving average is providing decent dynamic support and resistance levels from where we can place our orders in case the market goes down there. The code for the moving average can be written down as the following:

def ma(Data, lookback, what, where):

for i in range(len(Data)):
try:
Data[i, where] = (Data[i - lookback + 1:i + 1, what].mean())

except IndexError:
pass
return Data

To use it, we need to have an OHLC data array with an extra empty column. This can be done by using the following code:

# Defining the function that adds 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# Adding 1 extra column
my_data = adder(my_data, 1)
# Calling the moving average function
my_data = ma(my_data, 200, 3, 4)

The above states that the moving average function will be called on the array named my_data for a lookback period of 200, on the column indexed at 3 (closing prices in an OHLC array). The moving average values will then be put in the column indexed at 4 which is the one we have added using the adder function.

USDCHF hourly values with the 200-period simple moving average.

Another even more dynamic moving average is the exponential one. Its idea is to give more weight to the more recent values so that it reduces the lag between the price and the average.

EURUSD hourly values with the 200-period exponential moving average.
def ema(Data, alpha, lookback, what, where):

# alpha is the smoothing factor
# window is the lookback period
# what is the column that needs to have its average calculated
# where is where to put the exponential moving average


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

From exponential moving averages, we will create the Fibonacci Moving Average. The Fibonacci sequence follows this distinct pattern:

The numbers are found by adding the previous two numbers behind them. In the case of 13, it is calculated as 8 + 5, hence the formula is:

This gives us the intuition to code it using the following code:

def Fibonacci(n):
if n == 1:
return 1

elif n == 0:
return 0

else:
return Fibonacci(n - 1) + Fibonacci(n - 2)

The below function gives us the Fibonacci number according to its index. The index is simply the order of the numbers seen in the table below.

Fibonacci Table.

Now, if we use the function and look at its results, we will understand better.

fib(14)
# Output: 377
fib(5)
# Output: 5

The Fibonacci Moving Average is an equally weighted exponential moving average using the lookbacks of selected Fibonacci numbers. Here is what I mean step by step:

  • We calculate exponential moving averages using the following lookbacks {2, 3, 5, 8, 13, 21, 34, 55, 89, 144, 233, 377, 610, 987, 1597}.
  • We divide the sum of the exponential moving averages by their number. In our case, we will divide by 15.
  • Plot the Fibonacci Moving Average alongside the market price.
EURUSD Daily data with the Fibonacci Moving Average.

The way to trade the FMA is simply by initiating a contrarian trade when markets approach it. For example, if the market is dropping and heading towards the FMA, we can think about a bullish reaction that could happen around that zone.

def fibonnaci_moving_average(Data, fib_range, what, where):

for i in range(3, fib_range):

Data = adder(Data, 1)
lookback = fib(i)
Data = ema(Data, 2, lookback, what, -1)

Data = adder(Data, 1)
for i in range(len(Data)):
Data[i, -1] = np.sum(Data[i, where:where + 15])
Data[i, -1] = Data[i, - 1] / 15

return Data
# The fib variable we will be using is 17

The Countdown Indicator

The Countdown Indicator have been created in order to include the totality of the OHLC data inside a framework that calculates when we are around an extreme and when we are bound to reverse. I have made some optimizations and finally arrived at the following ways to construct the indicator. All we need, is OHLC data. The Countdown Indicator should be used in conjunction with other technical indicators to get a better confirmation. The below are the steps used to create it with the function in Python later given so that it can be copied and pasted.

Calculate the Upside Pressure. The calculation is simply a summation of two conditions:

  • If the current close is greater than the opening price, then we have 1 point in the Upside Pressure calculation. Next, if the current high is greater than the high from the last period, we have another point. At its maximum, the Upside Pressure can only have 2 points while at its minimum, it can have zero points. If the current close is greater than the open while the current high is lower than the previous high, the Upside Pressure should have 1 point.

Calculate the Downside Pressure. The calculation is simply a summation of two conditions:

  • If the current close is lower than the opening price, then we have 1 point in the Downside Pressure calculation. Next, if the current low is lower than the low from the last period, we have another point. At its maximum, the Downside Pressure can only have 2 points while at its minimum, it can have zero points. If the current close is lower than the open while the current low is higher than the previous low, the Downside Pressure should have 1 point.

Calculate the 8-period Cumulative Upside and Downside pressures. This is a simple summation of the last 8 pressures including the current one:

Next, the Countdown Indicator (Raw form) is simply the difference between the Cumulative Upside Pressure and the Cumulative Downside Pressure which then we can simply calculate a 3-period Exponential Moving Average on:

EURUSD with the 8-period Countdown Indicator in the second panel.

To code the Indicator, we need to have an OHLC array (not a data frame) and define the following three small manipulation functions:

# 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

Now we are ready to code the Countdown Indicator:

def countdown_indicator(Data, lookback, ma_lookback, opening, high, low, close, where):

# Adding columns
Data = adder(Data, 20)

# Calculating Upside Pressure
for i in range(len(Data)):

if Data[i, close] > Data[i, opening]:

Data[i, where] = 1if Data[i, high] > Data[i - 1, high]:

Data[i, where + 1] = 1

Data[:, where + 2] = Data[:, where] + Data[:, where + 1]
Data = deleter(Data, where, 2)

# Calculating Downside Pressure
for i in range(len(Data)):

if Data[i, close] < Data[i, opening]:

Data[i, where + 1] = 1if Data[i, low] < Data[i - 1, low]:

Data[i, where + 2] = 1

Data[:, where + 3] = Data[:, where + 1] + Data[:, where + 2]
Data = deleter(Data, where + 1, 2)

# Calculate Cumulative Upside Pressure
for i in range(len(Data)):

Data[i, where + 2] = Data[i - lookback + 1:i + 1, where].sum()

# Calculate Cumulative Downside Pressure
for i in range(len(Data)):

Data[i, where + 3] = Data[i - lookback + 1:i + 1, where + 1].sum()

# Calculate the Countdown Indicator
Data[:, where + 4] = Data[:, where + 2] - Data[:, where + 3]
Data = ema(Data, 2, ma_lookback, where + 4, where + 5)

Data = deleter(Data, where, 5)
Data = jump(Data, lookback)

return Data
# Using the Function
my_data = countdown_indicator(my_data, lookback, ma_lookback, 0, 1, 2, 3, 4)
USDCHF with the 8-period Countdown Indicator in the second panel.

If you are interested by market sentiment and how to model the positioning of institutional traders, feel free to have a look at the below article:

Creating the Combined Strategy

Combining indicators and techniques is the first step towards a robust trading system as getting a confluence of signals around a time period reinforces the conviction. There are many ways to create such structured strategies namely, scorecards, indices, and simultaneous conditions. The strategy we will be discussing will revolve around the simultaneous conditions and it is when certain conditions are met at the same time thus giving us a trading trigger.

EURUSD in the first panel with the Fibonacci moving average and the Countdown Indicator in the second panel.

The above plot shows the EURUSD with the Fibonacci Moving Average alongside the 8-period Countdown Indicator. We want to see whether if we have an asset that is close to its moving average with a Countdown Indicator that is also at an extreme, can we profitably exploit it? The conditions are therefore clear:

  • Go long (Buy) whenever the Countdown Indicator reaches or breaks -5. Similarly, the market price must be above and close to the Fibonacci Moving Average. The closeness can be measured by the distance variable described below. Hold this position until getting another signal or getting stopped out by the risk management system.
  • Go short (Sell) whenever the Countdown Indicator reaches or surpasses 5. Similarly, the market price must be below and close to the Fibonacci Moving Average. Hold this position until getting another signal or getting stopped out by the risk management system.
EURUSD signal chart following the strategy.
distance = 0.0015def signal(Data, close, countdown_col, fibonacci_ma, buy, sell):

for i in range(len(Data)):

if Data[i, countdown_col] < lower_barrier and Data[i, close] > Data[i, fibonacci_ma] and (Data[i, close] - Data[i, fibonacci_ma]) < distance:
Data[i, buy] = 1

if Data[i, countdown_col] > upper_barrier and Data[i, close] < Data[i, fibonacci_ma] and (Data[i, fibonacci_ma] - Data[i, close]) < distance:
Data[i, sell] = -1
USDCHF signal chart following the strategy.

It looks like the signals are quite rare on the above USDCHF plot but luckily, both were of high quality.

GBPUSD signal chart following the strategy.

As I have mentioned above, the strategy is more discretionary than systematic and hence, I recommend using it while manually doing the trading as systematically, it is a little bit complicated to optimize it. Personally, I look at it for confirmation. As I prefer to trade reactions (short moves), this strategy combines timing with strong movements which is basically what I need.

If you are interested by technical indicators, feel free to have a look at the below article:

Conclusion

If you regularly follow my articles, you will find that many of the indicators I develop or optimize have a high hit ratio and on average are profitable. This is mostly due to the risk management method I use. But what about market randomness and the fact that many underperformers blaming Technical Analysis for their failure?

First of all, I constantly publish my trading logs on Twitter before initiation and after initiation to show the results. This ensures transparency. I also publish a track record on Twitter every 1–3 months. However, I never guarantee a return nor superior skill whatsoever. As for the indicators that I develop, I constantly use them in my personal trading. Hence, I have no motive to publish biased research. My goal is to share back what I have learnt from the online community.

Remember to always do your back-tests. Even though I supply the indicator’s function (as opposed to just brag about it and say it is the holy grail and its function is a secret), you should always believe that other people are wrong. My indicators and style of trading works for me but maybe not for everybody. I rely on this rule:

The market price cannot be predicted or is very hard to be predicted more than 50% of the time. But market reactions can be predicted.

What the above quote means is that we can form a small zone around an area and say with some degree of confidence that the market price will show a reaction around that area. But we cannot really say that it will go down 4% from there, then test it again, and breakout on the third attempt to go to $103.85. The error term becomes exponentially higher because we are predicting over predictions.

While we are discussing this topic, I should point out a few things about my back-tests and articles:

  • The spread I use is based on institutional quotes of a small pip fraction. Generally, retail traders are given a whopping spread of 1–2 pips per trade. This is huge and unfair to them. I use 0.2–0.5 spread. However, most of the strategies that use the hourly time frame still work with 1 pip spread. For the ones that use M15 or M5 time frames, they cannot be profitable with a spread of 1 pip.
  • The holding period calculation I use is close-to-close in case there is no risk management process.
  • Although I discourage trading based on just one indicator, the numbers do not lie. What I am presenting is what could have happened when taking into account a low spread.
  • Some of the back-tests I provide are losers and they are published either to demystify a trading myth or to present interesting functions to be coded by readers.
  • Finally, I am a firm believer of not spoon-feeding the learners. 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 it and improve it before deciding to take it live or to eliminate it.

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.

Geek Culture

Proud to geek out.

Sign up for Geek Culture Hits

By Geek Culture

Subscribe to receive top 10 most read stories of Geek Culture — delivered straight into your inbox, once a week. Take a look.

By signing up, you will create a Medium account if you don’t already have one. Review our Privacy Policy for more information about our privacy practices.

Check your inbox
Medium sent you an email at to complete your subscription.

Sofien Kaabar

Written by

Institutional FOREX Strategist & Trader. Author of “The Book of Back-tests” https://www.amazon.com/dp/B089CWQWF8

Geek Culture

A new tech publication by Start it up (https://medium.com/swlh).

Sofien Kaabar

Written by

Institutional FOREX Strategist & Trader. Author of “The Book of Back-tests” https://www.amazon.com/dp/B089CWQWF8

Geek Culture

A new tech publication by Start it up (https://medium.com/swlh).

Medium is an open platform where 170 million readers come to find insightful and dynamic thinking. Here, expert and undiscovered voices alike dive into the heart of any topic and bring new ideas to the surface. Learn more

Follow the writers, publications, and topics that matter to you, and you’ll see them on your homepage and in your inbox. Explore

If you have a story to tell, knowledge to share, or a perspective to offer — welcome home. It’s easy and free to post your thinking on any topic. Write on Medium

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store