Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Backtest works in Daily mode but not in minute mode

Hello everyone,

I have this algo that I've been tweaking a bit, but since the algo uses triggers based on daily data, I've always used that mode. Now for the contest they say to use the minute mode, but for some reason my algo does not work in that mode. It never buys anything.

I'm guessing it has to do with the way I'm getting historical data, so maybe instead of getting data with '1d' as parameter, maybe I need to ask for minute historical data?

Or is there anything else I need to do to make it work as-is?

Thanks!

6 responses

It seems that I added the incorrect backtest. I am running a new one to attach it here.

This is the one.

Your volume for the last period is the volume for the minute - not the day as you expect. Which will never be greater than the average daily volume.
Try this:

import talib  
import numpy

macdShort = 12; macdLong = 26; macdSignal = 9  
volMAPeriods = 20

def initialize(context):  
    set_symbol_lookup_date('2013-01-01')  
    context.stocks    = symbols('DD', 'MRK', 'KO', 'MMM')  
    context.init_cash = context.portfolio.cash  
    schedule_function(func=HandleDataScheduled,  
                      date_rule=date_rules.every_day(),  
                      time_rule=time_rules.market_open(hours=0, minutes=1))

def handle_data(context, data):  
    pass

def HandleDataScheduled(context, data):  
    # Historical data for the stocks  
    prices  = history(macdLong + macdSignal + 1, '1d', 'close_price')  
    volumes = history(volMAPeriods + 1, '1d', 'volume').ffill().bfill()  
    eligibleStocks = []  
    inEligibleStocks = []

    for stock in context.stocks:  
        closes = numpy.array(prices[stock].values.tolist())  
        macdIndicator  = talib.MACD(closes, macdShort, macdLong, macdSignal)  
        macd   = macdIndicator[0][-1]  
        signal = macdIndicator[1][-1]  
        currentPosition = context.portfolio.positions[stock].amount  
        stockVolumes    = volumes[stock].values.tolist()[0:-1]  
        stockVolume     = stockVolumes[-1]  
        volEMA          = talib.EMA(numpy.array(stockVolumes), timeperiod = volMAPeriods)[-1] 

        ### New or continuation signal  
        if (macd < signal and stockVolume > volEMA):  
            eligibleStocks.append(stock)  
        ### Exit signal  
        elif (macd > signal  and currentPosition > 0 and stockVolume > volEMA):  
            inEligibleStocks.append(stock)  
        ### Maintain position  
        elif (currentPosition > 0):  
            eligibleStocks.append(stock)

    eligibleCount = float(len(eligibleStocks))  
    for stock in eligibleStocks:  
        order_target_percent(stock, 1.0 / eligibleCount)  
    for stock in inEligibleStocks:  
        order_target(stock, 0)

    record(Leverage = context.account.leverage, Cash = context.portfolio.cash)  

Oh wow! that's very very nice.

I see you grouped together the logic for the triggers.

What I don't understand quite fully is:

macdLong + macdSignal + 1
volMAPeriods + 1

why the +1?

On my code I was passing 40 as it should be the last 40 days. Here you are passing the 26 + 9 (macd params) so it gives 38 +1, so 39. Does that mean the last (or first) day is not included/needed? and why volMA periods is 21? I'm guessing ~40 /2, or is there anything else I'm not seeing?

Thanks a lot! it really was a nice cleanup. Very cool indeed!

@Akram, "+1" is a habit of mine. Ensuring that there's always enough data in the collection from which to drive the indicator calculations. Period over period metrics usually need periods+1 to calculate. Change it at your will.

FYI, change this "market_open" to "market_close" to get a nearer approximation to daily returns when running minutely. At least, that was my experience. Matching daily to minutely returns seems to be somewhat of a crap shoot. Maybe others have knowledge of how to reconcile the returns of the two periodicities.

Maybe taking the average of the open and close prices? I'll fiddle a bit with that param and see hot does the performance change. Thanks again!