Pyfolio集成

Alphalens可以模拟一个投资组合的表现,其中因子值被用于股票权重分配。构建好投资组合后,可以通过Pyfolio进行分析。有关如何构建该投资组合的详细信息,请参阅:- alphalens.performance.factor_returns - alphalens.performance.cumulative_returns - alphalens.performance.create_pyfolio_input

导入与设置

[1]:
import warnings
warnings.filterwarnings('ignore')
[2]:
import alphalens
import pyfolio
import pandas as pd
[3]:
%matplotlib inline

加载数据

首先加载一些股票数据

[4]:
tickers = [ 'ACN', 'ATVI', 'ADBE', 'AMD', 'AKAM', 'ADS', 'GOOGL', 'GOOG', 'APH', 'ADI', 'ANSS', 'AAPL',
'AVGO', 'CA', 'CDNS', 'CSCO', 'CTXS', 'CTSH', 'GLW', 'CSRA', 'DXC', 'EBAY', 'EA', 'FFIV', 'FB',
'FLIR', 'IT', 'GPN', 'HRS', 'HPE', 'HPQ', 'INTC', 'IBM', 'INTU', 'JNPR', 'KLAC', 'LRCX', 'MA', 'MCHP',
'MSFT', 'MSI', 'NTAP', 'NFLX', 'NVDA', 'ORCL', 'PAYX', 'PYPL', 'QRVO', 'QCOM', 'RHT', 'CRM', 'STX',
'AMG', 'AFL', 'ALL', 'AXP', 'AIG', 'AMP', 'AON', 'AJG', 'AIZ', 'BAC', 'BK', 'BBT', 'BRK.B', 'BLK', 'HRB',
'BHF', 'COF', 'CBOE', 'SCHW', 'CB', 'CINF', 'C', 'CFG', 'CME', 'CMA', 'DFS', 'ETFC', 'RE', 'FITB', 'BEN',
'GS', 'HIG', 'HBAN', 'ICE', 'IVZ', 'JPM', 'KEY', 'LUK', 'LNC', 'L', 'MTB', 'MMC', 'MET', 'MCO', 'MS',
'NDAQ', 'NAVI', 'NTRS', 'PBCT', 'PNC', 'PFG', 'PGR', 'PRU', 'RJF', 'RF', 'SPGI', 'STT', 'STI', 'SYF', 'TROW',
'ABT', 'ABBV', 'AET', 'A', 'ALXN', 'ALGN', 'AGN', 'ABC', 'AMGN', 'ANTM', 'BCR', 'BAX', 'BDX', 'BIIB', 'BSX',
'BMY', 'CAH', 'CELG', 'CNC', 'CERN', 'CI', 'COO', 'DHR', 'DVA', 'XRAY', 'EW', 'EVHC', 'ESRX', 'GILD', 'HCA',
'HSIC', 'HOLX', 'HUM', 'IDXX', 'ILMN', 'INCY', 'ISRG', 'IQV', 'JNJ', 'LH', 'LLY', 'MCK', 'MDT', 'MRK', 'MTD',
'MYL', 'PDCO', 'PKI', 'PRGO', 'PFE', 'DGX', 'REGN', 'RMD', 'SYK', 'TMO', 'UNH', 'UHS', 'VAR', 'VRTX', 'WAT',
'MMM', 'AYI', 'ALK', 'ALLE', 'AAL', 'AME', 'AOS', 'ARNC', 'BA', 'CHRW', 'CAT', 'CTAS', 'CSX', 'CMI', 'DE',
'DAL', 'DOV', 'ETN', 'EMR', 'EFX', 'EXPD', 'FAST', 'FDX', 'FLS', 'FLR', 'FTV', 'FBHS', 'GD', 'GE', 'GWW',
'HON', 'INFO', 'ITW', 'IR', 'JEC', 'JBHT', 'JCI', 'KSU', 'LLL', 'LMT', 'MAS', 'NLSN', 'NSC', 'NOC', 'PCAR',
'PH', 'PNR', 'PWR', 'RTN', 'RSG', 'RHI', 'ROK', 'COL', 'ROP', 'LUV', 'SRCL', 'TXT', 'TDG', 'UNP', 'UAL',
'AES', 'LNT', 'AEE', 'AEP', 'AWK', 'CNP', 'CMS', 'ED', 'D', 'DTE', 'DUK', 'EIX', 'ETR', 'ES', 'EXC']

