Back to Community
How can I sell automatically a few days later after I place a buy order?

I have a problem when I started to program a simple strategy. Basically, what I want is, for example, selling the stock automatically in 5 days after I buy the stock. How I can achieve this using this platform?

6 responses

I figured it out. Just add a variable in 'context' to countdown the selling dates for each stock in the universe. Every time you buy a stock, you add a countdown for that stock. Then decrease the countdown by 1 per frame, when it reaches 0, it is the time to sell that stock. Attached is an example, but the strategy implemented here is not good, it's just for the illustration.

Clone Algorithm
34
Loading...
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
# Put any initialization logic here.  The context object will be passed to
# the other methods in your algorithm.



def initialize(context):
    set_universe(universe.DollarVolumeUniverse(40, 45))
    
    context.countdown = {}
    

# Will be called on every trade event for the securities you specify. 
def handle_data(context, data):
    # Implement your algorithm logic here.

    # data[sid(X)] holds the trade event data for that security.
    # context.portfolio holds the current portfolio state.

    # Place orders with the order(SID, amount) method.

    # TODO: implement your own logic here.
    num_of_days_to_sell = 30
    for sid in data:
        # check if we should sell
        if sid in context.countdown and context.countdown[sid] != []:
            days_left = context.countdown[sid][0]
            if days_left > 0:
                context.countdown[sid][0] = days_left - 1
            else: 
                context.countdown[sid].pop(0)
                # sell the stock
                order(sid, -100)
                message = 'sell {n} shares {s}.'
                log.info(message.format(n = 100, s = sid.symbol))
        
        # check if we should buy
        daily_return = data[sid].returns()
        # if the stock drops more than 20%, buy it
        if daily_return < -0.20:
            order(sid, +100)
            message = 'buy {n} shares {s}.'
            log.info(message.format(n = 100, s = sid.symbol))
            # set the selling date
            if sid not in context.countdown:
                context.countdown[sid] = [num_of_days_to_sell]
            else:
                context.countdown[sid].append(num_of_days_to_sell)
        
        
            
                
    
        
There was a runtime error.

An easier and probably more robust approach is to store a dict that maps your symbol to a target sale time, and then once per frame, look at your holdings and see if that time has been reached. Looking purely at frame counts is a great way for timing to go screwy due to unexpected irregularities.

Hi J. Shagam, thanks for your suggestion. Actually I thought about the approach you mentioned, but the problem is that 5 days later after the buying date may not be a trading day, so the date may never be reached. Or is there any way to get the 5th trading day after the buying date?

Ah, if you want trading days rather than calendar days, then yeah you'll have to do something like that.

Maybe nudge you in the right direction or some direction anyway to hopefully be able to tell when five trading days have gone by...

import datetime as dt  # Surprising that datetime doesn't have timezone  
from pytz import timezone  
from zipline.utils import tradingcalendar

def handle_data(context, data):  
        # Real-world time now  
        days_offset = 0  # Alter days_offset like 2 to go back in time 2 days.  
        today  = dt.date.today() - dt.timedelta(days=days_offset) # end  
        y_now  = today.year  
        m_now  = today.month  
        d_now  = today.day  
        week   = today - dt.timedelta(days=7) # start, a week ago  
        y_week = week.year  
        m_week = week.month  
        d_week = week.day  
        start  = dt.datetime(y_week,m_week,d_week,0,0,0,0,timezone('US/Eastern'))  
        end    = dt.datetime(y_now, m_now, d_now, 0,0,0,0,timezone('US/Eastern'))

        context.event_dates = tradingcalendar.get_trading_days(start, end)  
        log.info(str(context.event_dates[-5]))

Hi Gary, thanks for the information. I'll check out the 'tradingcalendar'