Combining 'Order Optimal Portfolio' with a 'Days Held' Exit.

Hi all. I have an algo that orders on a signal, then keeps track of days the stock is held in a dict. Once n days have passed the position is closed. I am using order_target_percent right now, but I want to use the Optimize API control the portfolio,...only I don't want it to exit any positions unless n days have passed. Is this possible? I have come up empty in my experiments. Any ideas would be appreciated.

5 responses

Maybe something like this.

def close_securities(context, data):
# Starting with a dict securities and the days they are held
# Maybe make a pandas series from it first so it's easy to manipulate
# Then it's easy to get a list of securities held for longer than (in this case) 5 days
held_days_series = pd.Series(held_days_dict)
securities_to_close_list = held_days_series[held_days_series > 5].index.tolist()

# Create a set of the current holdings
# Then remove the securities one wants to close
current_holdings_set = set(context.portfolio.positions.keys())
securities_to_close_set = set(securities_to_close_list)
securities_to_freeze = current_holdings_set - securities_to_close_set

# Create a Frozen constraint from these so they stay as is
freeze_current_holdings = opt.Frozen(securities_to_freeze)

# create an empty (zero) weight objective to close everything
close_all_objective = opt.TargetWeights({})

# Execute the order_optimal_portfolio method with above objective and constraint
order_optimal_portfolio(objective = close_all_objective, constraints = [freeze_current_holdings])


Change the first line to be the dict of securities held too long. Run this as a scheduled function whenever one wishes to close the held too long positions. The attached algorithm isn't exactly like this but should give you some ideas.

Good luck.

That is tremendous, Dan. Thank you! I will reply again later on how I made out with implementing it in my algo.

Dan, I incorporated your idea into my algo, but the days held to exit seem to only be influenced by the offset in the date _rules. Changing the variable in "securities_to_close_list = held_days_series[held_days_series > 5].index.tolist()" is not changing the actual minimum days held. For instance, if I leave the offset at 0, regardless of what the held_days number is set to, the position will be liquidated the day after it is opened. At first I thought my dictionary counter was broken, but when I ran your sample I found the same result...no change in results when changing the days_held variable.

Any idea what might be going on? Possibly I am missing something obvious, as I am very new to Q and coding. With that in mind, please don't judge my code to harshly.

My fault. I misunderstood your original intent. I was thinking you wanted to close positions after a maximum of n days. However, a position could be closed earlier if it fell out of the selection logic. From what I believe you are saying you want sort of the opposite. Keep positions open for a minimum of n days. Is that correct?

If so, just freeze any securities held less than n days. Do this by creating a Frozen constraint and add that to your ordering method. Something like this.

    # Freeze any securities held less than dth days
dth = 10
held_days_series = pd.Series(context.days_elapsed)

securities_to_hold_list = held_days_series[held_days_series < dth].index.tolist()
freeze_securities_to_hold = opt.Frozen(securities_to_hold_list)