Quantopian's community platform is shutting down. Please read this post for more information and download your code.
Back to Community
Incorporating "portfolio optimise" into my algo - help get me across the line for competition entry

Hello there

I've developed an algo which meets nearly all of the criteria for inclusion in the competition.

I'm struggling with converting orders from "order_target_percent" method to placing orders with the optimise API.

As I understand it, I will then be able to add constraints which also help satisfy the remaining criteria (leverage, and style risk (the Algo is heavy on mean reversion )) .

My algo produces varying quantities of Buy and Sell signals each day. Positions are held for 6 days.

Here is my code, excluding the pipeline which is where I generate the long and short signals with the secret sauce :-).

Any hints, tips appreciated!!

    return Pipeline(  
        columns={  
            'latest_close' : latest_close,  
             'shorts': shorts,  
             'longs': longs

        },  
        screen=(securities_to_trade),  
    )



def before_trading_start(context, data):  
    # Gets our pipeline output every day.  
    context.output = pipeline_output('my_pipeline')  


    context.portpos_count = len(context.portfolio.positions)  
    print "port pos count:"+str(context.portpos_count)    

    context.shorts = context.output[  
        context.output['shorts']].index.tolist()

    context.longs = context.output[  
        context.output['longs']].index.tolist()

    context.YestPrice = context.output['latest_close']

    context.shorts_sig_count = len(context.shorts)  
    print "shorts sig count:"+str(context.shorts_sig_count)

    context.longs_sig_count = len(context.longs)  
    print "longs sig count:"+str(context.longs_sig_count)  


    context.MyShortsCandidate = cycle(context.shorts)  
    context.MyLongsCandidate = cycle(context.longs)

    for stock in context.portfolio.positions:  
        CurrPrice = float(data.current([stock], 'price'))  
        if stock in context.age:  
            context.age[stock] += 1  
        else:  
            context.age[stock] = 1  
    for stock in context.age:  
        if stock not in context.portfolio.positions:  
            context.age[stock] = 0  
        message = 'Stock.symbol: {symbol}  :  age: {age}'  
        log.info(message.format(symbol=stock.symbol, age=context.age[stock]))

    pass


def rebalance(context, data):  
    cancel_open_orders(context, data)  
#    cancel_open_orders(context, data)

    #checking each stock in the protfolio to see if is ready to exit  
    for stock in context.portfolio.positions:  
        if not get_open_orders(stock):  
            if (stock in context.age and context.age[stock] <days_held ):  
                pass  
            elif (  
                stock in context.age and context.age[stock] >=days_held  
            ):  
                order_target_percent(stock,0)  
            else:  
                context.age[stock] = 1



#process the new longs  
    if context.longs_sig_count == 0:  
        WeightThisBuyOrder = 0  
    else:  
        WeightThisBuyOrder = min(0.04,float((1.00 /days_held)/ context.longs_sig_count))  
    print "WeightThisBuyOrder: "+str(WeightThisBuyOrder)  
    for ThisBuyOrder in range(context.longs_sig_count):  
    #Another fix to accomodate when only 1 signal  
        if context.longs_sig_count < 1:  
             pass  
        else:  
            stock = next(context.MyLongsCandidate)  
            YestPrice = context.YestPrice[stock]  
            CurrPrice = float(data.current([stock], 'price'))  
            if np.isnan(CurrPrice):# | (CurrPrice >YestPrice):  
                pass  # probably best to wait until nan goes away  
            else:  
                BuyPrice = float(CurrPrice)  
                #another fix - needs further investigation  
                if BuyPrice > 0:  
                    order_target_percent(stock,WeightThisBuyOrder)  
                else:  
                    pass  

#process the new shorts  
    if context.shorts_sig_count == 0:  
        WeightThisSellOrder = 0  
    else:  
        WeightThisSellOrder = min(0.04,float((1.00 /days_held)/ context.shorts_sig_count))  
    print "WeightThisSellOrder: "+str(WeightThisSellOrder)  
    for ThisSellOrder in range(context.shorts_sig_count):  
    #Another fix to accomodate when only 1 signal  
        if context.shorts_sig_count < 1:  
             pass  
        else:  
            stock = next(context.MyShortsCandidate)  
            YestPrice = context.YestPrice[stock]  
            CurrPrice = float(data.current([stock], 'price'))  
            if np.isnan(CurrPrice):# | (CurrPrice < YestPrice):  
                pass  # probably best to wait until nan goes away  
            else:  
                SellPrice = float(CurrPrice)  
                #fix  needs investigation  
                if SellPrice > 0:  
                    order_target_percent(stock,-WeightThisSellOrder)  
                else:  
                    pass



def my_record_vars(context, data):  
    """  
    Record variables at the end of each day.  
    """

    # Record our variables.  
    record(leverage=context.account.leverage)  
    record(positions=len(context.portfolio.positions))  
    if 0 < len(context.age):  
        MaxAge = context.age[max(  
            context.age.keys(), key=(lambda k: context.age[k]))]  
        print ("MaxAge: ",MaxAge)  
        record(MaxAge=MaxAge)


def log_open_order(StockToLog):  
    oo = get_open_orders()  
    if len(oo) == 0:  
        return  
    for stock, orders in oo.iteritems():  
        if stock == StockToLog:  
            for o in orders:  
                message = 'Found open order for {amount} shares in {stock}'  
                log.info(message.format(amount=o.amount, stock=stock))


def log_open_orders():  
    oo = get_open_orders()  
    if len(oo) == 0:  
        return  
    for stock, orders in oo.iteritems():  
        for o in orders:  
            message = 'Found open order for {amount} shares in {stock}'  
            log.info(message.format(amount=o.amount, stock=stock))


def cancel_open_orders(context, data):  
    oo = get_open_orders()  
    if len(oo) == 0:  
        return  
    for stock, orders in oo.iteritems():  
        for o in orders:  
            cancel_order(o)

# This is the every minute stuff  
def handle_data(context, data):  
    pass  
2 responses

Hello all - OK, I have it working for the longs :-) "order_optimal_portfolio" works great!

Here is the code:

    # First create a series with the weights for each stock  
    # This can be done a lot of ways.  
    # Using the plain pandas Series method here  
        weight = min(0.04,float((1.00 /days_held)/ context.longs_sig_count))  
        weights = pd.Series(index = context.longs, data = weight)  
    # Next create a TargetWeights object using our weights series  
        target_weights = opt.TargetWeights(weights)  
    # Finally, execute the order_optimal_portfolio method  
    # No need to loop through the stocks.  
    # The order_optimal_portfolio does all the ordering at one time  
    # It returns a series of order_ids. Don't really need to store these but can be useful  
        orders = order_optimal_portfolio(objective = target_weights, constraints = [])  

But when i try and use the same code for the shorts, i get an error when i try and make the weight negative.

# First create a series with the weights for each stock  
    # This can be done a lot of ways.  
    # Using the plain pandas Series method here  
        weight = min(0.04,float((1.00 /days_held)/ context.shorts_sig_count))  
        weights = pd.Series(index = context.shorts, data = weight)  
    # Next create a TargetWeights object using our weights series  
        target_weights = opt.TargetWeights(weights)  
    # Finally, execute the order_optimal_portfolio method  
    # No need to loop through the stocks.  
    # The order_optimal_portfolio does all the ordering at one time  
    # It returns a series of order_ids. Don't really need to store these but can be useful  
        orders = order_optimal_portfolio(objective = -target_weights, constraints = [])  

Is that not the way to specify a short sale?

Any hints tips pls!

Tks

This works!
target_weights = opt.TargetWeights(-weights)