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>
运行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% |
子集表现¶
工作日分析¶
有时分析因子数据的子集会很有用,例如观察因子在一周中不同交易日的表现对比就很有意义。下面我们将展示如何筛选并分析仅针对周一的数据,这些持仓将保持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% |