Algorithmic Trading Models - Cumulative Sums Filter
In the sixth article of this series, we will continue to summarise a collection of commonly used technical analysis trading models that will steadily increase in mathematical and computational complexity. Typically, these models are likely to be most effective around fluctuating or periodic instruments, such as forex pairs or commodities, which is what I have backtested them on. The aim behind each of these models is that they should be objective and systematic i.e. we should be able to translate them into a trading bot that will check some conditions at the start of each time period and make a decision if a buy or sell order should be posted or whether an already open trade should be closed.
Please note that not all of these trading models are successful. In fact, a large number of them were unsuccessful. This summaries series has the sole objective of describing the theory behind different types of trading models and is not financial advice as to how you should trade.
This article will continue our investigation into building algorithmic trading models and in the following paragraphs, I will detail the CUSUM filter, which uses cumulative sums of price or returns in order to detect whether the mean value of our time series has changed. Mean reversion is a common topic in financial analysis and many models are built on the premise that data will eventually return to its average values after it has deviated for a period of time or specified distance. Typically, these strategies find success when markets are ranging, but when they’re trending, we need a different approach.
One of the most common ways of running a mean reversion strategy is through the use of Bollinger Bands. This strategy plots 3 lines, a 20 period moving average and the moving average +/- 2 standard deviations of the previous 20 values. The bands therefore will widen as prices become more volatile and constrict as prices become more stable. The period from June 2019 to March 2020 in the above USDCAD chart displays a ranging period. The Bollinger Bands are constricted and we can see where there is potential for a mean reversion strategy. When the value of the FX rate hits the top Bollinger Band, we would look to sell and vice versa when the rate hits the lower band.
The following time period visually explains the need for an alternate strategy, as the rate begins to trend and our mean reversion strategy breaks down. The rate consistently breaks through the top band. As you can see, a new mean value is reached and we need to re-assess our method for how we read the market.
In order to recognise when our market is trending, we will set a threshold, with which we will place a buy or sell if our cumulative differences break through that threshold. It’s similar to the Bollinger Bands, but in this case we’re looking specifically for a break through, rather than a reversal. We’re trying to catch a trend as close to the source as possible, and ride the momentum until we decide to close.
We will start by calculating price differences. This is followed by cycling through the dataset and creating two columns, one for the cumulative positive values and another for the cumulative negative values. At each iteration, when in the positive list, we will assign the value of each row to be the maximum of (0, positive_sum[i-1] + diff[i]).
Let’s break this down a little further. At every time period, we will calculate the difference between the current closing price and that at the end of the previous time period. If this is positive, we will add this to the cumulative sums of prices from the previous time period. If this value is negative to the extent that it takes our cumulative sums below 0, then we assign the column value to 0. This is the minimum that we let our positive runs reach and essentially denotes our momentum “going back to square one” since the momentum has been lost. This helps us to differentiate between ranging and trending markets. If the market is ranging, when it starts to reverse our CUSUM model will reset.
We repeat the same process with our negative values, but this time we take min(0, negative_sum[i-1] + diff[i]). The principle here is the same, we’re looking for a sustained period of movement in one direction so that we can classify a market as trending.
Once we have these values, we set our threshold. This will take some fine tuning and because different markets move at different rates, there’s no hard and fast rule for the threshold you set. A visual measure is best here, you can try playing with different values and see the accuracy of the signals. In the results below, I’ve included copies of the signals with thresholds of 0.1 and 0.05 using the USDCAD prices. Signals are generated when either the positive_sum variable crosses above the positive threshold or the negative_sum variable crosses below the negative threshold. The code for generating the dates of the signals is adapted from Advances in Financial Machine Learning (2018) and presented below.
#Dataset should have columns [‘Date’,’Close’]
posDates,negDates = ,
pos_sum,neg_sum = 0,0
dataset[‘Differences’] = dataset[‘Close’].diff()
for i,r in diff[1:].iterrows():
pos_sum = max(0,pos_sum + r[‘Difference’])
neg_sum = min(0, neg_sum + r[‘Difference’])
if pos_sum > threshold:
pos_sum = 0 #Reset
elif neg_sum < -h:
neg_sum = 0 #Reset
I ran this model on both raw price and returns data. In this article I will present the raw price signals and will publish another article soon displaying the returns data. This is because there is a slight adaptation to this model that we need to include for returns data that I will explain in more detail in that article. I think the understanding of the fundamentals of this algorithm is important in itself before we discuss adaptations.
The graphs below shows buy and sell signals for a 0.1 threshold.
The graphs bring up some surprising conclusions. The model is naturally not perfect and we shouldn’t expect it to be, since it’s designed to be successful in a very specific type of market performance.
The 0.1 threshold seems to be a good estimate of the type of signal we’re looking for. The second graph in each of our dashboards show a snapshot during respective uptrends and downtrends. When the price is rising, our model picks this movement early enough for us to profit off. The situation is the same when looking to sell in a downtrend. To turn this into a legitimate trading strategy, we could add a few more conditions that would help identify when a time series is moving out of its ranging phase, but the initial EDA shows some promising possibilities.