# Category Backtesting a mean reversion strategy in python

### Backtesting a mean reversion strategy in python

Hi all, welcome back. Once we have the script working for a single input of one pair of symbols, we can very easily adapt it at the end to work with the symbol pairs function created previously.

Use the hedge ratio to generate the spread between the two prices, and then plot this to see if it looks in any way mean reverting. We will also calculate the Hurst exponent of the spread series. It looks like the prices are definitely correlated to a degree, and generally move in the same direction.

But just how strong is this correlation?

Mean reversion strategies on Streak

We can see from the information provided in the jointplot that the Pearson Correlation coefficient is 0. This sets the pair up as a potentially good fit for a mean reversion strategy. What we need to do now is create the spread series between the two prices by first running a linear regression analysis between the two price series.

Right so we have now managed to run the regression between the ETF price series; the beta coefficient from this regression was then used as the hedge ratio to create the spread series of the two prices. So it looks relatively mean reverting.

But sometimes looks can be deceiving, so really it would be great if we could run some statistical tests on the spread series to get a better idea.

The test we will be using is the Augmented Dickey Fuller test. You can have a quick read up about it here if you need to refresh your memory:.

From this we can see that the test statistic of The p-value of 0. The last thing we will do is run a quick function to calculate the Hurst exponent of the spread series. For info on the Hurst Exponent please refer to: this article. To simplify things, the important info to remember here is that a time series can be characterised in the following manner with regard to the Hurst exponent H :.

The Hurst Exponent is under the 0. This means that the spread series looks like a definite candidate for a mean reversion strategy, what with the spread series being mean reverting and all.The entries here are contributed by software developers or programmers for software that is capable of customization. To quantify this, he uses the classic z-score calculation. In addition, he adds a component to evaluate the existing trend as well as position sizing to allow for reinvestment.

Wealth-Lab owes to C the power of extensibility and ability to express trading rules of any complexity. Here is an example of creating a mean-reversion strategy using the rules wizard.

Those of you who prefer C to take complete control will find a sample strategy code listing here. Here are some characteristic trades on a daily chart of Coca-Cola data provided by Yahoo. The code to test the system in MetaStock is provided here. This shows the strategy added to a daily chart of SPY for the timeframe beginning in until the middle of March NinjaScript uses compiled DLLs that run native, not interpreted, to provide you with the highest performance possible.

If you choose to use pyramiding or slippage, those can be set up in the trading parameters dialog as well. After entering the system conditions, you can also choose whether the parameters should be genetically optimized. After backtesting the trading strategy, use the detailed analysis button to view the backtest and trade-by-trade statistics for the system. Then click the start button. When prompted to upgrade, click the yes button. If prompted to close all software, click on the continue button.

Your library will now download. This prebuilt strategy can be overlaid onto your chart by opening the charting dropdown menu, selecting the add to chart command, then selecting the strategies tab. If you have any difficulty importing the library or using the strategy, users may contact our technical support staff by phone or by live chat.You will learn what mean reversion is, how to trade it, 10 steps for building a system and a complete example of a mean reversion system.

A mean reversion trading strategy involves betting that prices will revert back towards the mean or average. Markets are forever moving in and out of phases of mean reversion and momentum. A simplistic example of a mean reversion strategy is to buy a stock after it has had an unusually large fall in price.

The idea of mean reversion is rooted in a well known concept called regression to the mean. This is a theory first observed by statistician Francis Galton and it explains how extreme events are usually followed by more normal events. The way to apply this strategy in the market is to seek out extreme events and then bet that things will revert back to nearer the average. They have a long tail and extreme events can cluster together. Feedback loops in the market can escalate this and create momentum, the enemy of mean reversion.

Despite this, mean reversion is a powerful concept that traders can use to find an edge and built trading strategies around. A simple mean reversion strategy would be to buy a stock after an unusually large drop in price betting that the stock rebounds to a more normal level. However, there are numerous other ways that investors and traders apply the theory of mean reversion. Technical indicators like RSI can be used to find extreme oversold or overbought price levels.

These can act as good levels to enter and exit mean reversion trades. Standard deviation, Bollinger Bands, Money Flow, distance from a moving average, can all be used to locate extreme or unusual price moves. If a company reports strong quarterly earnings way above its long term average, the next quarter it will probably report closer to its average. There are many factors at play which can contribute to extreme results. Many of which suffer from natural mean reversion. For example, the weather.

