Back to Community
Alphalens ValueError: Wrong number of items passed 4, placement implies 1 with get_clean_factor_and_forward_returns

Dear quantopian community, I've little problem with the factor items passed.
Alphalens it's giving me problems to work with a factor_data pipeline that have 4 item column.
The screener is working right, but I get valueerror about the items passed when execute the method get_clean_factor_and_forward_returns()


ValueError: Wrong number of items passed 4, placement implies 1



ValueErrorTraceback (most recent call last)  
<ipython-input-17-c82e73b233ec> in <module>()  
      4   factor=factor_data,  
      5   prices=pricing_data,  
----> 6   periods=range(1,252,22) # The third argument to the range statement changes the "step" of the range  
      7  
      8 )

/usr/local/lib/python2.7/dist-packages/alphalens/utils.pyc in get_clean_factor_and_forward_returns(factor, prices, groupby, binning_by_group, quantiles, bins, periods, filter_zscore, groupby_labels, max_loss, zero_aware, cumulative_returns)
    797                                    quantiles=quantiles, bins=bins,  
    798                                    binning_by_group=binning_by_group,  
--> 799                                    max_loss=max_loss, zero_aware=zero_aware)  
    800  
    801     return factor_data

/usr/local/lib/python2.7/dist-packages/alphalens/utils.pyc in get_clean_factor(factor, forward_returns, groupby, binning_by_group, quantiles, bins, groupby_labels, max_loss, zero_aware)
    564  
    565     merged_data = forward_returns.copy()  
--> 566     merged_data['factor'] = factor_copy  
    567  
    568     if groupby is not None:

/usr/local/lib/python2.7/dist-packages/pandas/core/frame.pyc in __setitem__(self, key, value)
   2355         else:  
   2356             # set column  
-> 2357             self._set_item(key, value)  
   2358  
   2359     def _setitem_slice(self, key, value):

/usr/local/lib/python2.7/dist-packages/pandas/core/frame.pyc in _set_item(self, key, value)
   2422         self._ensure_valid_index(value)  
   2423         value = self._sanitize_column(key, value)  
-> 2424         NDFrame._set_item(self, key, value)  
   2425  
   2426         # check if we are modifying a copy

/usr/local/lib/python2.7/dist-packages/pandas/core/generic.pyc in _set_item(self, key, value)
   1462  
   1463     def _set_item(self, key, value):  
-> 1464         self._data.set(key, value)  
   1465         self._clear_item_cache()  
   1466 

/usr/local/lib/python2.7/dist-packages/pandas/core/internals.pyc in set(self, item, value, check)
   3416         except KeyError:  
   3417             # This item wasn't present, just insert at end  
-> 3418             self.insert(len(self.items), item, value)  
   3419             return  
   3420 

/usr/local/lib/python2.7/dist-packages/pandas/core/internals.pyc in insert(self, loc, item, value, allow_duplicates)
   3517  
   3518         block = make_block(values=value, ndim=self.ndim,  
-> 3519                            placement=slice(loc, loc + 1))  
   3520  
   3521         for blkno, count in _fast_count_smallints(self._blknos[loc:]):

/usr/local/lib/python2.7/dist-packages/pandas/core/internals.pyc in make_block(values, placement, klass, ndim, dtype, fastpath)
   2516                      placement=placement, dtype=dtype)  
   2517  
-> 2518     return klass(values, ndim=ndim, fastpath=fastpath, placement=placement)  
   2519  
   2520 # TODO: flexible with index=None and/or items=None

/usr/local/lib/python2.7/dist-packages/pandas/core/internals.pyc in __init__(self, values, placement, ndim, fastpath)
     88             raise ValueError('Wrong number of items passed %d, placement '  
     89                              'implies %d' % (len(self.values),  
---> 90                                              len(self.mgr_locs)))  
     91  
     92     @property

ValueError: Wrong number of items passed 4, placement implies 1

Screener

from quantopian.pipeline.data import factset  
from quantopian.pipeline import Pipeline  
from quantopian.pipeline.data import USEquityPricing  
from quantopian.pipeline.data.psychsignal import stocktwits  
from quantopian.pipeline.factors import SimpleMovingAverage  
from quantopian.pipeline.factors import Returns  
from quantopian.pipeline.factors import SimpleBeta  
from quantopian.pipeline.experimental import QTradableStocksUS  
from quantopian.pipeline.factors import AverageDollarVolume, Returns  
from quantopian.pipeline.data.builtin import USEquityPricing  
from quantopian.pipeline.data.factset import Fundamentals  
from quantopian.pipeline.data.morningstar import Fundamentals  
from quantopian.pipeline.data.morningstar import earnings_report  
from quantopian.pipeline.domain import US_EQUITIES  
from quantopian.pipeline.data import morningstar  
from quantopian.pipeline import CustomFactor  
from quantopian.pipeline import Pipeline  
from quantopian.research import run_pipeline  
from quantopian.pipeline.filters import QTradableStocksUS

