mean reversion

Here is a backtest for small mean reverting portfolios

Ideally, it should have selected 10-15 mean reverting stocks from a universe of 30-40 stocks but quantopian does not scale :(

54
Backtest from to with initial capital
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
 Returns 1 Month 3 Month 6 Month 12 Month
 Alpha 1 Month 3 Month 6 Month 12 Month
 Beta 1 Month 3 Month 6 Month 12 Month
 Sharpe 1 Month 3 Month 6 Month 12 Month
 Sortino 1 Month 3 Month 6 Month 12 Month
 Volatility 1 Month 3 Month 6 Month 12 Month
 Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Backtest ID: 5757eba0a6500811f94577cc
There was a runtime error.
8 responses

Sweet! Thanks for all your work on this.

Hello Pravin,

You say:

Ideally, it should have selected 10-15 mean reverting stocks from a universe of 30-40 stocks but quantopian does not scale :(

What is the problem? Time-out? Memory? Other? If it is timing out, you could consider running your code in before_trading_start, where you'll have 5X more time.

Also, what does your code do? Would you provide a little lecture on the overall concept and the major steps. I'll try to go back to the original paper, but as is typical, there's little explanation of the basic concepts at an intuitive level. For example, are we talking about finding a handful of stocks, with some expected to revert in price upward and some expected to revert in price downward; hence we would know which to long and which to short, and in what proportion? Or are we forming two baskets that are statistically related to one another (e.g. pair trading, except with a long basket and a short basket)? Something else altogether?

Hi Grant,

If I increase to universe to 30 stocks it times out. The optimization routine does not complete. If I set it to more than that the kernel dies.

The code attempts to find a mean reverting portfolio weights that is stationary. i.e. it moves around a constant mean with a variance. If it moves beyond 2 standard deviations from the constant mean the algorithm shorts the portfolio and vice versa. It used Box Tiao canonical decomposition method to find a mean reverting portfolio. So if universe if 20 stocks and K=5 it will select the best 5 out of 20 stocks and set the weights to other 15 to very small number (approx. zero).

I am still working on a proper model for this algorithm and trying to run it outside quantopian using prices from Yahoo. Ideally I want to give it more than 50 stocks and ask it to select 10+ best mean reverting portfolio weights. The reason being that more stocks in the portfolio the better insulated it is from random shocks to a single stock.

Also need to improve the trading strategy once a stationary portfolio is identified. At the moment, I am simply using a check of + or - 2 s.d. but should probably fit an OU process to it.

Pravin,

So in your example of 20 stocks total and picking the 5 best, does it set all 5 to an equal weight (either short or long)? Or within the 5 best, are the weights unequal? Also, it sounds like it'll either go long or short but not both at the same time? Or are you finding the best 5 to short and the best 5 to go long?

Do you know what part of the code the Quantopian backtester is choking on? Are you simply running CVXOPT once? I've done a lot of work with scipy.optimize.minimize and it scales well with larger portfolios. I wouldn't expect a problem with 30 stocks. What's the optimization problem you are solving?

Grant,

If universe is 20 and K=5, it picks 5 with unequal weights (both long and short) and usually dollar neutral.

I am running CVXOPT once and it chokes on the optimization. The optimization problem is an SDP as mentioned towards end of page 8 in this document.

Thanks Pravin,

So, presumably you are solving the optimization problem given by eq. 12, pg. 8 of the paper (http://www.di.ens.fr/~aspremon/PDF/MeanRevVec.pdf). You could try scipy.optimize.minimize, I think. Presumably, your objective function would become 1/[Tr(AY)], so that the minimum would correspond to the maximum of Tr(AY). If you use method=’SLSQP’ both equality and inequality constraints can be used.

In the paper, what does the constraint Y>=0 mean? Y is referred to as a solution matrix. Is it actually a vector? Either way, is Y>=0 shorthand for each element being zero or greater?

I recall that Quantopian doesn't actually fully support CVXOPT yet (see https://www.quantopian.com/posts/cvxopt-module). So, you might be better off using scipy.optimize.minimize, which presumably is fully supported.

Y >=0 means a positive semi definite matrix. I do not think scipy can do SDP in general. Very difficult to provide derivatives of all constraints and objective functions but I could be wrong. But it is a very uphill task.

I see (after a bit of googling). The positive semi-definite constraint is not a set of linear inequality constraints, but something else incompatible with scipy, as far as I can tell.