Similarly, if a stock has an unusually low PE ratio, an investor might buy the stock betting that the company is undervalued and the PE will revert to a more average level. Many investors trim their exposure to the stock market as a result.

Since the market is a reflection of the crowd, some investors will look at sentiment indicators like investor confidence to find turning points. Historically, investor surveys have shown investors become more pessimistic near market lows and more confident near market peaks.In this article we are going to consider our first intraday trading strategy.

It will be using a classic trading idea, that of "trading pairs". The strategy broadly creates a "spread" between the pair of ETFs by longing one and shorting an amount of the other. The ratio of long to short can be defined in many ways such as utilising statistical cointegrating time series techniques. The trading signals will be generated when the z-score exceeds certain thresholds under the belief that the spread will revert to the mean. The rationale for the strategy is that SPY and IWM are approximately characterising the same situation, that of the economics of a group of large-cap and small-cap US corporations.

Perhaps the best way to understand the strategy in depth is to actually implement it. The following section describes a full Python code single file for implementing this mean-reverting strategy. I have liberally commented the code in order to aid understanding. Once setup, the first task is to import the necessary Python libraries. For this backtest matplotlib and pandas are required. It then creates a separate dataframe pairswhich uses the indexes of both original files.

Since their timestamps are likely to be different due to missed trades and errors, this guarantees that we will have matching data. This is one of the main benefits of using a data analyis library like pandas. The "boilerplate" code is handled for us in a very efficient manner. I have set a default lookback window of bars.

As discussed above this is a parameter of the strategy. In order for the strategy to be considered robust we ideally want to see a returns profile or other measure of performance as a convex function of lookback period. Thus at a later stage in the code we will carry out a sensitivity analysis by varying the lookback period over a range. This constitutes the first set of bars equal to the size of the lookback as a trimming measure.

Clearly this is not a realistic situation as we are taking fractional amounts of IWM, which is not possible in a real implementation.

### How To Build A Mean Reversion Trading Strategy

Finally, we create the z-score of the spread, which is calculated by subtracting the mean of the spread and normalising by the standard deviation of the spread. Note that there is a rather subtle lookahead bias occuring here. I deliberately left it in the code as I wanted to emphasise how easy it is to make such a mistake in research.

The mean and standard deviation are calculated for the entire spread time series. If this is to reflect true historical accuracy then this information would not have been available as it implicitly makes use of future information. Thus we should use a rolling mean and stdev to calculate the z-score. These are calculated by going long the spread when the z-score negatively exceeds a negative z-score and going short the spread when the z-score positively exceeds a positive z-score.

The exit signal is given when the absolute value of the z-score is less than or equal to another smaller in magnitude threshold.In theory this selection of tickers based upon some non-arbitrary, meaningful grouping criteria should allow us to focus in on pairs of symbols that are more likely to have statistically meaningful co-integration of prices series.

To test other groups of symbols, all we have to do is update the SQL query based upon whichever criteria we are interested in…. The possible combinations are obviously plentiful, and we could even incorporate multiple criteria at once to hone our focus even further.

So, after following the instructions to create our database, one should be able to just copy and paste the entire code below into a python script and it will run through all the backtests in one go:. So hopefully this makes it as easy as possible for anyone reading this to just copy and paste and run this whole thing locally.

I must admit, the backtest results are far from amazing, and many, many of them end in negative territory.

Hey, very useful code. I am trying to replicate the same and noticed a symbol that might have been missed. If the exit zScore was set to anything other than 0 then yes, there should be a minus sign in front of the code as you pointed out. In fact if you wanted more flexibility regarding the entry and exit zScores for example if you wanted the exit zScore to be a different sign than the entry zScore for either long or short tradesperhaps it would be better to set up specific entry and exit zScores for long positions and short positions separately, i.

Any advice from your side would be of great help to me. Hi, new to python. Tried running your script on two securities in spyder python 2. Hi there, I have rerun my code and I am getting the same error — luckily it is a very easy fix!

This will cast the halflife variable as an integer and that should then work when passed to the rolling mean function. Could you run the following code for me please and let me know the output:. I checked the list symbPairs. Happy coding! OLS df1. I am trying to run your code above and I encountered some issues when calculating the halflife spread.

