Notebook
In [1]:
import numpy as np
import pandas as pd
from quantopian.research import run_pipeline
from quantopian.pipeline import Pipeline
from quantopian.pipeline.data.builtin import USEquityPricing
from quantopian.pipeline.factors import CustomFactor, Returns
from quantopian.pipeline.classifiers.fundamentals import Sector  
from quantopian.pipeline.filters import QTradableStocksUS
import alphalens as al
         

universe = QTradableStocksUS()

pipe = Pipeline(
    columns = {
            'universe' : universe,
    },
    screen=universe
)

stock_universe = run_pipeline(pipe, '2015-01-01', '2017-12-28')
In [2]:
factor = []
forward_returns = []

year = None
month = None
# loop through each day
for timestamp, daily_factor in stock_universe.groupby(level=0):

    # just to update user on processing progress
    if (year != timestamp.year) or (month != timestamp.month):
        print "Processing", timestamp.year, timestamp.month
        year = timestamp.year
        month = timestamp.month
        
    # equities in the universe at that particular day
    equities = daily_factor.index.levels[1]
    
    # we use get_pricing() with minute resolution to fetch the minute prices at that particular day
    __prices = get_pricing(equities, timestamp, timestamp, frequency='minute', fields='price', start_offset=1)

    if len(__prices) < 242:
        continue

    # compute factor
    __factor = __prices.iloc[:2].pct_change().iloc[1:] # yesterday close to today open gap
    __factor = -__factor # mean reverting
    factor.append(__factor)
    
    # use Alphalens to compute forward returns for 30m, 60m, 90m, 120m, 180m, 240m
    __forward_returns = al.utils.compute_forward_returns(__factor.stack(),
                                                         __prices,
                                                         periods=(30, 60, 90, 120, 180, 240))
    forward_returns.append(__forward_returns)
Processing 2015 1
Processing 2015 2
Processing 2015 3
Processing 2015 4
Processing 2015 5
Processing 2015 6
Processing 2015 7
Processing 2015 8
Processing 2015 9
Processing 2015 10
Processing 2015 11
Processing 2015 12
Processing 2016 1
Processing 2016 2
Processing 2016 3
Processing 2016 4
Processing 2016 5
Processing 2016 6
Processing 2016 7
Processing 2016 8
Processing 2016 9
Processing 2016 10
Processing 2016 11
Processing 2016 12
Processing 2017 1
Processing 2017 2
Processing 2017 3
Processing 2017 4
Processing 2017 5
Processing 2017 6
Processing 2017 7
Processing 2017 8
Processing 2017 9
Processing 2017 10
Processing 2017 11
Processing 2017 12
In [3]:
forward_returns = pd.concat(forward_returns)
In [4]:
factor = pd.concat(factor).stack()
In [5]:
factor_data = al.utils.get_clean_factor(factor=factor,
                                        forward_returns=forward_returns,
                                        quantiles=7)
Dropped 0.4% entries from factor data: 0.0% in forward returns computation and 0.4% in binning phase (set max_loss=0 to see potentially suppressed Exceptions).
max_loss is 35.0%, not exceeded: OK!
In [7]:
al.tears.create_returns_tear_sheet(factor_data)
Returns Analysis
30m 1h 1h30m 2h 3h 4h
Ann. alpha 9.527656e+27 4.386871e+13 1.229169e+09 5005361.824 25596.952 1975.982
beta 2.100000e-01 2.050000e-01 1.080000e-01 0.046 0.102 0.105
Mean Period Wise Return Top Quantile (bps) 3.944000e+01 1.927100e+01 1.288600e+01 9.536 6.353 4.831
Mean Period Wise Return Bottom Quantile (bps) -4.640000e+01 -2.316600e+01 -1.546500e+01 -11.543 -7.621 -5.819
Mean Period Wise Spread (bps) 8.451700e+01 4.180300e+01 2.793400e+01 20.771 13.764 10.477
/usr/local/lib/python2.7/dist-packages/alphalens/performance.py:392: UserWarning: 'freq' not set, using business day calendar
  UserWarning)
<matplotlib.figure.Figure at 0x7f24bade0050>
In [8]:
al.tears.create_information_tear_sheet(factor_data)
Information Analysis
30m 1h 1h30m 2h 3h 4h
IC Mean 0.231 0.204 0.193 0.181 0.170 0.166
IC Std. 0.110 0.107 0.106 0.105 0.106 0.106
Risk-Adjusted IC 2.101 1.902 1.814 1.726 1.610 1.565
t-stat(IC) 57.372 51.944 49.546 47.136 43.982 42.734
p-value(IC) 0.000 0.000 0.000 0.000 0.000 0.000
IC Skew 0.453 0.575 0.547 0.585 0.590 0.585
IC Kurtosis 2.788 3.156 2.997 3.070 3.087 3.090
<matplotlib.figure.Figure at 0x7f24b347b1d0>
In [ ]:
# This doesn't make sense in this analysis
#al.tears.create_turnover_tear_sheet(factor_data)