Back to Community
long-short market neutral w/ optimization API

Note:

set_slippage(slippage.FixedSlippage(spread=0.00))  
set_commission(commission.PerShare(cost=0, min_trade_cost=0))  

See https://www.quantopian.com/posts/optimize-api-now-available-in-algorithms

Also, note corner-case crash risk in optimization API: https://www.quantopian.com/posts/problem-w-slash-dvmt

Clone Algorithm
309
Loading...
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: 589075e192df695e24d17bf4
There was a runtime error.
6 responses

Note:

set_slippage(slippage.FixedSlippage(spread=0.00))  
set_commission(commission.PerShare(cost=0, min_trade_cost=0))  

Same as above, except I added:

a = rankdata(a)  

Not sure why it helps, but I always see the Q boys doing it, and they're getting paid, so they must know what they're doing.

If you clone and improve, you must post, per my license terms.

Clone Algorithm
309
Loading...
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: 5892942a9b82845e3ab16d08
There was a runtime error.

Grant,
Thanks for the algo!
Looks like pieces of your mean-revision algos here...right?
Question : what does get_weights do?
Thanks,
alan

Hi Alan,

The function get_weights computes a long-short price mean reversion factor across all stocks in a universe. For each stock, the factor is the ratio of the mean price (over all trailing prices) to the current price. If the mean price to current price ratio is less than 1, then, the reciprocal is used, and d is -1 (otherwise it is 1). So, the np.sum(x_tilde) is a measure of how much profit could be had, under the assumption that price mean reversion will happen on both the long and the short sides, respectively.

So, what ends up returned is a signed factor, and a weight that is a measure of the profit potential for the trailing window of prices fed to the function.

Make sense?

Here's a tweak.

Note:

set_slippage(slippage.FixedSlippage(spread=0.00))  
set_commission(commission.PerShare(cost=0, min_trade_cost=0))  

The main change is to flip the sign of the factor if it gets too big/small:

def mean_rev(context,data,prices):  
    m = len(context.stocks)  
    d = np.ones(m)  
    x_tilde = np.mean(prices,axis=0)/prices[-1,:]  
    y_tilde = 1.0/x_tilde  
    d[x_tilde < 1] = -1  
    d[x_tilde < 0.9] = 1  
    d[x_tilde > 1.1] = -1  
    x_tilde[x_tilde < 1] = 0  
    y_tilde[x_tilde != 0] = 0  
    x_tilde = x_tilde + y_tilde

    return (d*x_tilde, np.sum(x_tilde)/m)  
Clone Algorithm
309
Loading...
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: 589a467df67ca15e0b037c84
There was a runtime error.

Sorry this took me so long to reply to you, but have been on vacation in Hawaii...optimizing the sun rays!
Thanks for your reply...I think I now understand get_weights.
A few more questions:

  1. You seem to be looking at a 4-day window of minutely prices,
    and smoothing out the weights given from the optimization in 30 min increments...right?
    My question is why did you chose the time-scale you did?
    Instead of minutely data, you could use daily data(i.e. look for mean reversion over a 3-6-12 monthly period.)

  2. Do we have any indication that we are in a time frame for this basket of equities where mean-reversion works?
    I'm assuming that this algo is a modification of your QForum-MeanReversion post, which I've used before...thanks!..., where the paper doesn't seem to address when the "mean-reversion signal is on". I guess one of the key differences is the optimization is used to get weights for the shorts simultaneously with the longs...it would be nice to have some theory that sez that works.
    I'm also looking at the following paper to try and enhance my understanding. [Mean-Reversion and Optimization][2]

@ Alan -

Glad to hear someone is getting some R&R in the sun. Lots of snow and cold here.

You seem to be looking at a 4-day window of minutely prices,
and smoothing out the weights given from the optimization in 30 min increments...right?

That's the basic idea. Rather than using a fixed window, one can use an expanding window, and take a weighted average.

My question is why did you chose the time-scale you did?

Determined by just fiddling with the algo, trying different windows.

Instead of minutely data, you could use daily data(i.e. look for mean reversion over a 3-6-12 monthly period.

Easy enough to try, but my hunch is that it is a relatively short-term effect.

The alphalens thingy might work here. Supposedly, it will work with any inputs; they don't have to be daily returns from pipeline.

it would be nice to have some theory that sez that works

Yes, I'm not sure how to do that. I'm not sure one will find a "theory" as much as more detailed empirical evidence of what's going on.