Notebook
In [1]:
import numpy as np
import pandas as pd
import time
from quantopian.pipeline import Pipeline
import quantopian.pipeline.data as d
import quantopian.research as r
import quantopian.pipeline.factors as fac
import quantopian.pipeline.filters as f
import math
import alphalens as al
import matplotlib.pyplot as plt
In [2]:
unv = f.Q1500US()
In [5]:
def gen_factor_data(factor):
    assets = factor.index.levels[1].unique()
    pricing_data = get_pricing(assets, start, end, fields='close_price')
    factor_data = al.utils.get_clean_factor_and_forward_returns(factor=factor, prices=pricing_data)
    return factor_data

def make_pipeline():
    return Pipeline(screen=unv)
In [6]:
# parameters
start = '2003-02-01'
end = '2020-01-01'
mkt = symbols('SPY') # used to calculate beta, feel free to use other markets 
In [8]:
p = make_pipeline()

lbeta1yr = -fac.SimpleBeta(mkt, regression_length=252)
lbeta1yr = lbeta1yr.rank(mask=unv).zscore(mask=unv)
p.add(lbeta1yr, 'low')

p.add(fac.SimpleBeta(mkt, regression_length=252), 'beta')
In [9]:
df = r.run_pipeline(p, start, end)

Pipeline Execution Time: 4 Minutes, 51.84 Seconds
In [12]:
xs = df['beta']*df['low']
alpha = -xs[xs > 0].groupby(level=0).sum()/xs[xs <= 0].groupby(level=0).sum()

df['wn'] = df.align(alpha, level=0, axis=0)[1]
df['wp'] = 1
df['w'] = np.where(df['low'] <= 0, df['wn'], df['wp'])
df['low_adj'] = df['w']*df['low']
df
Out[12]:
beta low wn wp w low_adj
2003-02-03 00:00:00+00:00 Equity(2 [HWM]) 1.200405 -1.137340 0.339526 1 0.339526 -0.386156
Equity(24 [AAPL]) 1.029856 -0.747326 0.339526 1 0.339526 -0.253736
Equity(41 [ARCB]) 0.608036 0.827266 0.339526 1 1.000000 0.827266
Equity(52 [ABM]) 0.728395 0.345199 0.339526 1 1.000000 0.345199
Equity(60 [ABS]) 0.641897 0.735213 0.339526 1 1.000000 0.735213
Equity(62 [ABT]) 0.721622 0.374268 0.339526 1 1.000000 0.374268
Equity(67 [ADSK]) 1.122936 -0.994415 0.339526 1 0.339526 -0.337630
Equity(76 [TAP]) 0.409351 1.374740 0.339526 1 1.000000 1.374740
Equity(88 [ACI]) 0.973942 -0.594711 0.339526 1 0.339526 -0.201920
Equity(107 [ACV]) 0.381743 1.423189 0.339526 1 1.000000 1.423189
Equity(110 [RAMP]) 0.939175 -0.468744 0.339526 1 0.339526 -0.159151
Equity(114 [ADBE]) 1.497944 -1.408654 0.339526 1 0.339526 -0.478274
Equity(115 [ADCT]) 2.172877 -1.709038 0.339526 1 0.339526 -0.580262
Equity(122 [ADI]) 1.912787 -1.629097 0.339526 1 0.339526 -0.553120
Equity(128 [ADM]) 0.407798 1.379585 0.339526 1 1.000000 1.379585
Equity(146 [AD]) 0.784558 0.098109 0.339526 1 1.000000 0.098109
Equity(161 [AEP]) 1.054775 -0.817577 0.339526 1 0.339526 -0.277588
Equity(166 [AES]) 2.078706 -1.694503 0.339526 1 0.339526 -0.575327
Equity(168 [AET]) 0.831834 -0.112644 0.339526 1 0.339526 -0.038245
Equity(185 [AFL]) 0.947663 -0.514770 0.339526 1 0.339526 -0.174778
Equity(197 [AGCO]) 0.733383 0.323397 0.339526 1 1.000000 0.323397
Equity(198 [AGE]) 1.258349 -1.205169 0.339526 1 0.339526 -0.409186
Equity(205 [AGN]) 0.743878 0.289483 0.339526 1 1.000000 0.289483
Equity(209 [AM]) 0.754428 0.245879 0.339526 1 1.000000 0.245879
Equity(216 [HES]) 0.713117 0.408183 0.339526 1 1.000000 0.408183
Equity(239 [AIG]) 1.248454 -1.195479 0.339526 1 0.339526 -0.405896
Equity(247 [AIN]) 0.672495 0.633470 0.339526 1 1.000000 0.633470
Equity(266 [AJG]) 0.852400 -0.170783 0.339526 1 0.339526 -0.057985
Equity(289 [MATX]) 0.877881 -0.250723 0.339526 1 0.339526 -0.085127
Equity(290 [ALFA]) 0.755972 0.236189 0.339526 1 1.000000 0.236189
... ... ... ... ... ... ... ...
2020-01-02 00:00:00+00:00 Equity(52998 [LEVI]) 0.563492 1.250468 0.336730 1 1.000000 1.250468
Equity(53023 [LYFT]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53046 [TW]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53064 [PD]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53083 [TPTX]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53089 [PINS]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53095 [ZM]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53116 [BYND]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53148 [KTB]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53158 [UBER]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53179 [FSLY]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53181 [AVTR]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53196 [CTVA]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53238 [RVLV]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53244 [AMCR]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53248 [CRWD]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53256 [CHWY]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53260 [IAA]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53271 [WORK]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53273 [GO]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53304 [ADPT]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53313 [REAL]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53314 [KRTX]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53362 [MDLA]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53379 [LVGO]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53403 [DT]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53478 [SDC]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53498 [NVST]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53511 [DDOG]) NaN NaN 0.336730 1 1.000000 NaN
Equity(53535 [PTON]) NaN NaN 0.336730 1 1.000000 NaN