YFinance数据下载

[5]:
import yfinance as yf
import pandas_datareader.data as web
yf.pdr_override()

df = web.get_data_yahoo(tickers, start='2015-01-01',  end='2017-01-01')
df.index = pd.to_datetime(df.index, utc=True)
[*********************100%***********************]  247 of 247 completed

17 Failed downloads:
- RHT: No data found, symbol may be delisted
- JEC: No data found, symbol may be delisted
- RTN: No data found, symbol may be delisted
- BBT: No data found, symbol may be delisted
- BHF: Data doesn't exist for startDate = 1420092000, endDate = 1483250400
- AGN: No data found, symbol may be delisted
- BRK.B: No data found, symbol may be delisted
- ARNC: Data doesn't exist for startDate = 1420092000, endDate = 1483250400
- HRS: No data found, symbol may be delisted
- IR: Data doesn't exist for startDate = 1420092000, endDate = 1483250400
- CELG: No data found, symbol may be delisted
- BCR: No data found for this date range, symbol may be delisted
- STI: No data found, symbol may be delisted
- MYL: No data found, symbol may be delisted
- LUK: No data found for this date range, symbol may be delisted
- LLL: No data found, symbol may be delisted
- ETFC: No data found, symbol may be delisted

数据格式化

[6]:
df = df.stack()
df.index.names = ['date', 'asset']
df.info()
<class 'pandas.core.frame.DataFrame'>
MultiIndex: 114987 entries, (Timestamp('2015-01-02 00:00:00+0000', tz='UTC'), 'A') to (Timestamp('2016-12-30 00:00:00+0000', tz='UTC'), 'XRAY')
Data columns (total 6 columns):
 #   Column     Non-Null Count   Dtype
---  ------     --------------   -----
 0   Adj Close  114987 non-null  float64
 1   Close      114987 non-null  float64
 2   High       114987 non-null  float64
 3   Low        114987 non-null  float64
 4   Open       114987 non-null  float64
 5   Volume     114987 non-null  float64
dtypes: float64(6)
memory usage: 5.7+ MB

计算因子

我们将计算一个简单的均值回归因子,观察近期股票表现:过去5天表现良好的股票将获得较高排名,反之亦然。

[7]:
factor = df.loc[:,'Open'].unstack('asset')
factor = -factor.pct_change(5)
factor = factor.stack()

传递给alphalens的定价数据应包含资产的入场价格,因此必须反映在给定时间戳观察到因子值后的下一个可用价格。这些价格不得用于计算该时间点的因子值。务必反复检查,确保您的研究没有引入前瞻性偏差。

价格数据还必须包含资产的退出价格,对于周期1将使用下一个时间戳的价格,对于周期2将使用2个时间步长后的价格,以此类推。

对于计算因子时使用的时间频率没有限制/假设,对于交易因子的具体时间也没有限制(开盘交易、收盘交易或日内交易),唯一的要求是根据上述规则确保因子和价格数据框正确对齐。

在我们的示例中,每天交易开始前,我们会观察昨日的因子值。传递给alphalens的价格是该因子观测后的下一个可用价格:即作为资产入场价的每日开盘价。同时,由于我们没有添加额外价格数据,资产出场价将是后续交易日的开盘价(具体天数取决于'periods'参数)。因此Alphalens计算的收益将基于资产的开盘价。

[8]:
pricing = df.loc[:,'Open'].unstack('asset').iloc[1:]

运行Alphalens分析

获取输入数据

[9]:
factor_data = alphalens.utils.get_clean_factor_and_forward_returns(factor,
                                                                   pricing,
                                                                   periods=(1, 3, 5),
                                                                   quantiles=5,
                                                                   bins=None)