The hallife of the spread between the two is negative and equal to days. Now if I set a negative halflife equal to to 1 As per your code above I have no rolling standard deviation. Does it make sense to have a negative half life? If so why would you set half life equal to 1 for negative values when the real half life might be bigger like days in my example?

## Python Backtesting Mean Reversion – Part 3

You calculate cadf and hedge ratio from the full sample. However you execute trades before cadf and hedge ratio are known. I presume you are aware this issue but this is important for your readers who may use this model for real trading. Trading Strategy Backtest.

You may also like. October 23, April 19, February 3, Hope the above is helpful. Sai Prem August 28, - pm Hey, very useful code. In its current format the flexibility is limited. Sai Prem August 28, - pm Thanks!

Thanks Loading I am getting rolling error as well but a different one. Look forward to hearing your opinion. Thanks a lot again LoadingAfter completing the series on creating an inter-day mean reversion strategy, I thought it may be an idea to visit another mean reversion strategy, but one that works on an intra-day scale.

That is, we will be looking for the mean reversion to take place within one trading day. Stock prices tend to follow geometric random walks, as we are often reminded by countless financial scholars; but this is true only if we test their price series for mean reversion strictly at regular intervals, such as using their daily closing price.

Our job is to find special conditions where mean reversion occurs with regularity. As the following strategy will show, there may indeed be seasonal mean reversion occurring at the intra-day time frame for stocks. The standard deviation is computed using the daily close-to-close returns of the last 90 days.

## Python Backtesting Mean Reversion – Part 4

I will be running this backtest using the NYSE stock universe which contains stock — you can download the ticker list by clicking on the download button below.

Once you have that file stored somewhere, we can feed it in using pandas, and set up our stock ticker list as follows:. The logic of our approach is as follows…we will iterate through the list of stock tickers, each time we will download the relevant price data into a DataFrame and then add a couple of columns to help us create signals as to when our two criteria are met gap down of larger than 1 90 day rolling standard deviation and an opening price above the 20 day moving average. We will then use these signals to create our return series for that stock, and then store that information by appending each stocks return series to a list.

Finally we will concatenate all those return series into a master DataFrame and calculate our overall daily return. Now this stock list has over stocks in it, so expect this code to take a bit of time to run…I believe mine took about minutes to run when I tried it, so try to be a bit patient. Once the code has run and we have our list filled with all the individual strategy return series for each stock, we have to concatenate them all into a master DataFrame and then calculate the overall daily strategy return.

This can be done as follows:. So now we have a return series that holds the strategy returns based on trading the qualifying stocks each day, in equal weight. So a Sharpe Ratio of over 2 and an annual return of around 8. Of course, we have to remember that we are not taking into account any transaction costs so those returns could be quite heavily effected in a real world setting.

That post can be found here. Thanks for the post. We are working on a high performance data analytics framework in python and would like to use your codes as examples. Are we allowed to use the material? Is there a license for this material? Hi Ehsan — thanks for the kind words. I write this blog just for my own amusement, so no license is needed to re-use the code, please feel free to do so.

All I would ask is that, if possible, you reference my blog as the source so that I may possibly attract more traffic.

I noticed something because this is taking Open to Close change, the line below should add a shift 1? Because if you dont you will be taking in today close price But we are buying at Open and cannot possibly know today close prices.In theory this selection of tickers based upon some non-arbitrary, meaningful grouping criteria should allow us to focus in on pairs of symbols that are more likely to have statistically meaningful co-integration of prices series.

Welcome back everyone, finally I have found a little time to get around to finishing off this short series on Python Backtesting Mean Reversion strategy on ETF pairs.

In the last post we got as far as creating the spread series between the two ETF price series in question by first running a linear regression to find the hedge ratio and ran an Augmented Dickey Fuller test, along with calculating the half-life of that spread series to see whether it was a decent candidate for a tradable strategy pair.

Hi all, welcome back. Once we have the script working for a single input of one pair of symbols, we can very easily adapt it at the end to work with the symbol pairs function created previously. Home Tags Posts tagged with "python backtesting mean reversion". Tag: python backtesting mean reversion. Trading Strategy Backtest. Continue Reading. July 10, 15 comments. July 8, 15 comments. May 9, 8 comments.