Machine-learning algorithms can be used to build robust trading strategies.

In a previous post we explored how we can use a Naive Bayes classifier to predict the direction of Apple stock. While the Naive Bayes is a powerful algorithm, it tends to be a “black-box”, meaning it is difficult to understand what’s going on inside. Additionally, in order to use it to trade, you must have the ability to feed it live rates and be able to make a prediction and enter a trade in a timely fashion. This creates added layers of complexity before you are able to use these types of algorithms in your own trading.

We need a way to leverage the capabilities of our Naive Bayes classifier while still being able to understand the strategy and then easily apply it to our current trading method.

The answer comes from a lesser known, but well researched, subset of data mining known as association rule learning.

In this post we will briefly explain the concepts behind association rule learning and use it to build a basic strategy for the USD/CAD.

What is Association Rule Learning?

Association rule learning is one of the six subsets of data mining (you can learn more about how data mining, machine learning, and Big Data all fit in here). It can be broadly defined as the technique to find associations between variables. It uses different types of algorithms to construct high-confidence “if...then….” statements relating the variables in your data. The classic example comes from placing items on the supermarket floor. Supermarkets analyze their data and are able to find relationships between products purchased together; “if a customer buys milk and eggs, then they are likely to also buy bread.” This allows the store manager to place those items close together to make the customer’s life easier and hopefully increase sales.

There are some popular algorithms that are used for association rule learning, like the Apriori algorithm, that search huge databases and find the items sets that produce high-confidence association rules. Since the number of potential “items”, or in our case “indicators”, is huge (a virtually limitless span of technical, fundamental, and sentimental inputs), we will use a predefined set of technical indicators and an algorithm we are already familiar with to construct a set of rules we can then easily use in our own trading.

Building a Strategy Using Association Rule Learning

Now that we have a basic understanding of association rule learning, let’s see how we can use it to turn our black-box, machine-learning algorithm into a set of clear, objective rules we can apply to our own strategy.

We will begin by gathering the data we need, the USD/CAD 4h rates spanning from October 23, 2011 until September 22, 2014. (These were downloaded from FXCM’s TradeStation, please don’t hesitate to reach out if you would like this dataset to play around with it yourself).

Then we will install the libraries we will need:

install.packages("quantmod")

library(quantmod)

#Gives us access to the technical indicators we need

install.packages("e1071")

library(e1071)

#Includes the Naive Bayes classifier

install.packages("ggplot2")

library(ggplot2)

#The charting functions we will use

And calculate the indicators we will use:

Data #Our dataset

CCI20 #A 20-period Commodity Channel Index calculated of the High/Low/Close of our data

Note: since the CCI is calculated off the close, we will calculate our other indicators off the close as well and shift back their values from the direction of the next bar to prevent data snooping.

RSI3 #A 3-period RSI calculated off the close

DEMA10 DEMA10c #A 10-period Double Exponential Moving Average (DEMA), with standard parameters. And we will be looking at the difference between the price and the DEMA.

DEMA10c #Convert into pips

Then create our dataset, round the indicator values, and shift the values:

Indicators Indicators Indicators #Removing the most recent data point for calculating the indicators, and lining it up with the direction of that bar effectively shifts our indicator calculations back by one and prevents us from accessing information we couldn’t know. Next let’s calculate the variable we are looking to predict, the direction of the next bar, and create our final data set. Price Class 0 ,"UP","DOWN") Class #Remove the oldest data point to match up our predicted Class with the indicators. DataSet DataSet #Remove the instances where the indicators are still being calculated. Training #Separate into a training set (60% of the data), test set (20% of the data), and validation set (20% of the data). Finally, let’s build our Naive Bayes classifier: NB #Using our three technical indicators to predict the class off the training set Let’s see how well the algorithm did on its own to establish a baseline. table(predict(NB,Test,type="class"),Test[,4],dnn=list('predicted','actual')) About 52%, not bad but let’s see if we can do better. TestPredictions #Get a list of all our predictions TestCorrect #See if these predictions are correct TestData #Build one data set we can use for all of our plots Okay, let’s see what patterns our algorithm was able to pick up over the training set and how well those patterns held up over the test set. The plots on the left (“Predictions over Training Set”) show where the Naive Bayes algorithm predicted long vs. short over the entire range of our indicator’s values (x-axis). Green is where the algorithm predicted long and orange is where the algorithm predicted short. This allows to see where the algorithm found the strongest long and short signals. The plots on the right (“Accuracy over Test Set”) show where the algorithm was most accurate across those same indicator values over the test set. Blue is where the algorithm was correct and red is where the algorithm was incorrect over the indicator values (x-axis). This shows us where the patterns best held up over out-of-sample testing. It is always important to test over data the algorithm hasn’t seen to evaluate where it was most accurate. **Hover over the pictures to enlarge them. Sorry mobile users.

