IS643 Quantitative Finance - Project 3 - Kalman Filtering

What is Kalman Filtering?

"A Kalman filter is a computational algorithm that processes measurements to deduce an optimum estimate of the past, present, or future state of a linear system by using a time sequence of measurements of the system behavior, plus a statistical model that characterizes the system and measurement errors, plus initial condition information." - from here.

Basically, this is a set of equations that can help estimate the next value of a time series of measurements of a system. While mainly used in time series analysis, and useful in keep track of trajectories of moving objects. For this project, we will use them to help predict tomorrow's value of a stock based on information on prices we have seen in the past.

Outline of Algorithm

The algorithm I came up with is similar to the previous projects. Given a portfolio of stocks, we are going to train a model for each one. I do this so we can customize the models to each stock. For a given stock, we'll grab a certain amount of historical data plus today's price, and run it through the filter. When that is done, we can cread the filter's prediction of what the next value would be. From this prediction we will make an order, either long or short, and check the status of this order on the next day. In this case, I also keep track of well we are doing (i.e., if these predictions are turning out to be true or not) and plot it on the graph.

Implementations

Algorithm 1 - First Kalman Filter Implementation

Quantopian Link

For my first implementation, I used code from this SciPy link and modified it for my purposes. The KalmaFilter class takes in at least one parameter, which is the number of input vectors we will run through the filter. The constructor does take some other Kalman related parameters, which can be tweaked per stock:


In [ ]:
# Parameters for each kalman  filter
context.params = { stock:{ "init_xhat": 0.0, 
                            "init_P": 1.0, 
                            "Q": 1e-5, 
                            "R": 0.1**2, 
                            "orderSize": 5000, 
                            "percentChange": 0.02} for stock in context.stocks }

This implementation follows the outline above. First, we handle the transaction from the previous day, if there was any. The transaction details are stored in a dictionary called context.order_info, keyed by the stock object. The transaction object is populated whenever we make an order, which looks like this when we predict an upward movement:


In [ ]:
context.order_info[stock] = {"predict": "up", 
                             "price": data[stock].price,
                             "orderSize": context.params[stock]["orderSize"]}

After doing that, we want to make a prediction for the next day using a Kalman filter. While working on this, I noticed that a single Kalman filter did not perform very well. Very often, I could not get past 50% accuracy (which would just be guessing) and the algorithm would show pretty bad gains. This is why I tried to implement something like Ensemble Learning: despite the fact that this is not really a supervised learning algorithm, I decided to setup multiple Kalman filters, only differeing in how much of the historical input to give it. For example, you can have three Kalman filters for one stock, each one processed over 7, 14 and 30 days worth of historical data, respectively. We can then take a vote on whether or not we think there will be an increase or decrease in price.

Though this seemed to help, I noticed two things:

  • Using a shorter number of days for the filter seemed to give better results than a longer number of days. This maybe points to the Kalman filter code not reproducing the right 'state transitions' for this problem
  • More often than not, the filter(s) would start off well but eventually would devolve to around 50% accuracy. This gives me some concern and why I tired another Kalman implementtion below

However, with some finagling, I did get some decent results from this algorithm, as shown here:


In [1]:
from IPython.display import Image
Image(filename='part3/Algo1.png', height="90%", width="90%")


Out[1]:

For the shown output, I am only trading 3 stocks. However, despite the decent gains, at some point we do not make any more gains despite waiting for a long time. For example, the return rate peaks somewhere mid-2013 and stays steady. This is not good, and I am not sure why this is the case: the filter supposedly shows >50% accuracy, but depsite that, we cannot seem to get anymore gains. This seems to be steady throughout all stocks I tested. This might mean that the dynamics of this specific Kalman filter implementation start off corrcet but over sime time, no longer reflect reality. I think a better / different imeplmentation of the filter might resolve this (see discussion here).

Algortihm 2 - Kalman Filter from Package

Quantopian Link

I edited the previous algorithm and replaced the custom implementation with an implementation from the pykalman module. The code that does the prediction step was inferred from the documentation but may not be correct. I did not see significant differences with this implementation, outside of the fact that this implementation seems less sensitive to the percent change.

In an effort to quell some of the bad bets made in the beginning of backtesting (which is due to a high volatility moment in the prices of the underlying stock), I implemented Stop Loss ordering. As discussed below, this gives us positive gain but the results still do not look good.

Here are the results without Stop Loss ordering:


In [3]:
Image(filename='part3/Algo2-NoStopLoss.png', height="90%", width="90%")


Out[3]:

Here are the results with Stop Loss ordering:


In [4]:
Image(filename='part3/Algo2-StopLoss.png', height="90%", width="90%")


Out[4]:

Results

The results from this project were not great. I could not get the first Kalman filter to get me an accuracy that was significantly better than 50%, and the second filter does not seem much better. The only way I could get any gains was by trying out Stop Loss ordering (which is controlled by a flag in the second algo), but the gains were so rediculous (with poor alpha and beta values) that I would not consider this for a real algorithm.

Fundamentally, I think Kalman filters are not a good idea without a good idea of what the state transition matrix is suppose to be. In the research online on kalman filters, many talk about how to derive this matrix from a base mathematical model of whatever phenomenon is being tracked. The first kalman filter implementation did not have a way of setting this matrix, so I assume the equations really model physical motion; the same goes for the pykalman module: without passing in the state matrix to the constructor, the default that it is using may not be a good fit for the job.

Future

  • Find a way to look at past data and derive state transition matrix?
  • Try 'Unscented' versions of the Kalman filter, which allow for arbitrary (non-linear) dynamics

In [ ]: