Back to Community
How to Create Equal weighted Portfolio

I am trying to create an algorithm with a holding period of 1 day, that selects a number of stocks each and equally weights them, max position size 2%. I am not quite sure how to do this however. My attempt below causes a run time error:

def rebalance(context, data):
# Retrieve alpha from pipeline output
weight = .02
weights = pd.Series(data = weight)

if not alpha.empty:  
   objective = opt.TargetWeights(weights)

AttributeError: 'numpy.int64' object has no attribute 'end_date'
There was a runtime error on line 110.

Can someone suggest an alternative?

Thanks,
Tartaglia

6 responses

The error you are getting is a bit misleading. The TargetWeights objective expects a series with the index being the security objects and the values being the associated weights. You only supplied the weights. By default pandas will assign integers as the index values. The error happens when the objective tries to get the 'end_date' attribute from the integer index (remember it is expecting a security) and it fails.

So, simply supply the securities one wishes to trade as the index. Something like this:

    # Specify a series with the weights we want  
    # Need to specify BOTH the securities (as the index) and the weight  
    my_weights = pd.Series(index=context.my_stocks, data=context.target_weight)  


See the attached algo. Good luck!

Clone Algorithm
1
Loading...
Backtest from to with initial capital
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
"""
This is a stategy to demonstrate ordering by fixed weights

"""

# import pipeline methods 
from quantopian.algorithm import attach_pipeline, pipeline_output
from quantopian.pipeline import Pipeline, CustomFactor

# import the built in filters and factors
from quantopian.pipeline.filters import QTradableStocksUS
from quantopian.pipeline.factors import SimpleMovingAverage

# import any datasets we need
from quantopian.pipeline.data import Fundamentals  
from quantopian.pipeline.data.builtin import USEquityPricing

# import optimize
import quantopian.optimize as opt

# import numpy and pandas just in case
import numpy as np
import pandas as pd


def initialize(context):
    """
    Called once at the start of the algorithm.
    """
    # Set the constant weight we want
    context.target_leverage = 1.0
    context.target_stock_qty = 50
    context.target_weight = context.target_leverage / context.target_stock_qty

    # Set up our pipeline
    attach_pipeline(make_pipeline(), 'pipeline')
    
    # order every day, 1 hour after market open.
    schedule_function(
        my_orders_using_optimize,
        date_rules.every_day(),
        time_rules.market_open(hours=1),
        )
def make_pipeline():
    """
    A function to create our dynamic stock selector (pipeline). Documentation
    on pipeline can be found here:
    https://www.quantopian.com/help#pipeline-title
    """

    # Base universe set to the QTradableStocksUS
    base_universe = QTradableStocksUS()

    # Factor of yesterday's close price.
    yesterday_close = USEquityPricing.close.latest

    pipe = Pipeline(
        columns={
            'close': yesterday_close,
        },
        screen=base_universe
    )
    return pipe


def before_trading_start(context, data):
    """
    Called every day before market open.
    """
    context.output = pipeline_output('pipeline')
    
    # Let's just take the top stocks (in no particular order)
    context.my_stocks = context.output.head(context.target_stock_qty).index

def my_orders_using_optimize(context, data):
    """
    Use Optimize to place orders all at once
    """
    # Specify our series with the weights we want
    # Need to specify BOTH the securities (as the index) and the weight
    my_weights = pd.Series(index=context.my_stocks, data=context.target_weight)
    
    # Create our maximize alpha objective
    weight_objective = opt.TargetWeights(my_weights) 
    
    # Set the constraints
    pass
    
    # Execute the order_optimal_portfolio method with above objective and constraint
    order_optimal_portfolio(objective = weight_objective, 
                            constraints = [])
    
    
There was a runtime error.

Thank you so much Dan.

I have seen the approach you mentioned but my problem is, I do not know how to provide the list of stocks I will be trading. Say my algorithm picks stocks based on sentiment similar to the tutorial, then I am not sure how to create a list of the stocks selected. Is there a simpler way of just automatically equally weighting each stock, rather than having to assign them in a such a list.

You need to be able to tell the TargetWeights method two things: which stocks to trade, and, what the weight of each stock should be. (Otherwise how would it know which stocks to choose. You need to tell it).

Which tutorial are you referring to? Is it Lesson 3 'Pipeline API' (https://www.quantopian.com/tutorials/getting-started#lesson3) ?

When using a pipeline to fetch data, the data is always returned in a dataframe. The dataframe columns are whatever factors, filters, or classifiers you define. The rows are always the security objects (ie the stocks). To get a list of stocks one simply needs to turn the index into a list. Something like this:

my_list_of_stocks = pipeline.output.index.tolist()

Python and Pandas is pretty forgiving. One often doesn't need to supply a strict python list. Often times the index is fine. Just 'list like' is often good enough.

The other thing to remember is that most of the time one wouldn't want to trade ALL the stocks returned in pipeline.output. So, selecting a subset of the dataframe is quite typical. Using the 'Lesson 3' pipeline, we could take the 50 stocks with the highest 'sentiment_score' something like this:

my_best_stock_list = pipeline.output.nlargest(50, 'sentiment_score').index.tolist()

The above could also be done with filters as part of the pipeline definition. Personal preference which way one goes.

Hope that helps?

This helps a lot, thanks so much Dan.

I was indeed referring to lesson 3 from the first tutorial, but I misunderstood where the stock selection process took place.

Your explanation makes perfect sense. In the tutorial they retrieve the sentiment score from context.pipeline_data.sentiment_score and pass that to the optimizer, and let the optimizer do the selection process.

If I create equal weights instead, I have not yet clarified which stocks to select, as you said, I don't want to trade all the stocks.

Thanks so much for the quick help!!!

Glad to help.

The tutorial (jumping ahead to Lesson 7) uses the objective MaximizeAlpha. Unlike the TargetWeights objective it can assign a zero weight to a security if others contribute more to the alpha. In this way it can be thought of as part of the selection process. Perhaps a better way to think of the stocks provided in the index is these are the 'universe' of potential securities to trade. One will always want to prune the list to a meaningful subset of the total securities. The contest requires at least paring down to the QTradableStocksUS.

One challenge you may have going forward is to select stocks you want to long and stocks you want to short. These can become two different 'universes' and you may want to treat them differently. Search the forum posts on ways to do that if you find yourself headed in that direction.

Again, good luck!

I see, that makes sense.

Yeah, I will check those out, thanks for all the help!!!