Dropped 1.0% entries from factor data: 1.0% 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!

汇总分析报告

[10]:
alphalens.tears.create_summary_tear_sheet(factor_data)
Quantiles Statistics
最小值 最大值 平均值 标准差 计数 计数百分比
因子分位数
1 -0.750000 0.074766 -0.041785 0.036192 22724 20.163981
2 -0.113307 0.094112 -0.013844 0.020647 22507 19.971428
3 -0.075532 0.109737 -0.001742 0.019542 22367 19.847200
4 -0.046988 0.127086 0.010283 0.020051 22500 19.965216
5 -0.029071 0.428571 0.037100 0.033545 22598 20.052176
Returns Analysis
1天 3天 5天
年化Alpha 0.279 0.122 0.090
beta 0.104 0.043 0.050
最高分位平均周期回报率 (基点) 4.890 2.209 1.824
底部十分位数平均周期回报率(bps) -2.953 -1.651 -1.705
周期平均价差(基点) 7.843 3.855 3.523
Information Analysis
1天 3天 5天
信息系数均值 0.016 0.012 0.016
IC标准差 0.173 0.169 0.169
风险调整后IC值 0.091 0.068 0.098
t统计量(IC) 2.012 1.517 2.171
p值(IC) 0.045 0.130 0.030
IC偏度 0.081 0.155 0.069
IC峰度 0.342 0.335 0.409
Turnover Analysis
1天 3天 5天
第一分位数平均换手率 0.347 0.601 0.788
第二分位数平均换手率 0.605 0.744 0.800
第三分位数平均换手率 0.652 0.763 0.786
四分位数4平均换手率 0.605 0.744 0.796
五分位平均换手率 0.350 0.596 0.781
1天 3天 5天
因子排名平均自相关性 0.749 0.359 -0.016
<Figure size 432x288 with 0 Axes>
../_images/notebooks_pyfolio_integration_22_10.png

运行Pyfolio分析

获取输入数据

我们可以在Alphalens分析中看到,分位数1和5最具预测性,因此我们将仅使用这些分位数构建投资组合数据。

[11]:
pf_returns, pf_positions, pf_benchmark = \
    alphalens.performance.create_pyfolio_input(factor_data,
                                               period='1D',
                                               capital=100000,
                                               long_short=True,
                                               group_neutral=False,
                                               equal_weight=True,
                                               quantiles=[1,5],
                                               groups=None,
                                               benchmark_period='1D')

Pyfolio业绩报告

现在我们已经准备好数据,可以运行Pyfolio函数了

[12]:
pyfolio.tears.create_full_tear_sheet(pf_returns,
                                     positions=pf_positions,
                                     benchmark_rets=pf_benchmark)
起始日期2015-01-09
结束日期2016-12-22
总月数34
回测
年化收益率 7.349%
累计收益率 22.253%
年化波动率 4.984%
夏普比率 1.45
卡尔玛比率 1.63
稳定性 0.85
最大回撤 -4.508%
欧米茄比率 1.37
索提诺比率 2.33
偏度 1.56
峰度 21.29
尾部比率 1.20
每日风险价值 -0.599%
总杠杆率 0.69
阿尔法值 0.07
贝塔值 0.11
最大回撤周期 净回撤百分比 峰值日期 谷值日期 恢复日期 持续时间
0 4.51 2016-03-30 2016-11-14 NaT NaN
1 2.29 2015-09-17 2015-09-28 2015-10-23 27
2 2.24 2016-01-04 2016-01-19 2016-02-11 29
3 1.97 2015-08-17 2015-08-21 2015-08-24 6
4 1.97 2015-02-04 2015-02-13 2015-04-01 41
压力事件 平均值 最小值 最大值
2015年秋季 0.03% -1.40% 3.45%
新常态 0.03% -1.40% 3.45%
历史持仓前十的多头头寸 最大值
资产
ABBV 1.11%
ABT 1.11%
ACN 1.11%
ADS 1.11%
平均超额收益 1.11%
年化超额收益 1.11%
AES 1.11%
全部 1.11%
AWK 1.11%
BSX 1.11%
历史上前十大空头持仓 最大值
资产
AAPL -1.11%
ADI -1.11%
AKAM -1.11%
ALLE -1.11%
AMD -1.11%
ANSS -1.11%
全有或全无 -1.11%
ATVI -1.11%
AVGO -1.11%
AYI -1.11%
历史持仓前十名 最大值
资产
AAPL 1.11%
ABBV 1.11%
ABT 1.11%
ACN 1.11%
ADI 1.11%
ADS 1.11%
平均超额收益 1.11%
年化超额收益 1.11%
AES 1.11%
AKAM 1.11%
../_images/notebooks_pyfolio_integration_29_6.png
../_images/notebooks_pyfolio_integration_29_7.png
../_images/notebooks_pyfolio_integration_29_8.png