def make_pipeline():

    # Measures a company's asset growth rate.  
    asset_growth = factset.Fundamentals.assets_gr_qf.latest 

    # Get latest closing price  
    close_price = USEquityPricing.close.latest  
    #Return  
    return_2d = Returns(inputs=[USEquityPricing.close], window_length=2)  
     # Measures a company's asset growth rate.  
    #asset_growth = factset.Fundamentals.assets_gr_qf.latest  
    pe_ratio = Fundamentals.pe_ratio.latest  
    earningsreport = earnings_report.diluted_eps.latest  
    #earningsreport1yearago = earnings_report.diluted_eps.latest  
    # Calculate 3 day average of bull_minus_bear scores  
    sentiment_score = SimpleMovingAverage(  
        inputs=[stocktwits.bull_minus_bear],  
        window_length=1,  
    )  

    class Previous(CustomFactor):  
    # Returns value of input x trading days ago where x is the window_length  
    # Both the inputs and window_length must be specified as there are no defaults

        def compute(self, today, assets, out, inputs):  
            out[:] = inputs[0]  
    eps_1_year_ago = Previous(inputs = [morningstar.earnings_report.diluted_eps], window_length = 252)  
    eps_last_qtr = Previous(inputs = [morningstar.earnings_report.diluted_eps], window_length = 63)  

    return Pipeline(  
      columns={'sentiment_score': sentiment_score,  
            'pe_ratio': pe_ratio,  
            'earningsreport': earningsreport,  
            'eps_1_year_ago': eps_1_year_ago},  
      screen= QTradableStocksUS() & (sentiment_score<=-3.00) & (pe_ratio<=25.0) & (earningsreport>eps_1_year_ago)  
    )

factor_data = run_pipeline(pipeline=make_pipeline(), start_date='2016-1-1', end_date='2017-1-1')

# Show the first 5 rows of factor data  
factor_data.head(5)  

Pricing Data

pricing_data = get_pricing(  
  symbols=factor_data.index.levels[1], # Finds all assets that appear at least once in "factor_data"  
  start_date='2016-1-1',  
  end_date='2018-2-1', # must be after run_pipeline()'s end date. Explained more in lesson 4  
  fields='open_price' # Generally, you should use open pricing. Explained more in lesson 4  
)

# Show the first 5 rows of pricing_data  
pricing_data.head(5)

Here there is the Alphalens get clean factor that is giving ValueError

from alphalens.utils import get_clean_factor_and_forward_returns

merged_data = get_clean_factor_and_forward_returns(  
  factor=factor_data,  
  prices=pricing_data  
)

# Show the first 5 rows of merged_data  
merged_data.head(5)

ValueError: Wrong number of items passed 4, placement implies 1

2 responses

Any suggestions about the 1 item limit?

Alphalens is a tool created to analyze a single factor. It compares factor data to future prices to see if a theoretical predictive relationship. The factor (or signal as it's sometimes referred) must be formatted as a single column pipeline output. More specifically, the factor needs to be stored in a pandas multiIndex series indexed by timestamp (level 0) and asset (level 1). The best way to get a factor in this output format is to run a pipeline and select a single column representing the factor one wishes to analyze. Take a look at the documentation here https://www.quantopian.com/docs/user-guide/tools/alphalens .

So, in this case, it seems there are 4 factors being returned by the pipeline.
- sentiment_score
- pe_ratio
- earningsreport
- eps_1_year_ago

One can only analyze a single factor a time. As an example, to check if there may be a predictive relationship of sentiment_score to future prices, then select that single column and pass it to the get_clean_factor_and_forward_returns method. Since there are no spaces in the column names one can do this easily with dot notation. Something like this.

merged_data = get_clean_factor_and_forward_returns(  
  factor=factor_data.sentiment_score,  
  prices=pricing_data  
)

Do something similar for each of the four factors to analyze them one at a time.

Typically one would see which factor(s) have significant potential on their own like this. Then, if there appears to be more than one strong contender, combine those factors into a single 'super factor'. Often several mediocre factors can combine to be better than any one individually. There are many ways to combine factors linearly and non-linearly. Maybe take a look at these posts for ideas.

https://www.quantopian.com/posts/how-to-combine-factors-in-alphalens

https://www.quantopian.com/posts/combining-weighted-factors

Hope that helps.

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.