Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Worthy of Q fund?

I am curious to know if Q is interested in this class of algorithms that show high intraday trading frequency.

The backtest ran with default slippage but commission set to PerTrade(cost=0.0075) as It cannot be profitable with default commission.
Also the time period is short because the algorithm runs into a timeout if I try to run a longer backtest, but this should be enough.

9 responses

Well I do hope Q answers. Meanwhile, pardon the interruption, want to say, it can be a lot more profitable than it appears to be, if it currently isn't using all of the initial capital. Try this to know:

    c = context  
    if 'risk_hi' in c:  
        shorts = 0  
        for p in c.portfolio.positions:  
            shrs = c.portfolio.positions[p].amount  
            if shrs < 0:  
                shorts += int(abs(shrs * data[p].price))

        cash_dip  = int(max(0, c.portfolio.starting_cash - c.portfolio.cash))  
        risk      = int(max(cash_dip, shorts))  # Amount in play, maximum of shorts or cash used  
        c.risk_hi = max(risk, c.risk_hi)

        if c.risk_hi != 0:     # Avoid zero-divide  
            record(PvR_Ret = (100 * c.portfolio.pnl / c.risk_hi))        # Profit_vs_Risk returns

    else:    # Init this instead in initialize() for better efficiency  
        c.risk_hi = 0  

Looks pretty sweet to me - I usually backtest with PerShare(0.0035, min=0.35) since that seems to be roughly what I realize with Interactive Brokers...

Thanks Simon, I will try again with the suggested settings (this algorithm goal is to go live trading, so your is a good point)

@garyha, the algorithm's leverage is around 1.0 because that's what I wanted to test but I keep your suggestion in mind when I start testing the leverage. Thank you.

Sure. I'm thinking you might be able to clarify some questions I'm trying to grapple with when you arrive there, no pressure.
This is some of your great work from elsewhere and I have corrupted it with a multiplier to create an imbalance around line 200 and sprinkled leverage charting in there at various points. It's critical we know what we're doing when dealing with investors, and it would be a shame to say to them, my algo has a leverage of 2 when it is really 3 at some point, seems to be happening here somehow. Because of this I'm winding up with the view that max leverage is somehow pretty important, and placement of the line where leverage is being inspected, naturally.

Edit: Some clarification below, later ...

@garyha, sorry but I didn't get your point. In your example you are using "a multiplier to create an imbalance around line 200" and so the algorithm is not investing as much cash as the ExposureMngr calculates, but more and this cause the over leverage. Did I miss something?

@Simon.

I ran few test with PerShare(0.0035, min=0.35) and the performance decrease drastically. This is because with this new settings I have to buy/sell 100 shares (0.35/0.0035=100) to absorb the minimum transaction cost. This means that all the low volume stocks that my algorithm trades are now affected by a high slippage cost (or I simply have to trade only on high volume stocks, haven't tried yet).

The question is, why Quantopian can afford to not have a minimum transaction cost in their contest? Is there a commission option in IB where the minimum transaction cost is not present so that I can trade small amount of stocks without having to pay high commission cost?

Note: this doesn't affect the main question of this thread. Is Quantopian interested in the kind of algorithms where the one above is an example (that is high intraday trading frequency)?

If you are seeing results that only work when trading very low volume stocks at high frequencies, you need to be very careful that you are not just trying to do mean-reversion on meaningless bid-ask bounce. Unfortunately, there's no way to really test this with Quantopian, but one of my main findings in the process of creating a quote-based tick-frequency backtester (in Scala) was that most of my basket mean-reversion profits were just untradeable bid-ask bounce. I mentioned this once in https://www.quantopian.com/posts/inaccurate-max-drawdowns-on-no-trade-days-slash-periods with a handy diagram: http://imgur.com/1WPMwFD

Not knowing what your algo does, I clearly have no idea whether this problem applies to you, but I thought I'd mention it. One way to test would be to sample a few of your universe of stocks, look up the quotes on yahoo and use that half that spread as the slippage in a FixedSlippage model. If your alpha disappears, it might be wise to paper trade it before diving in. Paper trading with an Interactive Brokers paper account should give a pretty good idea of whether it's going to be feasible, but I think those accounds are all on the Fixed commission schedule, which has an even higher minimum commission of $1/trade.

If you model relies on limit orders getting filled, then you have an even harder problem, which is that you cannot simulate the probability of being filled and the probability of adverse selection without order book data, I would think - I haven't tried to do that personally. You could do a conservative simulation with Level 1 quotes by requiring a complete trade-through...

Some needed clarification of my earlier message:

Why is max leverage 3.05 while context.account.leverage is far lower? Maybe because record() is only the end of day value? Daily level.
So, couldn't we be ordering way into negative cash at noon, return to a leverage of 1 by close, and mistakenly figure we are fine?
I think I was trying to demonstrate that problem above by forcing into negative cash, margin, and wasn't clear.

We can be thinking we have an awesome result and leverage around 1 when actually it would have required 3 times the starting capital in the Interactive Brokers account to achieve that result, we missed a leverage spike.

Due to this, shouldn't we be watching max_leverage, not just current leverage, since record() happens only once per day?
I presume if we run record() every minute, all except the last one per day are ignored. True?

When looking at maximums, it isn't necessary to run record() every minute, just when there is a new high.
Reading context.account.leverage still has to happen every minute to see if there is a new maximum.
This can do that ...

    # Record maximum leverage encountered  
    if 'mx_lvrg' not in context:  
        context.mx_lvrg = 0         # init this instead in initialize() for better efficiency  
    if context.account.leverage > context.mx_lvrg:  
        context.mx_lvrg = context.account.leverage  
        record(mx_lvrg = context.mx_lvrg)