子集表现

工作日分析

有时分析因子数据的子集会很有用,例如观察因子在一周中不同交易日的表现对比就很有意义。下面我们将展示如何筛选并分析仅针对周一的数据,这些持仓将保持5天

[13]:
monday_factor_data = factor_data[ factor_data.index.get_level_values('date').weekday == 0 ]
[14]:
pf_returns, pf_positions, pf_benchmark = \
    alphalens.performance.create_pyfolio_input(monday_factor_data,
                                               period='5D',
                                               capital=100000,
                                               long_short=True,
                                               group_neutral=False,
                                               equal_weight=True,
                                               quantiles=[1,5],
                                               groups=None,
                                               benchmark_period='1D')

Pyfolio业绩报告

[15]:
pyfolio.tears.create_full_tear_sheet(pf_returns,
                                     positions=pf_positions,
                                     benchmark_rets=pf_benchmark)
起始日期2015-01-12
结束日期2016-12-19
总月数33
回测
年化收益率 3.309%
累计收益率 9.578%
年化波动率 5.058%
夏普比率 0.67
卡尔玛比率 0.38
稳定性 0.37
最大回撤 -8.687%
欧米茄比率 1.40
索提诺比率 1.23
偏度 4.96
峰度 75.85
尾部比率 1.73
每日风险价值 -0.624%
总杠杆率 0.13
阿尔法值 0.03
贝塔值 0.17
最大回撤周期 净回撤百分比 峰值日期 谷值日期 恢复日期 持续时间
0 8.69 2015-12-20 2016-08-29 NaT NaN
1 2.22 2015-02-08 2015-03-23 2015-04-27 56
2 1.40 2015-06-28 2015-07-13 2015-08-24 41
3 0.61 2015-05-10 2015-05-18 2015-06-15 26
4 0.54 2015-10-04 2015-10-05 2015-10-12 6
压力事件 平均值 最小值 最大值
2015年秋季 0.10% -0.64% 4.61%
新常态 0.01% -1.99% 4.61%
历史持仓前十的多头头寸 最大值
资产
A 1.11%
AAL 1.11%
ADBE 1.11%
ADI 1.11%
平均超额收益 1.11%
年化超额收益 1.11%
AET 1.11%
AIG 1.11%
AIZ 1.11%
ALLE 1.11%
历史上前十大空头持仓 最大值
资产
A -1.11%
AAL -1.11%
AAPL -1.11%
ABBV -1.11%
ABT -1.11%
ADBE -1.11%
ADI -1.11%
ADS -1.11%
AEE -1.11%
AEP -1.11%
历史持仓前十名 最大值
资产
A 1.11%
AAL 1.11%
AAPL 1.11%
ABBV 1.11%
ABT 1.11%
ADBE 1.11%
ADI 1.11%
ADS 1.11%
平均超额收益 1.11%
年化超额收益 1.11%
../_images/notebooks_pyfolio_integration_36_6.png
../_images/notebooks_pyfolio_integration_36_7.png
../_images/notebooks_pyfolio_integration_36_8.png