Back to Community
Buy/Sell By Date With Delay

I'm trying to implement an algorithm that buys and sells on specific dates, but with some days of offset. I cannot seem to find a way to implement this in a way that uses trading days instead of calendar days for the offset. Here's what I've got now:

-----------------------------------------------------------------------

stock = symbol('SPY')

-----------------------------------------------------------------------

import datetime
from datetime import timedelta

def initialize(context):
context.delay = 0
schedule_function(trade,date_rules.every_day(),time_rules.market_open(minutes = 1))

def before_trading_start(context, data):
pass

def trade(context,data):
if str(get_datetime().date()) == str(datetime.date(2017,4,11)+datetime.timedelta(days=context.delay)):
order_target_percent(stock,1.0)
if str(get_datetime().date()) == str(datetime.date(2017,4,18)+datetime.timedelta(days=context.delay)):
order_target_percent(stock,0.0)

Can anyone offer suggestions?

4 responses

Which 'specific days' do you want to trade? Will this be a hard coded list, the first of each month, the day after earnings have been announced, or something else?

Disclaimer

The material on this website is provided for informational purposes only and does not constitute an offer to sell, a solicitation to buy, or a recommendation or endorsement for any security or strategy, nor does it constitute an offer to provide investment advisory services by Quantopian. In addition, the material offers no opinion with respect to the suitability of any security or specific investment. No information contained herein should be regarded as a suggestion to engage in or refrain from any investment-related course of action as none of Quantopian nor any of its affiliates is undertaking to provide investment advice, act as an adviser to any plan or entity subject to the Employee Retirement Income Security Act of 1974, as amended, individual retirement account or individual retirement annuity, or give advice in a fiduciary capacity with respect to the materials presented herein. If you are an individual retirement or other investor, contact your financial advisor or other fiduciary unrelated to Quantopian about whether any given investment idea, strategy, product or service described herein may be appropriate for your circumstances. All investments involve risk, including loss of principal. Quantopian makes no guarantees as to the accuracy or completeness of the views expressed in the website. The views are subject to change, and may have become unreliable for various reasons, including changes in market conditions or economic circumstances.

Thanks, Dan. It will be a hard-coded list with no regular pattern.

I'm relatively new to this, but I've been exploring the use of get_trading_days from the zipline.utils.tradingcalendar to get trading day offsets.

from zipline.utils import tradingcalendar
from zipline.utils.tradingcalendar import get_trading_days

 date_range = get_trading_days(datetime.datetime(2017,3,14),datetime.datetime(2017,3,21))        #Tuesday thru Tuesday  
 print(date_range[4])      #correctly produces the following Monday

A problem that remains is that get_trading_days requires parameters which datetime.datetime produces. Using datetime.date throws an error:
AttributeError: 'datetime.date' object has no attribute 'date'

If I use this date_range[4] in my algorithm, however, it never matches, probably due to the time portion of the response.

if get_datetime().date() == date_range[4]:  
    order_target_percent(stock,1.0)

How can I massage date_range[4] into a form which can successfully match with the get_datetime().date() response?
If I can accomplish this, I think I can make the algorithm work with trading day offsets.

Here is half a solution. In your initialize function put this

    # enter a list of rebalance dates as strings  
    date_str_list = ['1-1-2020',  
                     '1-3-2020',  
                     '1-5-2020',  
                     '1-7-2020',  
                     '1-15-2020',  
                     ]  
    # create a list of dates  
    context.date_list = [pd.Timestamp(date).date() for date in date_str_list]


Then, in rebalance check if the current trading day is in the list.

    today = algo.get_datetime().date()

    if today not in context.date_list:  
        # return and do nothing  
        log.info(' NOT rebalancing on {}'.format(today))  
        return  

This will check for dates in the list but not do the offset as requested. I'm looking into how to potentially use the trading calendar for that.

Hope this is a start.

Thanks again for your help, Dan. I persevered with altering the format produced by get_trading days, and was finally successful.
Here's the entire algorithm for buying and selling on fixed specified dates with independent buying and selling trading days of delay up to 5 days.
It seems to produce correct trading (not calendar) day delays. There's probably a more elegant way of accomplishing it, but this was the best I could do.

-----------------------------------------------------------------------

stock = symbol('SPY')

-----------------------------------------------------------------------

import datetime
from zipline.utils import tradingcalendar
from zipline.utils.tradingcalendar import get_trading_days

def initialize(context):
context.buy_delay = 3
context.sell_delay = 4
schedule_function(trade,date_rules.every_day(),time_rules.market_open(minutes = 1))

def before_trading_start(context, data):
pass

def trade(context,data):
buy_range = get_trading_days(datetime.datetime(2017,3,14),datetime.datetime(2017,3,21))

if str(get_datetime().date()) == str(buy_range[context.buy_delay])[0:10]:  
    order_target_percent(stock,1.0)


sell_range = get_trading_days(datetime.datetime(2017,3,21),datetime.datetime(2017,3,28))

if str(get_datetime().date()) == str(sell_range[context.sell_delay])[0:10]:  
    order_target_percent(stock,0.0)