Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Median Reversion Strategy for On-Line Portfolio Selection

Hi all,
I have looked at this algorithm and back test
I was wondering if someone could give me some detailed explanation in regards to this algorithm logic
and why is it so successful??...
I know my question is a bit vague but any help would be greatly appreciated.

Many thanks all,
Best Regards,
Andrew

6 responses

That's very impressive. Thanks for sharing this with us. I have no input because this is frankly beyond my skill level.

What was your leverage at for this backtest?

I checked. No leverage.

I believe it is to do with slippage and commissions. I put in the following slippage and commissions:

Assumes that your entire buy order will be filled 0.01 higher and a sell order will be filled 0.01 lower (could still be conservative depending on order size and liquidity)
set_slippage(slippage.FixedSlippage(spread=0.02))

Slightly more expensive that IB's 0.005 per share with $1 minimum
set_commission(commission.PerShare(cost=0.01, min_trade_cost=1))

With these parameters, the algorithm went to -99% returns in the 2 month period between the beginning of Jan and end of Feb this year. The algorithm is so profitable because of very unrealistic transaction costs and slippage.

As a follow up, the original model has the following line of code (a custom slippage model):

set_slippage(TradeAtTheOpenSlippageModel(0.1))

If we are to assume that this model is as accurate as possible, we still cannot ignore the commissions system, which has been set to:

set_commission(commission.PerTrade(cost=0))

Thus, if we keep their slippage model and just change the commission scheme to the one mentioned in my prior post, the algorithm, when run from Jan 4th 2015 to present on minute data hits -99% returns by mid-March. This tells me that the original algorithm's hyperinflated results are almost entirely because of the lack of commissions being built into the system.

Leverage is the ratio of amount spent vs initial capital. If borrowing occurs, leverage goes above the value of 1 (borrowing, negative cash) and that condition is called margin. As soon as one's first buy occurs, leverage is no longer zero. Examples: The leverage for a first purchase of $5 (including commission) on $10 initial capital would be .5 (one half). Spending $15 on $10 initial capital would be 1.5.
Most of the time when we refer to "leverage" we really mean to be talking about 'margin', negative cash, borrowing.

Here's another way to keep an eye out for margin. It won't tax the logging limits too much because it only logs new highs (or lows in the second one), and can be easily dropped into an algo (it does its own initialization for storing the previous value to be able to compare):

def handle_data(context, data):  
    # Log any new leverage high  
    if 'leverage_high' not in context:  
        context.leverage_high = 0  
    if context.account.leverage > context.leverage_high:  
        context.leverage_high = context.account.leverage  
        log.info('leverage_high {}'.format(context.leverage_high))  

Sometimes an easier way to think of it is lowest cash used instead, and this does that:

def handle_data(context, data):  
    # Log any new lowest cash level  
    if 'cash_low' not in context:  
        context.cash_low = context.portfolio.starting_cash  
    if context.portfolio.cash < context.cash_low:  
        context.cash_low = context.portfolio.cash  
        log.info('cash low {}'.format( int(context.cash_low) ))  

You used record() for cash, that's great
Side-note: One thing that folks ought to keep in mind is that the custom chart necessarily does smoothing to be able to be so nice, so mousing over it can show averaged values that didn't really actually happen. For example if you record just two values, 0 on some bars and 100 on others, sometimes the chart will show you a value of say, 60, due to smoothing.
Lines like those above provide precision if needed.

By the way, did you know you can click custom chart legend items to toggle them off and on? I just discovered that a few days ago, useful sometimes when two or more recorded sets of values are in widely different ranges from each other.

You'll find that the algo above uses a lot of leverage/margin. It had already spent twice the initial capital five days in (leverage of 2.0040087117). Three times a couple of years later. I didn't have the patience to wait for the full test. It is useful for you to know that unfortunately the chart and metrics currently ignore margin (negative cash, borrowing). On our own we can calculate profit divided by maximum spent (including margin) and that will give us an idea of code merit no matter how much margin happens to be used as code changes are made. And that feels great to not have to be putting forth so much effort to be as close as possible to the utilization of 100% of initial capital. Good luck.