Notebook
In [1]:
from quantopian.pipeline.data import factset
from quantopian.pipeline import Pipeline
from quantopian.research import run_pipeline
from quantopian.pipeline.factors import CustomFactor, SimpleMovingAverage
from quantopian.pipeline.filters import QTradableStocksUS
from alphalens.tears import create_information_tear_sheet
from alphalens.utils import get_clean_factor_and_forward_returns
from quantopian.pipeline.filters import QTradableStocksUS
from quantopian.pipeline.experimental import risk_loading_pipeline
from quantopian.pipeline.data.psychsignal import stocktwits
from quantopian.pipeline.data import Fundamentals
from quantopian.pipeline.data.builtin import USEquityPricing

def make_pipeline():

    value = Fundamentals.ebit.latest / Fundamentals.enterprise_value.latest
    quality = Fundamentals.roe.latest
    sentiment_score = SimpleMovingAverage(
        inputs=[stocktwits.bull_minus_bear],
        window_length=3,
    )

    universe = QTradableStocksUS()
    
    value_winsorized = value.winsorize(min_percentile=0.05, max_percentile=0.95)
    quality_winsorized = quality.winsorize(min_percentile=0.05, max_percentile=0.95)
    sentiment_score_winsorized = sentiment_score.winsorize(min_percentile=0.05,                                                                             max_percentile=0.95)

    combined_factor = (
        value_winsorized.zscore() + 
        quality_winsorized.zscore() + 
        sentiment_score_winsorized.zscore()
    )

    longs = combined_factor.top(100, mask=universe)
    
    avg_volume = SimpleMovingAverage(inputs=[USEquityPricing.volume], window_length=50)
    filter_volume = avg_volume > 1000000
    
    stocks_to_trade = longs & filter_volume

    return Pipeline(
        columns={
            'longs': longs,
            'combined_factor': combined_factor
        },
        screen=stocks_to_trade
    )

pip = make_pipeline()
factor_data = run_pipeline(pip, '2010-1-1', '2012-1-1')
factor_data.head(3)
Out[1]:
combined_factor longs
2010-01-04 00:00:00+00:00 Equity(62 [ABT]) 3.264415 True
Equity(739 [BBBY]) 2.632752 True
Equity(1209 [CA]) 2.935585 True
In [2]:
pricing_data = get_pricing(factor_data.index.levels[1], '2010-1-1', '2012-2-1', fields='open_price')
pricing_data.head(3)
Out[2]:
Equity(62 [ABT]) Equity(64 [GOLD]) Equity(76 [TAP]) Equity(114 [ADBE]) Equity(122 [ADI]) Equity(128 [ADM]) Equity(161 [AEP]) Equity(166 [AES]) Equity(168 [AET]) Equity(185 [AFL]) ... Equity(39626 [EXPR]) Equity(39797 [OAS]) Equity(39918 [RLD]) Equity(39921 [QLIK]) Equity(40299 [CHMT]) Equity(40353 [SODA]) Equity(40430 [GM]) Equity(40606 [KNX]) Equity(40607 [AG]) Equity(41182 [GNC])
2010-01-04 00:00:00+00:00 50.092 39.892 43.176 36.65 30.081 30.200 31.793 13.38 31.523 44.242 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2010-01-05 00:00:00+00:00 50.351 39.853 43.422 37.04 29.996 30.267 31.685 13.67 32.389 45.213 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN
2010-01-06 00:00:00+00:00 49.861 40.500 43.100 37.33 30.005 30.315 31.304 13.45 31.956 47.411 ... NaN NaN NaN NaN NaN NaN NaN NaN NaN NaN

3 rows × 685 columns

In [3]:
merged_data = get_clean_factor_and_forward_returns(factor=factor_data, prices=pricing_data)
merged_data.head(3)

ValueErrorTraceback (most recent call last)
<ipython-input-3-c7eb5f36075d> in <module>()
----> 1 merged_data = get_clean_factor_and_forward_returns(factor=factor_data, prices=pricing_data)
      2 merged_data.head(3)

/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, ndim, fastpath, placement, **kwargs)
   1661 
   1662         super(ObjectBlock, self).__init__(values, ndim=ndim, fastpath=fastpath,
-> 1663                                           placement=placement, **kwargs)
   1664 
   1665     @property

/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 2, placement implies 1
In [ ]:
create_information_tear_sheet(merged_data)
In [ ]:
create_returns_tear_sheet(merged_data)
In [ ]: