After checking that the predictive performance of our convolutional neural network was acceptably good we realized that these predictions were not providing much in terms of real returns when predicting the direction of a single stock. Let´s simulate what happens when we add more symbols to the simulation.
With this loop we can easily subscribe to information for additional symbols using Quantconnect´s algorithmic trading framework. Our opinion is that this algorithm framework makes an excellent use of systems engineering concepts and has a lot of potential for generating efficiencies algorithmic and automated trading development. The loop is basically fixing the symbols for Apple, UnitedHealthGroup, Home Depot, Merck&Co and The Coca-cola Company in the universe.
symbols = ["AAPL", "UNH", "HD", "MRK", "KO"]
for symbol in symbols:
self.AddEquity(symbol, Resolution.Minute)
These symbols have been selected without much analysis, we just want to check how our prediction model performs with more opportunities to buy or sell. The selection algorithm has been just: "take the top DOW30 N tickers by volume". This will not mask our results too much as our model looks at intraday effects to generate buy (long) or sell (short) signals. If we were to simulate a long-only, long-term strategy, picking up these top companies would introduce a great amount of bias, by selecting universes manually we tend to test our strategies with companies that have been historically successful, we are contaminating our back-tests with information from the future and ultimately extracting incorrect conclusions regarding the future.
Another algorithm design choice we are initially making is to train the convolutional network model for each of the ticker companies with its own daily data, we train KO with KO data, AAPL with APPL and so on. We are assuming here, maybe incorrectly, that each company exhibits a different daily trading pattern. This will be our initial multi-ticker model in which we will have thus multiple models: one for each ticker. The simplest way to store them is with a python dictionary:
class CnnVisualPredictionAlphaModel(AlphaModel):
def __init__(self):
# Initiate first day of operation.
self.has_started = False
self.opening_prices = {}
self.price_differences = {}
#Flag for the first training ever:
self.trained = False
#Machine Learning values:
self.features = 15
self.prediction_cut = 360
self.slack = 3
self.min_confidence = 0.7
self.image_size = (self.features, self.prediction_cut)
self.cnn_model = Sequential()
self.categorical_encoding ={}
#Dictionary to hold trained models:
self.models = {}
self.categorical_encodings = {}
Here the self.models = {} will hold the individual trained models with a key-value pair of ticker - model. We also generate here a self.categorical_encodings dictionary to hold separately the results of encoding the "bullish" (True) and the "bearish" (False) labels automatically generated for each of the individual ticker models. The model was briefly described in this post .
Running the back-test from 2015-1-1 until today yields the following equity results:
Not good. The model operates for 5 years and losses 8.4% of its equity. We are retraining the model with the previous 5 years of data every year, so that using stale information is not considered a problem and the good performance at the end of the test is probably more linked to the COVID19 crisis extreme market movements. Also, our trading fees are eating all of our profits, the algorithm would manage to break-even in the absence of these fees, but running a simulation with zero fees is completely misleading and useless.
The alpha signals (the buy or sell signals) do not yield any conclusive data either:
The signal that the prediction model generates is right 50% of the time, it favors short positions (0.72 Long-Short Ratio) and is able to barely break even with a mean value per insight of $18 dollars; that is, the value of the signal results themselves, with no slippage or fees factored in. So we will be paying more than $41000 in fees to generate $7818 in correct predictions.
At this point our hypothesis for the lack of good positive returns is that the prediction model can predict very easily those days that the stock price will close above or below its open price but it is very difficult to make profitable use of the difference from 15:30 (our prediction time) to market close.
We will use a different approach to test our main assumption in this post: that stocks behave similarly inside a given day and a predictive power exists trying to predict, for example, KO close prices with a model trained with AAPL price-volume data. The modification to our algorithm is simple and inelegant, we will have a single model entry in our self.models dictionary that we will access for training and for prediction. This model will be trained with 5 years of data for all 5 stocks in the universe. This yields 5,500 day 2D images.
The results for the same back-test using this approach are these:
The results are a little bit worse; the model is unable to remain profitable in this current incarnation. At this point, and with these insights in mind, we can discard the model with its current prediction target model. It seems that there is predictive information in bulk price and volume information when represented as a 2D image but it is difficult to transform it into a profitable strategy, at least for stocks and in the short timeframe that it is able to predict currently. In the future we will make use of and extend this approach with modified training and prediction data in such a way that movements for larger time frames can be predicted.
We will keep our readers posted on these 2D convolutional models even if our next publication series show different algorithm models that are indeed profitable.
For the time being, if you have financial markets research, modelling, testing or live trading deployment needs you can contact us here.
Comments