Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
How to use "order_optimal_portfolio" in correctly?(rebalance on different days, or just sell part of holding)

Hi there, because my account does not have margin, I have to rebalance my account by sell first and buy in 2 days later.
So I use schedule_function() to run two jobs: clear_position and buyin_position.
There is another update job where context.STOCKS and context.bond_weights will be updated.
If context.bond_weights is non-zero, that means I am holding bonds.

Sample codes:

def clear_position(context, data):  
    # Sell stocks if they are not hold anymore  
    sell_list = []  
    for s in context.portfolio.positions:  
        s = str(s.symbol)  
        if s not in context.STOCKS:  
            sell_list.append(s)  
    # Sell bonds if they are not hold anymore  
    for s in context.BONDS:  
        if s in context.portfolio.positions and context.bond_weights == 0:  
            sell_list.append(str(s.symbol))

    if len(sell_list) > 0:  
        log.info("Sell:" + str(sell_list))  
        weights = pd.Series(index=sell_list, data=0.0)  
        weights = opt.TargetWeights(weights)  
        order_optimal_portfolio(  
            objective = weights,  
            constraints = []  
        )  
    else:  
        log.info("Hold current portfolio")  
def buyin_position(context, data):  
    """  
    Execute trades using optimize.  
    Expects securities (stocks and bonds) with weights to be in context.weights  
    """  
    # Create a single series from our stock and bond weights  
    total_weights = pd.concat([context.stock_weights, context.bond_weights])  
    # Create a TargetWeights objective  
    target_weights = opt.TargetWeights(total_weights)  
    # Execute the order_optimal_portfolio method with above objective and any constraint  
    order_optimal_portfolio(  
        objective = target_weights,  
        constraints = []  
        )  
    log.info( "Buy in: " + str([s for s in context.STOCKS]) )  
    record(stocks=context.stock_weights.sum(), bonds=context.bond_weights.sum())      

The problem is when I call

        weights = pd.Series(index=sell_list, data=0.0)  
        weights = opt.TargetWeights(weights)  
        order_optimal_portfolio(  
            objective = weights,  
            constraints = []  
        )      

All my portfolios are sold, however, I just want to sell the ones in "sell_list". Please help, thanks!!

3 responses

The default behavior of the order_optimal_portfolio method using the TargetWeights objective is to assume a target weight of zero for any security not explicitly defined in the weights parameter. There are two general approaches to 'over-ride' this behavior and 'hold' certain portions of one's portfolio. Either add the currently held stocks, with the current weights, to the 'weights' series, or, add a Frozen constraint.

The straightforward approach is to use the Frozen constraint (https://www.quantopian.com/docs/api-reference/optimize-api-reference#quantopian.optimize.Frozen). First, create a list of any current holdings that should not change and pass it to this constraint. Typically we would not want to change any current holdings which aren't in our new 'weights' series. Maybe like this


    weights = pd.Series(index=sell_list, data=0.0)  
    weights = opt.TargetWeights(weights)

    # Make a list of stocks which are in the portfolio but not in the weights.  
    # Create a 'Frozen' constraint from this list.  
    hold_list = [stock for stock in context.portfolio.positions if stock not in weights]  
    freeze_these = opt.Frozen(hold_list)

    # Place orders for desired weights but with the 'freeze_these' constraint  
    order_optimal_portfolio(objective=target_weights, constraints=[freeze_these])

There are a couple of forum posts on this topic. Maybe check this one out https://www.quantopian.com/posts/can-someone-demonstrate-a-basic-buy-with-the-new-rule-order-optimal-portfolio

Good luck.

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.

HI Dan, thank you so much for the reply. I read the answer and also read the link you list, but still have a question.

Assume I current holding_list is ['A', 'B', 'C'], and on rebalance day, I got ['A', 'B', 'D']
So on day 1, I want to sell 'C', frozen 'A' and 'B', I think your code explains how to do that.
On day 2 and 3, I will wait for the fund to be cleared.
On day 3, I'll buy 'D' by the cash from selling 'C'
But in the sample code you provide, I have to sell C and buy D at the same time, becasue of this
command "order_optimal_portfolio(objective=target_weights, constraints=[freeze_these])"

So how can I buy 'D' with all cash in my hand..? Thanks again!

    weights = pd.Series(index=sell_list, data=0.0)  
    weights = opt.TargetWeights(weights)

    # Make a list of stocks which are in the portfolio but not in the weights.  
    # Create a 'Frozen' constraint from this list.  
    hold_list = [stock for stock in context.portfolio.positions if stock not in weights]  
    freeze_these = opt.Frozen(hold_list)

    # Place orders for desired weights but with the 'freeze_these' constraint  
    order_optimal_portfolio(objective=target_weights, constraints=[freeze_these])  

And unfortunetely, this line of codes
"order_optimal_portfolio(objective=total_weights, constraints=[freeze_list])"
has a runtime error:
" AttributeError:'Series' object has no attribute 'referenced_assets'
Line: 199 inclear_position
"