6364169 rows × 6 columns

In [13]:
ax = ((1-alpha)/(1+alpha)).plot(label='Net long exposure')
vals = ax.get_yticks() 
ax.set_yticklabels(['{: ,.0%}'.format(x) for x in vals])
ax.legend()
Out[13]:
<matplotlib.legend.Legend at 0x7f1c07562a20>
In [23]:
df.loc['2003-02-03']['beta'].plot(kind='hist', bins=100)
Out[23]:
<matplotlib.axes._subplots.AxesSubplot at 0x7f1b7452ccf8>
In [14]:
df['beta'].groupby(level=0).skew().plot(label='Skew of Beta').legend()
Out[14]:
<matplotlib.legend.Legend at 0x7f1c08b506d8>
In [15]:
lows_adj = gen_factor_data(df['low_adj'])
lows = gen_factor_data(df['low'])
Dropped 1.6% entries from factor data: 1.6% in forward returns computation and 0.0% in binning phase (set max_loss=0 to see potentially suppressed Exceptions).
max_loss is 35.0%, not exceeded: OK!
Dropped 1.6% entries from factor data: 1.6% in forward returns computation and 0.0% in binning phase (set max_loss=0 to see potentially suppressed Exceptions).
max_loss is 35.0%, not exceeded: OK!
In [16]:
al.tears.create_full_tear_sheet(lows)
Quantiles Statistics
min max mean std count count %
factor_quantile
1 -1.730896 -1.031011 -1.385493 0.200082 1254110 20.026268
2 -1.044153 -0.340056 -0.693025 0.199727 1251674 19.987369
3 -0.355112 0.352322 -0.001164 0.199742 1251549 19.985373
4 0.333537 1.042778 0.690911 0.199859 1251674 19.987369
5 1.023004 1.730896 1.384061 0.200444 1253318 20.013621
Returns Analysis
1D 5D 10D
Ann. alpha 0.034 0.036 0.037
beta -0.380 -0.384 -0.371
Mean Period Wise Return Top Quantile (bps) -0.928 -0.875 -0.755
Mean Period Wise Return Bottom Quantile (bps) 0.621 0.489 0.241
Mean Period Wise Spread (bps) -1.549 -1.283 -0.926
<matplotlib.figure.Figure at 0x7f1c2faa2710>
Information Analysis
1D 5D 10D
IC Mean 0.007 0.003 0.002
IC Std. 0.247 0.240 0.228
Risk-Adjusted IC 0.028 0.012 0.010
t-stat(IC) 1.816 0.760 0.652
p-value(IC) 0.069 0.448 0.515
IC Skew 0.069 0.114 0.122
IC Kurtosis -0.393 -0.437 -0.471
/venvs/py35/lib/python3.5/site-packages/statsmodels/nonparametric/kdetools.py:20: VisibleDeprecationWarning: using a non-integer number instead of an integer will result in an error in the future
  y = X[:m/2+1] + np.r_[0,X[m/2+1:],0]*1j
