Back to Community
Help With Optimize TargetWeights

I am really confused with how optimize works and am having trouble comprehending what is going on with this algo. My pipeline returns 10 stocks and with order_target_percent I can get 5% allocations in each stock but when I try and use the new optimize target weights for .05 the algo seems to purchase each stock, sell most minutes later and hold only a couple overnight with the wrong weights. Any help or insight would be appreciated.

Clone Algorithm
10
Loading...
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
import quantopian.optimize as opt
import quantopian.algorithm as algo

from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import AverageDollarVolume, SimpleMovingAverage
from quantopian.pipeline.filters import Q1500US
from quantopian.pipeline.experimental import QTradableStocksUS

def initialize(context):
    
    universe = QTradableStocksUS()
    
    pipe = Pipeline()
    
    attach_pipeline(pipe, name ='pipeline')
    
    avg_price = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=10, mask=universe)
    
    min_price = avg_price.top(10)
    
    pipe.set_screen(min_price)
     
    schedule_function(trade, date_rules.every_day(), time_rules.market_open())
 
def before_trading_start(context, data):
    
    context.output = pipeline_output('pipeline')
  
    context.stocks = context.output.index
    
    num = len((context.stocks))
    print '%s stocks in pipeline' % num
     
def trade(context, data):
    
    for stock in context.stocks:
        target = opt.TargetWeights({stock:0.05})
        
        if data.can_trade(stock):
            algo.order_optimal_portfolio(objective = target, constraints = [])
            print 'bought %s' % stock
            #order_target_percent(stock, .05)
            
    
        
    
    
    

There was a runtime error.
4 responses

Jay has order_optimal_portfolio() within a loop above. Is there a way to order individual stocks selectively with Optimize? Below is more like I'm currently using in case it might help get you rolling.

Clone Algorithm
4
Loading...
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
import quantopian.optimize as opt
import quantopian.algorithm as algo
from quantopian.pipeline.classifiers.morningstar import Sector
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import AverageDollarVolume, SimpleMovingAverage
from quantopian.pipeline.filters import Q1500US
from quantopian.pipeline.experimental import QTradableStocksUS

def make_pipeline():
    m   = Sector().notnull() & QTradableStocksUS()
    sma = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=10, mask=m)
    return Pipeline(
        screen  = m & sma.top(10),
        columns = {
            'sma'   : -sma,
            'sector': Sector(mask=m),
        })

def initialize(context):
    attach_pipeline(make_pipeline(), 'pipeline')
    
    schedule_function(trade, date_rules.every_day(), time_rules.market_open())

def before_trading_start(context, data):
    context.output = pipeline_output('pipeline')
    context.stocks = context.output.index
    num = len((context.stocks))
    print '%s stocks in pipeline' % num

def trade(context, data):

    order_optimal_portfolio(
        objective = opt.MaximizeAlpha(context.output.sma),
        constraints=[
            opt.MaxGrossExposure(1.0),
            opt.PositionConcentration.with_equal_bounds(-.015, .015),
            opt.DollarNeutral(),    # Same amount of capital to long and short.
            opt.NetGroupExposure.with_equal_bounds(   # Net leverage in each sector.
                labels = context.output.sector,
                min = -0.0001,
                max =  0.0001,
            ),
        ],
    )
    '''
    for stock in context.stocks:
        target = opt.TargetWeights({stock:0.05})

        if data.can_trade(stock):
            algo.order_optimal_portfolio(objective = target, constraints = [])
            print 'bought %s' % stock
            #order_target_percent(stock, .05)
    '''

There was a runtime error.

One confusion with the 'order_optimal_portfolio' may be that it places the orders all at once (unlike the 'order_target' methods). Therefore, there's no need to loop through all the stocks one wants to order. Simply set up a pandas series, or python dict, associating each security with it's desired weight. Use that series to create a 'TargetWeights' objective, then use that objective when executing the 'order_optimal_portfolio' method.

Any securities not in 'TargetWeights' will be assumed to have a target of 0 percent. Therefore, 'order_optimal_portfolio' will try to close any open positions without a weight. This is the cause of the behavior "the algo seems to purchase each stock, sell most minutes later and hold only a couple overnight with the wrong weights". Looping through 'order_optimal_portfolio' with a single weight in each iteration will try and close positions from previous iterations (because it assumes a zero weight).

The 'order_optimal_portfolio' method also checks for 'can_trade'. It's not required to explicitly do this. It won't cause an error if a security can't trade (though will log a warning). However, there could be reasons to check if a security can trade and one can still do it anyway. One may always want to hold a fixed number of securities so verifying they all can trade may be important.

@Blue Seahawk uses the 'positionConcentration.with_equal_bounds constraint (not objective) to get equal weighting. If using other constraints this is a good way to go. Other constraints may want to tweek the desired weights so it's good to give those weights a range. However, for plain down and dirty order a fixed weight of each security then using the 'TargetWeights' objective is very straightforward.

See attached algorithm. Take a look at the logs for the trades which were placed. Good luck.

Clone Algorithm
27
Loading...
Total Returns
--
Alpha
--
Beta
--
Sharpe
--
Sortino
--
Max Drawdown
--
Benchmark Returns
--
Volatility
--
Returns 1 Month 3 Month 6 Month 12 Month
Alpha 1 Month 3 Month 6 Month 12 Month
Beta 1 Month 3 Month 6 Month 12 Month
Sharpe 1 Month 3 Month 6 Month 12 Month
Sortino 1 Month 3 Month 6 Month 12 Month
Volatility 1 Month 3 Month 6 Month 12 Month
Max Drawdown 1 Month 3 Month 6 Month 12 Month
import quantopian.optimize as opt
import quantopian.algorithm as algo

from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import AverageDollarVolume, SimpleMovingAverage
from quantopian.pipeline.filters import Q1500US
from quantopian.pipeline.experimental import QTradableStocksUS

# Import numpy to use of all the powerful methods
import pandas as pd


def initialize(context):
    
    universe = QTradableStocksUS()
    
    pipe = Pipeline()
    
    attach_pipeline(pipe, name ='pipeline')
    
    avg_price = SimpleMovingAverage(inputs=[USEquityPricing.close], window_length=10, mask=universe)
    
    min_price = avg_price.top(10)
    
    pipe.set_screen(min_price)
     
    schedule_function(trade, date_rules.every_day(), time_rules.market_open())
 
def before_trading_start(context, data):
    
    context.output = pipeline_output('pipeline')
  
    context.stocks = context.output.index
    
    num = len((context.stocks))
    print '%s stocks in pipeline' % num
     
def trade(context, data):
    
    # 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 = .05
    weights = pd.Series(index = context.stocks, 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 = [])
            
    # One could log the orders which were placed
    for order_id in orders:
        order = get_order(order_id)
        log.info('ordered {} shares of {}'.format(order.amount, order.sid))
    
            
    
        
    
    
    

There was a runtime error.

This was very helpful, thank you

What is the best way to ensure a minimum amounts of positions using Optimize, but sized based on conviction? E.g. 500 positions in the portfolio with sizing for stock x ranked #1 being higher than stock y ranked #400. I'm having difficulty arriving at an in between of MaximizeAlpha and TargetWeight, the former resulting in variable position sizing but uncertain # of positions and the latter resulting in fixed sizing and # of positions. I want variable sizing but fixed # of positions.