Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Selling stock after time

Can anyone tell me how to sell a stock exactly 10 trading days after it was bought?

specific to my code?

Already, ive tried it with a daycount variable in handle data, but it isn't working

13 responses

Hi Charles,

the 'handle_data' function runs every minute, so you don't want to use that function to increment a variable designed to keep a count of your holding period daily. what I find to be best for day counts is to add an empty dictionary in the 'initialize' function:

def initialize(context):  
    context.holding_time = {}  

Then, whenever I make a new purchase, I add the stock purchased and 0 days to the dictionary. In the example below, I am iterating through an example buy list, and adding each stock and 0 days of ownership to the dictionary:

# example order

for stock in example_buy_list: # iterate through buy list  
    order(stock, 1) # make order  
    context.holding_time[stock] = 0 # add the stock and 0 days to the dictionary  

From there you can schedule a function to run every morning to both increment the holding period, and liquidate stocks that have hit the amount of days you want to trigger a liquidation:

def check_duration(context, data):  
    for stock in context.holding_time.keys(): # iterate through all stocks in the holding time dictionary  
        context.holding_time[stock] = context.holding_time[stock] + 1 # increment all stocks by 1 day  
    for stock in context.portfolio.positions: # iterate through all stocks in the portfolio  
        if context.holding_time[stock] >= 10: # check if stock has hit 10 days  
            order_target_percent(stock, 0) # liquidate the stock  

Awesome! It works!

Alright, can you help me again?

I've been fiddling with trying to have a brief 3 day hiatus from buying after the sellout, but i can't make it work

any suggestions?

Yea no problem. First add this to your imports:

from datetime import datetime, timedelta  

In the 'initialize' function, add this empty dictionary:

context.Last_Trade_Date = {}  

Then, wherever you have logic to sell out of positions, add the following line after the order:

current_bar = get_datetime('UTC')  
context.Last_Trade_Date[stock] = current_bar  

Then schedule a new function to run once a day with this code:

def Check_Last_Trade_Date(context, data):  
    current_bar = get_datetime('UTC')  
    context.Trade_Ban = {}  
    for stock in context.Last_Trade_Date:  
        if current_bar - timedelta(days=3) < context.Last_Trade_Date[stock]:  
            context.Trade_Ban[stock] = True  
        else:  
            context.Trade_Ban[stock] = False  

Alter the timedelta in the function above to dictate how many days you want the trade ban to last.

Final step is to go to every instance in your algo where you are entering new positions, and use an if statement to make sure the stock is not in the trade ban...psuedo code below:

if context.Trade_Ban[stock] == False:  
    # order stock  
elif context.Trade_Ban[stock] == True:  
    # do not order stock

hmmmm

I implemented it, but when i add the "if context.Trade_Ban[stock] == False: " into the buy logic, i got a key error on Trad_Ban?

*Trade_Ban

  open_orders = get_open_orders()  
        if data.can_trade(stock) & (stock not in open_orders):  
            buy = currentcash > .05 * context.portfolio.portfolio_value  
            if (stock not in context.portfolio.positions):  
                if (buy and last_close < min_close and context.Trade_Ban[stocks] == False):  
                        currentcash -= context.portfolio.portfolio_value * .05  
                        order_target_percent(stock, 0.05)  
                        orders += 1  
                        context.holding_time[stock] = 0  

Oh, stocks that were not previously traded will throw that error. Try to fix with the following:

if stock not in context.Trade_Ban.keys():  
    # order stock  
elif stock in context.Trade_Ban.keys():  
    if context.Trade_Ban[stock] == False:  
        # order stock  
    elif context.Trade_Ban[stock] == True:  
        # do not order stock  

Here is how I changed apposite to your suggestion:

open_orders = get_open_orders()  
        if data.can_trade(stock) & (stock not in open_orders):  
            buy = currentcash > .05 * context.portfolio.portfolio_value  
            if (stock not in context.portfolio.positions):  
                if (buy and last_close < min_close and stock not in context.Trade_Ban.keys()):  
                        currentcash -= context.portfolio.portfolio_value * .05  
                        order_target_percent(stock, 0.05)  
                        orders += 1  
                        context.holding_time[stock] = 0  
                elif stock in context.Trade_Ban.keys():  
                    if context.Trade_Ban[stock] == False:  
                        currentcash -= context.portfolio.portfolio_value * .05  
                        order_target_percent(stock, 0.05)  
                        orders += 1  
                        context.holding_time[stock] = 0  
                    elif context.Trade_Ban[stock] == True:  
                        pass  

I still get a key error on trade ban...

You will just need to find a way to get around the initial edge case where a stock was not previously populated to the Trade_Ban dictionary.

Charles,

Just thought of a better fix...will post in a few hours.

Could use https://www.quantopian.com/posts/waits-simple-per-security-waiting-period-any-number-of-days.
Set waits_max to 11, sell if waits[stock] is 10. The only two lines you need to worry about are marked, in this case would be setting the wait counter for a stock and skipping sell until its time has come.

That method should work as well. One fix is to just populate the context.Trade_Ban dictionary one time in the "before_trading_start" function:

# run this after the context.security_list is obtained  
dummy_count = 0  
if dummy_count == 0:  
    for stock in context.security_list:  
        context.Trade_Ban[stock] = 10 # use some dummy value greater than intended trade ban term  
    dummy_count += 1 # increment to stop this code from running on subsequent days

Kay, Frank

here's what I changed:

def before_trading_start(context, data):  
    """  
    Called every day before market open.  
    """  
    context.output = pipeline_output('my_pipeline')  

    context.security_list = context.output.index  
    # run this after the context.security_list is obtained  
    dummy_count = 0  
    if dummy_count == 0:  
        for stock in context.security_list:  
            context.Trade_Ban[stock] = 10 # use some dummy value greater than intended trade ban term  
            dummy_count += 1 # increment to stop this code from running on subsequent days  

still getting that key error :)