/venvs/py35/lib/python3.5/site-packages/alphalens/utils.py:912: UserWarning: Skipping return periods that aren't exact multiples of days.
  + " of days."
Turnover Analysis
1D 5D 10D
Quantile 1 Mean Turnover 0.015 0.041 0.065
Quantile 2 Mean Turnover 0.032 0.085 0.131
Quantile 3 Mean Turnover 0.036 0.096 0.147
Quantile 4 Mean Turnover 0.031 0.084 0.129
Quantile 5 Mean Turnover 0.014 0.039 0.061
1D 5D 10D
Mean Factor Rank Autocorrelation 0.999 0.996 0.992
In [17]:
al.tears.create_full_tear_sheet(lows_adj, long_short=False)
Quantiles Statistics
min max mean std count count %
factor_quantile
1 -0.930107 -0.320518 -0.581397 0.112533 1254110 20.026268
2 -0.558316 -0.107564 -0.290832 0.092314 1251674 19.987369
3 -0.186534 0.352322 0.049356 0.144645 1251549 19.985373
4 0.333537 1.042778 0.690911 0.199859 1251674 19.987369
5 1.023004 1.730896 1.384061 0.200444 1253318 20.013621
Returns Analysis
1D 5D 10D
Ann. alpha 0.038 0.040 0.040
beta 0.018 0.018 0.033
Mean Period Wise Return Top Quantile (bps) 4.422 4.449 4.497
Mean Period Wise Return Bottom Quantile (bps) 5.971 5.810 5.488
Mean Period Wise Spread (bps) -1.549 -0.062 0.287
<matplotlib.figure.Figure at 0x7f1c087719b0>
Information Analysis
1D 5D 10D
IC Mean 0.007 0.003 0.002
IC Std. 0.247 0.240 0.228
Risk-Adjusted IC 0.028 0.012 0.010
t-stat(IC) 1.816 0.760 0.652
p-value(IC) 0.069 0.448 0.515
IC Skew 0.069 0.114 0.122
IC Kurtosis -0.393 -0.437 -0.471
Turnover Analysis
1D 5D 10D
Quantile 1 Mean Turnover 0.015 0.041 0.065
Quantile 2 Mean Turnover 0.032 0.085 0.131
Quantile 3 Mean Turnover 0.036 0.096 0.147
Quantile 4 Mean Turnover 0.031 0.084 0.129
Quantile 5 Mean Turnover 0.014 0.039 0.061
1D 5D 10D
Mean Factor Rank Autocorrelation 0.999 0.996 0.992
In [26]:
(1+al.performance.factor_returns(lows, demeaned=False)['1D']).cumprod().plot(label='cumulative L/S return').legend()
Out[26]:
<matplotlib.legend.Legend at 0x7f1b6c5bd9e8>
In [41]:
lows_adj_rets = al.performance.factor_returns(lows_adj, demeaned=False)['1D']
(1+lows_adj_rets).cumprod().plot(label='cumulative L/S return').legend()
Out[41]:
<matplotlib.legend.Legend at 0x7f1b6f43c2b0>
In [49]:
x = lows_adj_rets#[('2020-01-01' > lows_adj_rets.index) & (lows_adj_rets.index > '2010-01-01')]
vol = math.sqrt(252)*x.std()
ret = (1+x).prod()**(1/len(x))-1
In [50]:
(1+ret)**252-1
Out[50]:
0.039612015926870914
In [52]:
((1+ret)**252-1)/vol
Out[52]:
0.84720401557366831
In [38]:
2+5
Out[38]:
7
In [51]:
vol
Out[51]:
0.04675617112136606
In [ ]: