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
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
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?
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.
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 :)