Predict Stock-Market Behavior using Markov Chains and R
Practical walkthroughs on machine learning, data exploration and finding insight.
Past Performance is no Guarantee of Future Results
If you want to experiment whether the stock market is influence by previous market events, then a Markov model is a perfect experimental tool.
We’ll be using Pranab Ghosh’s methodology described in Customer Conversion Prediction with Markov Chain Classifier. Even though he applies it to customer conversion and I apply it to the stock market, the point is that it doesn’t matter where it comes from as long as you can collect enough sequences, even of varying lengths, to find patterns in past behavior.
Some notes: this is just my interpretation using the R language as Pranab uses pseudo code along with a Github repository with Java examples. I hope a am at least capturing his high-level vision as I did take plenty of low-level programming liberties. And, for my fine print, this is only for entertainment and shouldn’t be construed as financial nor trading advice.
Cataloging Patterns Using S&P 500 Market Data
In its raw form, 10 years of S&P 500 index data represents only one sequence of many events leading to the last quoted price. In order to get more sequences and, more importantly, get a better understanding of the market’s behavior, we need to break up the data into many samples of sequences leading to different price patterns. This way we can build a fairly rich catalog of market behaviors and attempt to match them with future patterns to predict future outcomes. For example, below are three sets of consecutive S&P 500 price closes. They represent different periods and contain varying amounts of prices. Think of each of these sequences as a pattern leading to a final price expression. Let’s look at some examples:
2012-10-18 to 2012-11-21
1417.26 –> 1428.39 –> 1394.53 –> 1377.51 –> Next Day Volume Up
2016-08-12 to 2016-08-22
2184.05 –> 2190.15 –> 2178.15 –> 2182.22 –> 2187.02 –> Next Day Volume Up
2014-04-04 to 2014-04-10
1865.09 –> 1845.04 –> Next Day Volume Down
Take the last example, imagine that past three days of the current market match historical behaviors of day 1, 2 and 3. You now have a pattern that matches current market conditions and can use the future price (day 4) as an indicator for tomorrow’s market direction (i.e. market going down). This obviously isn’t using any of Markov’s ideas and is just predicting future behavior on the basis of an up-down-up market pattern.
If you collect thousands and thousands of these sequences, you can build a rich catalog of S&P 500 market behavior. We won’t just compare the closing prices, we’ll also compare the day’s open versus the day’s close, the previous day’s high to the current high, the previous day’s low to the current low, the previous day’s volume to the current one, etc (this will become clearer as we work through the code).
Binning Values Into 3 Buckets
An important twist in Pranab Ghosh’s approach is to simplify each event within a sequence into a single feature. He splits the value into 3 groups - Low, Medium, High. The simplification of the event into three bins will facilitate the subsequent matching between other sequence events and, hopefully, capture the story so it can be used to predict future behavior.
To better generalize stock market data, for example, we can collect the percent difference between one day’s price and the previous day’s. Once we have collected all of them, we can bin them into three groups of equal frequency using the InfoTheo package. The small group is assigned ‘L’, the medium group, ‘M’ and the large, ‘H’.
Here are 6 percentage differences between one close and the previous one:
-0.00061281019 -0.00285190466 0.00266118835 0.00232492640 0.00530862595 0.00512213970
Using equal-frequency binning we can translate the above numbers into:
"M" "L" "M" "M" "H" "H"
Combining Event Features into a Single Event Feature
You then paste all the features for a particular event into a single feature. If we are looking at the percentage difference between closes, opens, highs, lows, we’ll end up with a feature containing four letters. Each representing the bin for that particular feature:
Then we string all the feature events for the sequence and end up with something like this along with the observed outcome:
"HMLL" "MHHL" "LLLH" "HMMM" "HHHL" "HHHH" --> Volume Up
Creating Two Markov Chains, One for Days with Volume Jumps, and another for Volume Drops
Another twist in Pranab Ghosh’s approach is to separate sequences of events into separate data sets based on the outcome. As we are predicting volume changes, one data set will contain sequences of volume increases and another, decreases. This enables each data set to offer a probability of a directional volume move and the largest probability, wins.
Manuel Amunategui - Follow me on Twitter: @amunategui