Notebook

Alphalens + Quantopian | How To

For more information on how to read and understand the plots look at:

In [8]:
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, AverageDollarVolume
from quantopian.pipeline.classifiers.morningstar import Sector
In [2]:
import datetime
from sqlalchemy import or_

fundamentals = init_fundamentals()

universe = get_fundamentals(query(fundamentals.valuation.market_cap)
        .filter(fundamentals.operation_ratios.total_debt_equity_ratio != None)
        .filter(fundamentals.valuation.market_cap != None)
        .filter(fundamentals.valuation.shares_outstanding != None)  
        .filter(fundamentals.company_reference.primary_exchange_id != "OTCPK") # no pink sheets
        .filter(fundamentals.company_reference.primary_exchange_id != "OTCBB") # no pink sheets
        .filter(fundamentals.asset_classification.morningstar_sector_code != None) # require sector
        .filter(fundamentals.share_class_reference.security_type == 'ST00000001') # common stock only
        .filter(~fundamentals.share_class_reference.symbol.contains('_WI')) # drop when-issued
        .filter(fundamentals.share_class_reference.is_primary_share == True) # remove ancillary classes
        .filter(((fundamentals.valuation.market_cap*1.0) / (fundamentals.valuation.shares_outstanding*1.0)) > 1.0)  # stock price > $1
        .filter(fundamentals.share_class_reference.is_depositary_receipt == False) # !ADR/GDR
        .filter(fundamentals.valuation.market_cap > 30000000) # cap > $30MM
        .filter(~fundamentals.company_reference.standard_name.contains(' LP')) # exclude LPs
        .filter(~fundamentals.company_reference.standard_name.contains(' L P'))
        .filter(~fundamentals.company_reference.standard_name.contains(' L.P'))
        .filter(fundamentals.balance_sheet.limited_partnership == None) # exclude LPs
        .order_by(fundamentals.valuation.market_cap.desc())
        .limit(100), "2016-01-01")
In [26]:
simulation_data = get_pricing(universe.columns,
                              start_date="2016-01-04",
                              end_date="2016-03-04",
                              frequency="minute",
                              fields="price")
In [27]:
factor = pd.rolling_mean(simulation_data, 5) / pd.rolling_mean(simulation_data, 60)
In [28]:
factor = factor.dropna()
In [29]:
signal = factor.stack()
In [33]:
signal.head()
Out[33]:
2016-01-04 16:20:00+00:00  Equity(24 [AAPL])         0.997678
                           Equity(26578 [GOOG_L])    1.004111
                           Equity(5061 [MSFT])       0.998687
                           Equity(8347 [XOM])        0.996444
                           Equity(11100 [BRK_B])     0.998250
dtype: float64

Get pricing

In [34]:
assets = signal.index.levels[1].unique()
# We need to get a little more pricing data than the 
# length of our factor so we can compare forward returns.
# We'll tack on another month in this example.
pricing = get_pricing(assets, start_date='2016-01-04', end_date='2016-03-04', fields='open_price', frequency="minute")

Use Alphalens to create a factor tear sheet

In [35]:
import alphalens

alphalens.tears.create_factor_tear_sheet(factor=signal, prices=pricing)
Returns Analysis
1 5 10
Ann. alpha 0.000 -0.000 -0.000
beta 0.000 0.000 -0.000
Mean Daily Return Top Quantile (bps) 0.320 0.024 -0.002
Mean Daily Return Bottom Quantile (bps) -0.273 0.011 0.023
Mean Daily Spread (bps) 1.782 0.279 0.078
Information Analysis
1 5 10
IC Mean 0.036 0.008 -0.000
IC Std. 0.168 0.179 0.185
t-stat(IC) 14.558 3.200 -0.118
p-value(IC) 0.000 0.001 0.906
IC Skew -0.088 -0.040 -0.090
IC Kurtosis 0.086 0.023 0.070
Ann. IR 3.424 0.753 -0.028
Turnover Analysis
Top Quantile Bottom Quantile
Mean Turnover 0.076 0.079
Mean Factor Rank Autocorrelation -0.032
<matplotlib.figure.Figure at 0x7fb4350bca90>