New to the Quant Quickstart series? Read part one and part two.
If you've made it this far, congratulations! You've successfully imported the Dow 30 from Intrinio and graphed the relative strength index for multiple stocks.
In this post, we're going to create a simple mean reversion strategy that you'll be able to build on to develop your own profitable trading strategies. We'll change our momentum and mean reversion periods to account for this.
If you're new to this series, my name is Leo Smigel, and I'm an algorithmic trader. I apply data science to traditional valuation and trading techniques to make money in the markets. If you're interested, you can learn more at Analyzing Alpha.
Before we dig into the code, let's discuss the strategy. Stocks tend to trend in the long-term and mean-revert in the short term. There's quite a bit of academic literature on this topic, which we won't cover here. If you're interested in the research, I highly recommend SSRN.
We'll create a short strategy. To implement our strategy, we'll rank the Dow 30's largest laggards using their simple moving average (SMA) over the last 50 days. The 50-period simple moving average (SMA) will be our trend indicator where we expect the stock to continue to the downside. We'll then take the top ten falling Dow stocks and rank them by the highest 10-period relative strength indicator (RSI). The 10-period RSI will show us shares that recently reached oversold conditions and moved higher. We'll sell our current positions and buy the two stocks with the highest RSI every Friday with an expectation that the stocks will continue lower.
Let's see what this looks like in code.
As we've done before, we create our class inheriting from bt.Strategy and then add our parameters. We initialize our strategy and use a dictionary to contain the SMA and RSI for each security.
add_timer is a callback to notify_timer allowing us to run code at a specified point in time. In our case, we rebalance every Friday, or the next business day if Friday isn't a trading day, based upon the params above.
notify_trade alerts us of open and closing of trades as shown below.
As often the case, rebalance is where the real magic is done.
We start by creating a list of our Dow 30 securities. We then rank the securities by the SMA using a lambda function, which is just an anonymous function that allows us to skip the formalities of defining one. We then take the top ten lagging stocks and rank them by the highest RSI.
After we've done slicing our stocks, we sell any stocks that are no longer in the top 2 ranked positions and buy the stocks that are.
If you're new to Python, this may seem daunting. The good news is that after you understand the above, you can take your trading to a whole new level.
For good measure, we'll add our previous code below. We've seen it already. It loads the Intrinio data into the system and calculates the before and after profits.
So how did we do?
When we run the program, we get a list of our trades. Remember, a trade takes two orders: one to open the trade and one to close it.
It looks like we increased our portfolio value by 25% over the period. Not bad! Obviously, you would need to do more research to see if this strategy was effective over different time periods.
In the next post, we'll switch gears and add fundamentals to our strategy. If you're ambitious, create a fundamentals database before next month. As always, the code for this post is on GitHub.
New to Intrinio? Visit intrinio.com to learn more.