Predictions over Training Set Accuracy over Test Set

Example code for producing these plots:

Training Predictions:

ggplot(TrainingData,aes(x=CCI20,fill=TrainingPredictions))+geom_histogram(binwidth=15,position="fill")+labs(title="Training Predictions: CCI", x = "20-Period CCI", y= "Up/Down Ratio",fill="Predictions")+scale_fill_manual(values=c("#FF6737","#00B204"))

Test Accuracy:

ggplot(TestData,aes(x=RSI3,fill=TestCorrect))+geom_histogram(binwidth=5,position="fill")+labs(title="Test Accuracy: RSI", x = "3-Period RSI", y= "Correct/Incorrect Ratio",fill="Accuracy")+scale_fill_manual(values=c("#0066FF","#FF4747"))

Constructing Your Rules

Great! We have the patterns that our algorithm was able to find in our indicators and how well those patterns held up over new data.

What we want to do now is find the indicator values where 1) the algorithm found a strong buy or sell signal and 2) where the algorithm was more accurate. This will allow us to isolate the values for each indicator where there were both a strong signal and an accurate one. These indicator values then form our rules.

For example, looking at the 20-period CCI, we see that when the indicator value was between -100 and -290, the algorithm found both a strong buy signal and was very accurate. This shows us that this range of indicators should be one of the rules in our long strategy.

The indicator values, and subsequent rules, are highlighted in light blue for long trades and yellow for short trades.

*Note: many machine-learning algorithms are very good at picking up relationships between indicators. For example, it might find that when the CCI is below -200 AND the RSI is below 25, it’s actually a very strong sell signal. However, the Naive Bayes is not one of these algorithms. The term “Naive” actually refers to this, as the algorithm makes the naive assumption that each input is completely independent from the others. So we are analyzing each indicator on its own.

First, we will find the areas where we were able to find strong buy or sell signals. The indicator values, and subsequent rules, are highlighted in light blue for long signals and yellow for short signals. Then, we will find the areas where the algorithm was accurate and it was within the strong buy or sell ranges. Again, the indicator values, and subsequent rules, are highlighted in light blue for long signals and yellow for short signals.

Predictions over Training Set Accuracy over Test Set

We can then write out the indicator values we isolated into both long and short rules.

Long Rules Short Rules IF The CCI20 is above -290 and below -100 AND



The RSI3 is below 30 AND



The DEMA10cross is above -40 and below -20



THEN Long Signal IF The CCI20 is above 185 and below 325 AND



The RSI3 is above 50 AND



The DEMA10cross is above 10 and below 40



THEN Short Signal

Which we then need to test over our validation set:

Long -290 & Validation$CCI < -100 & Validation$DEMA10c > -40 & Validation$DEMA10c < -20)

#Isolating the trades

LongTrades #Creating a dataset of those trades

LongAcc #Testing the accuracy

(sum(LongAcc)/length(LongAcc))*100

#And our long accuracy

Short 10 & Validation$DEMA10c < 40 & Validation$CCI > 185 & Validation$CCI < 325 & Validation$RSI3 > 50)