Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Date constrained trading: HELP!

I was looking to trade a certain security on the same day and sell on the same day each year. How do I code this so that I do not need to manually input dates? Testing a seasonality trading algorithm. Some filler with moving average is there, but i just need to know how to do the date buy and sell on the same day and month as prescribed in the code.

import datetime


def initialize(context):  
    #security to be ordered  
    context.security = sid(32133)  
    #list of days to execute algorithm #1  
    context.alg1_days= [datetime.date(2007,4,20),datetime.date(2008,4,20),datetime.date(2009,4,20),datetime.date(2010,4,20),datetime.date(2011,4,20),datetime.date(2012,4,20)]  
    #list of days to execute algorithm #2  
    context.alg2_days= [datetime.date(2007,9,21),datetime.date(2008,9,21),datetime.date(2009,9,21),datetime.date(2010,9,21),datetime.date(2011,9,21),datetime.date(2012,9,21)]  
def handle_data(context, data):  
    fmavg = data[context.security].mavg(12)  
    smavg = data[context.security].mavg(26)  
    macd = fmavg - smavg #MACD mavg(12) - mavg(26)  
    qavg = [macd,9] #MACD avg (9 days) # i dont know if this is right?  
    y = data[context.security].datetime.year  
    m = data[context.security].datetime.month  
    d = data[context.security].datetime.day  
    event_day = datetime.date(y,m,d)  

    #algorithm #1 execution  
    for day in context.alg1_days:  
        if event_day == day:  
            order(context.security,+10000)  
    #algorithm #2 execution  
    for day in context.alg2_days:  
        if event_day == day:  
            order(context.security,-10000)  
8 responses

Hello Kylr,

You just need to test for month and day, but not year. So, if it is April 20th, then do something. If it is September 21st, do something else. Right? If I understand you correctly, the year is irrelevant. Just make sure the market was open on those days for every year in your backtest.

Grant

the issue is, year is needed when handling with date time. 3 contexts. (y,m,d). so I'm having trouble doing that.

Kylr,

Have a look...I attempted to re-write your code, per your original intent. As I mentioned, now you need to consider how to handle the fact that the market isn't always open.

Grant

I would use timedelta to do this. Grant's solution is Ok but when those days fall on the weekend I'm not sure it will work. Below is the code. You can switch out weeks for days or years or whatever you need.

if (get_datetime() - context.lastPortfolioUpdate) >= timedelta(weeks=context.rebalanceFrequency)  

thanks guys!

Kylr,

Here's a tweak to the algo I posted above. It uses (with context.bought = False as an initial condition):

#algorithm #1 execution  
    if get_datetime().month == 4 and get_datetime().day >= 20 and context.bought == False:  
        order(context.security,+10000)  
        print get_datetime()  
        context.bought = True  
    #algorithm #2 execution  
    if get_datetime().month == 9 and get_datetime().day >= 21 and context.bought == True:  
        order(context.security,-10000)  
        print get_datetime()  
        context.bought = False  

Probably equivalent to the approach Brian posted above. Try both!

A couple notes. You are out of the market a large fraction of the time, so if it is rising, you'll lose out. Conversely, you'll see a benefit to this approach when the market tanks (e.g. 2008-2009). You might try a more modest seasonal/quarterly re-balancing (e.g. SPY/BND) to see if there is an edge.

Grant

pandas date range functions might help you out. See the docs. You can use pd.date_range or pd.bdate_range which will be only business days. You might have some issues with getting the exact day, especially if it falls on a weekend.

# Here's a simple solution if you need exact dates

four_twenty = [pd.to_datetime(str(i)+'-04-20') for i in range(2007,2015)]

# Gives you this  
[Timestamp('2007-04-20 00:00:00', tz=None),
 Timestamp('2008-04-20 00:00:00', tz=None),  
 Timestamp('2009-04-20 00:00:00', tz=None),  
 Timestamp('2010-04-20 00:00:00', tz=None),  
 Timestamp('2011-04-20 00:00:00', tz=None),  
 Timestamp('2012-04-20 00:00:00', tz=None),  
 Timestamp('2013-04-20 00:00:00', tz=None),  
 Timestamp('2014-04-20 00:00:00', tz=None)]  

You might need to use datetime.date() for checking if a date in in the list, I've had an issue with that.

four_twenty =[pd.to_datetime(str(i)+'-04-20').date() for i in range(2007,2015)]

[datetime.date(2007, 4, 20),
 datetime.date(2008, 4, 20),  
 datetime.date(2009, 4, 20),  
 datetime.date(2010, 4, 20),  
 datetime.date(2011, 4, 20),  
 datetime.date(2012, 4, 20),  
 datetime.date(2013, 4, 20),  
 datetime.date(2014, 4, 20)]  

Good Luck

Hello Kylr, and all,

If you really want to dig into this, Quantopian has a bunch of trading calendar utilities here:

https://github.com/quantopian/zipline/tree/master/zipline/utils

They can be exposed in the algorithm (although you may need to request that certain functions be unblocked).

Grant