@Channelchan
2018-10-17T21:02:11.000000Z
字数 7174
阅读 75841
Alphalens是一个Python第三方库,专门用于选股因子alpha(α)的绩效分析。
下载方式: pip install alphalens==0.2.1
官方网站: http://quantopian.github.io/alphalens/index.html
factor: MultiIndex(用stack()方法来转换)
prices: DataFrame
索引要求均为日期-datetime日期格式
将以上数据通过alphalens处理成标准格式-factor_data 用于进一步分析
下面以沪深300成分股为例,构造选股因子(factor)并
from jaqs_fxdayu.data import DataView # 可以视为一个轻量级的数据库,数据格式基于pandas,方便数据的调用和处理
from jaqs_fxdayu.data import RemoteDataService # 数据服务,用于下载数据
import os
import warnings
warnings.filterwarnings("ignore")
dataview_folder = '../Factor'
if not (os.path.isdir(dataview_folder)):
os.makedirs(dataview_folder)
# 数据下载
def save_dataview():
data_config = {
"remote.data.address": "tcp://data.quantOS.org:8910",
"remote.data.username": "18566262672",
"remote.data.password": "eyJhbGciOiJIUzI1NiJ9.eyJjcmVhdGVfdGltZSI6IjE1MTI3MDI3NTAyMTIiLCJpc3MiOiJhdXRoMCIsImlkIjoiMTg1NjYyNjI2NzIifQ.O_-yR0zYagrLRvPbggnru1Rapk4kiyAzcwYt2a3vlpM"
}
ds = RemoteDataService()
ds.init_from_config(data_config)
dv = DataView()
props = {'start_date': 20140101, 'end_date': 20140201, 'universe': '000300.SH',
'fields': "pb,pe,ps,float_mv,sw1",
'freq': 1}
dv.init_from_config(props, ds)
dv.prepare_data()
dv.save_dataview(dataview_folder) # 保存数据文件到指定路径,方便下次直接加载
# save_dataview()
# 加载数据
dv = DataView()
dv.load_dataview(dataview_folder)
Dataview loaded successfully.
dv.fields
['low_adj',
'index_weight',
'ps',
'index_member',
'close_adj',
'high_adj',
'sw1',
'float_mv',
'high',
'open_adj',
'vwap_adj',
'pb',
'open',
'pe',
'vwap',
'close',
'adjust_factor',
'low',
'trade_status']
import pandas as pd
from datetime import datetime
factor = dv.get_ts("pb")
factor.index = pd.Index(map(lambda x: datetime.strptime(str(x),"%Y%m%d") , factor.index)) #索引调整为datetime日期格式
factor = factor.stack()#处理成MultiIndex格式(alphalens分析因子必须的格式)
factor.head()
symbol
2014-01-02 000001.SZ 1.0563
000002.SZ 1.2891
000008.SZ 4.8981
000009.SZ 3.5794
000012.SZ 2.3725
dtype: float64
def change_index(df):
df.index = pd.Index(map(lambda x: datetime.strptime(str(x),"%Y%m%d") , df.index)) #索引调整为datetime日期格式
return df
prices = dv.get_ts("close_adj") #获取价格
prices = change_index(prices)
prices.head()
symbol | 000001.SZ | 000002.SZ | 000008.SZ | 000009.SZ | 000012.SZ | 000024.SZ | 000027.SZ | 000039.SZ | 000046.SZ | 000059.SZ | ... | 601998.SH | 603000.SH | 603160.SH | 603288.SH | 603699.SH | 603799.SH | 603833.SH | 603858.SH | 603885.SH | 603993.SH |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2014-01-02 | 685.432796 | 869.28004 | 54.679500 | 57.244120 | 155.894015 | 97.545898 | 45.840241 | 348.968736 | 130.848969 | 7.635187 | ... | 4.617178 | 79.318951 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 6.541196 |
2014-01-03 | 668.619236 | 852.96064 | 54.375725 | 55.721670 | 153.407362 | 95.883723 | 44.750802 | 354.379104 | 128.507153 | 7.359216 | ... | 4.545408 | 78.055589 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 6.438347 |
2014-01-06 | 654.047484 | 813.79408 | 51.702505 | 55.234486 | 144.799717 | 90.754728 | 43.745166 | 342.656640 | 126.458064 | 7.006587 | ... | 4.473638 | 77.762489 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 6.191510 |
2014-01-07 | 651.805676 | 808.35428 | 50.973445 | 55.112690 | 144.034593 | 88.760118 | 43.577560 | 353.026512 | 124.408975 | 6.883933 | ... | 4.461677 | 79.743441 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 6.191510 |
2014-01-08 | 659.091552 | 807.26632 | 50.001365 | 54.138322 | 143.652031 | 86.338093 | 44.080378 | 351.448488 | 126.165337 | 6.853270 | ... | 4.473638 | 81.865890 | NaN | NaN | NaN | NaN | NaN | NaN | NaN | 6.098946 |
5 rows × 472 columns
import alphalens
#计算目标股票池每只股票的持有期收益,和对应因子值的quantile分类
factor_data = alphalens.utils.get_clean_factor_and_forward_returns(factor, prices, quantiles=5, periods=(1,5,10))
factor_data.head()
1 | 5 | 10 | factor | factor_quantile | ||
---|---|---|---|---|---|---|
date | asset | |||||
2014-01-02 | 000001.SZ | -0.024530 | -0.033524 | -0.044154 | 1.0563 | 1 |
000002.SZ | -0.018773 | -0.066333 | -0.100125 | 1.2891 | 2 | |
000008.SZ | -0.005556 | -0.102222 | -0.054444 | 4.8981 | 4 | |
000009.SZ | -0.026596 | -0.075532 | -0.057447 | 3.5794 | 4 | |
000012.SZ | -0.015951 | -0.093252 | -0.039264 | 2.3725 | 3 |
import matplotlib.pyplot as plt
mean_return_by_q, std_err_by_q = alphalens.performance.mean_return_by_quantile(factor_data, by_date=True, demeaned=True)
alphalens.plotting.plot_cumulative_returns_by_quantile(mean_return_by_q, 1)
alphalens.plotting.plot_cumulative_returns_by_quantile(mean_return_by_q, 5)
alphalens.plotting.plot_cumulative_returns_by_quantile(mean_return_by_q, 10)
plt.show()
度量变量的预测值与实际值之间的相关关系。信息系数是用来评估金融分析师预测技能的一种表现方法。
系数在-1到1之间,越大表示正相关程度强。
这里,我们可以用信息系数来评价一个选股因子效力的好坏。也即,用因子值大小与下一期股票收益大小的相关程度来评估因子。
经验来看,通常|mean(IC)|>0.02可以作为判定一个选股因子有收益预测效力的标准
其中d为秩次差。
A = [1,3,5,7,9]
B = [3,2,4,5,1]
A的排序是1,2,3,4,5
B的排序是3,2,4,5,1
d为排序相减
接下来我们要计算的因子IC值,即为当期因子值与下期股票收益值的spearman相关系数。
ic = alphalens.performance.factor_information_coefficient(factor_data)
ic.head()
1 | 5 | 10 | |
---|---|---|---|
date | |||
2014-01-02 | 0.325364 | 0.372408 | 0.346461 |
2014-01-03 | 0.094661 | 0.233455 | 0.287933 |
2014-01-06 | 0.211379 | 0.156397 | 0.210309 |
2014-01-07 | 0.375963 | 0.150975 | 0.144572 |
2014-01-08 | -0.029050 | 0.167510 | 0.014627 |
alphalens.plotting.plot_ic_hist(ic) #因子IC分布
alphalens.plotting.plot_ic_ts(ic) #因子IC时间序列曲线
plt.show()
# 月均IC热度图
mean_monthly_ic = alphalens.performance.mean_information_coefficient(factor_data, by_time='M')
alphalens.plotting.plot_monthly_ic_heatmap(mean_monthly_ic)#因子月均IC表现
plt.show()
import numpy as np
excel_data = factor_data[factor_data['factor_quantile']==1]["factor_quantile"].unstack().replace(np.nan, 0)
excel_data.to_excel('./pb_quantile_1_by_alphalens.xlsx')
excel_data.head()
asset | 000001.SZ | 000002.SZ | 000024.SZ | 000027.SZ | 000039.SZ | 000059.SZ | 000063.SZ | 000069.SZ | 000157.SZ | 000338.SZ | ... | 601898.SH | 601901.SH | 601918.SH | 601939.SH | 601985.SH | 601988.SH | 601991.SH | 601992.SH | 601997.SH | 601998.SH |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
date | |||||||||||||||||||||
2014-01-02 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | ... | 1.0 | 0.0 | 1.0 | 1.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 1.0 |
2014-01-03 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | ... | 1.0 | 0.0 | 1.0 | 1.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 1.0 |
2014-01-06 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | ... | 1.0 | 0.0 | 1.0 | 1.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 1.0 |
2014-01-07 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | ... | 1.0 | 0.0 | 1.0 | 1.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 1.0 |
2014-01-08 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 0.0 | 1.0 | 0.0 | ... | 1.0 | 0.0 | 1.0 | 1.0 | 0.0 | 1.0 | 0.0 | 1.0 | 0.0 | 1.0 |
5 rows × 192 columns
sectors = dv.get_ts("sw1")
sectors = change_index(sectors)
sectors.head()
symbol | 000001.SZ | 000002.SZ | 000008.SZ | 000009.SZ | 000012.SZ | 000024.SZ | 000027.SZ | 000039.SZ | 000046.SZ | 000059.SZ | ... | 601998.SH | 603000.SH | 603160.SH | 603288.SH | 603699.SH | 603799.SH | 603833.SH | 603858.SH | 603885.SH | 603993.SH |
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
2014-01-02 | 银行 | 房地产 | 休闲服务 | 综合 | 建筑材料 | 房地产 | 公用事业 | 机械设备 | 房地产 | 化工 | ... | 银行 | 传媒 | 电子 | 食品饮料 | 机械设备 | 有色金属 | 轻工制造 | 医药生物 | 交通运输 | 有色金属 |
2014-01-03 | 银行 | 房地产 | 休闲服务 | 综合 | 建筑材料 | 房地产 | 公用事业 | 机械设备 | 房地产 | 化工 | ... | 银行 | 传媒 | 电子 | 食品饮料 | 机械设备 | 有色金属 | 轻工制造 | 医药生物 | 交通运输 | 有色金属 |
2014-01-06 | 银行 | 房地产 | 休闲服务 | 综合 | 建筑材料 | 房地产 | 公用事业 | 机械设备 | 房地产 | 化工 | ... | 银行 | 传媒 | 电子 | 食品饮料 | 机械设备 | 有色金属 | 轻工制造 | 医药生物 | 交通运输 | 有色金属 |
2014-01-07 | 银行 | 房地产 | 休闲服务 | 综合 | 建筑材料 | 房地产 | 公用事业 | 机械设备 | 房地产 | 化工 | ... | 银行 | 传媒 | 电子 | 食品饮料 | 机械设备 | 有色金属 | 轻工制造 | 医药生物 | 交通运输 | 有色金属 |
2014-01-08 | 银行 | 房地产 | 休闲服务 | 综合 | 建筑材料 | 房地产 | 公用事业 | 机械设备 | 房地产 | 化工 | ... | 银行 | 传媒 | 电子 | 食品饮料 | 机械设备 | 有色金属 | 轻工制造 | 医药生物 | 交通运输 | 有色金属 |
5 rows × 472 columns
factor_data = alphalens.utils.get_clean_factor_and_forward_returns(factor,
prices,
groupby=sectors.stack(),
quantiles=5,
periods=(1, 5, 10))
factor_data.head()
1 | 5 | 10 | factor | group | factor_quantile | ||
---|---|---|---|---|---|---|---|
date | asset | ||||||
2014-01-02 | 000001.SZ | -0.024530 | -0.033524 | -0.044154 | 1.0563 | 银行 | 1 |
000002.SZ | -0.018773 | -0.066333 | -0.100125 | 1.2891 | 房地产 | 2 | |
000008.SZ | -0.005556 | -0.102222 | -0.054444 | 4.8981 | 休闲服务 | 4 | |
000009.SZ | -0.026596 | -0.075532 | -0.057447 | 3.5794 | 综合 | 4 | |
000012.SZ | -0.015951 | -0.093252 | -0.039264 | 2.3725 | 建筑材料 | 3 |
ic_by_sector = alphalens.performance.mean_information_coefficient(factor_data, by_group=True)
ic_by_sector.head()
1 | 5 | 10 | |
---|---|---|---|
group | |||
交通运输 | -0.054600 | -0.076287 | -0.101861 |
休闲服务 | -0.008219 | -0.047374 | -0.066913 |
传媒 | -0.034612 | -0.043479 | -0.047153 |
公用事业 | -0.029263 | -0.038912 | -0.046744 |
农林牧渔 | -0.023074 | -0.033296 | -0.043930 |
from matplotlib import pyplot as plt
alphalens.plotting.plot_ic_by_group(ic_by_sector)
plt.show()