performance

介绍

因子选股研究中常用的绩效计算方法

import warnings
warnings.filterwarnings('ignore')
from jaqs_fxdayu.data import DataView
from jaqs_fxdayu.research import SignalDigger

# 加载dataview数据集
dv = DataView()
dataview_folder = './data'
dv.load_dataview(dataview_folder)

# 计算signal_data
sd = SignalDigger()
sd.process_signal_before_analysis(signal=dv.get_ts("pe"),
                                   price=dv.get_ts("close_adj"),
                                   group=dv.get_ts("sw1"),
                                   n_quantiles=5,
                                   period=15,
                                   benchmark_price=dv.data_benchmark,
                                   )
signal_data = sd.signal_data
signal_data.head()
Dataview loaded successfully.
Nan Data Count (should be zero) : 0;  Percentage of effective data: 99%
signal return group quantile
trade_date symbol
20170503 000001.SZ 6.7925 -0.015258 480000 1
000002.SZ 10.0821 0.013463 430000 1
000008.SZ 42.9544 -0.122721 640000 4
000009.SZ 79.4778 -0.155903 510000 5
000027.SZ 20.4542 -0.041935 410000 2

calc_signal_ic

  • jaqs_fxdayu.research.signaldigger.performance.calc_signal_ic(signal_data, by_group=False)

简要描述:

  • 计算每日ic

参数:

字段 必选 类型 说明
signal_data pandas.DataFrame trade_date+symbol为MultiIndex,columns至少包含signal(因子)、return(持有期相对/绝对收益)、group(分组/行业分类)--仅在by_group=True时必须
by_group bool 是否分组进行计算,默认为False

返回:

每日ic

示例:

from jaqs_fxdayu.research.signaldigger.performance import calc_signal_ic

ic_data = calc_signal_ic(signal_data,by_group=False)
ic_data.head()
ic
trade_date
20170503 -0.288577
20170504 -0.341181
20170505 -0.350174
20170508 -0.380677
20170509 -0.427141
group_ic_data = calc_signal_ic(signal_data,by_group=True)
group_ic_data.head()
ic
trade_date group
20170503 110000 -0.142857
210000 -0.452381
220000 -0.285714
230000 0.100000
240000 0.013986

calc_ic_stats_table

  • jaqs_fxdayu.research.signaldigger.performance.calc_ic_stats_table(ic_data)

简要描述:

  • 根据每日ic计算总体ic统计结果

参数:

字段 必选 类型 说明
ic_data pandas.DataFrame trade_date为index,ic为columns。可通过calc_signal_ic计算得到

返回:

总体ic统计结果

示例:

from jaqs_fxdayu.research.signaldigger.performance import calc_ic_stats_table

calc_ic_stats_table(ic_data)
IC Mean IC Std. t-stat(IC) p-value(IC) IC Skew IC Kurtosis Ann. IR
ic -0.030303 0.207642 -1.392159 0.167305 0.189897 -0.601332 -0.145938

mean_information_coefficient

  • jaqs_fxdayu.research.signaldigger.performance.mean_information_coefficient(ic, by_time=None, by_group=False)

简要描述:

  • 输入ic,计算平均ic

参数:

字段 必选 类型 说明
ic pandas.DataFrame trade_date为index,ic为columns。可通过calc_signal_ic计算得到。注意:当by_group=True时,index需要为trade_date+group的MultiIndex(可以通过calc_signal_ic计算得到(设置by_group=True))
by_time str 支持pandas.TimeGrouper中的日期划分,如"M"(按月),"A"(全部时段),"Q"(按季度),"W"(按周)。默认求每日ic的所有样本的平均值
by_group bool 是否分组进行平均计算,默认为False

返回:

平均ic

示例:

示例一:按每3周求平均ic

from jaqs_fxdayu.research.signaldigger.performance import mean_information_coefficient

mean_information_coefficient(ic_data, by_time='3w')
ic
trade_date
2017-05-07 -0.326644
2017-05-28 -0.225651
2017-06-18 0.062981
2017-07-09 -0.193377
2017-07-30 0.217053
2017-08-20 0.034492
2017-09-10 -0.005609
2017-10-01 NaN

示例二:分组求每组的月平均ic

mean_information_coefficient(group_ic_data, by_group=True, by_time="M")
ic
trade_date group
2017-05-31 110000 -0.323308
210000 -0.464912
220000 -0.221515
230000 -0.142105
240000 -0.158263
270000 -0.236225
280000 -0.210836
330000 -0.253759
340000 0.245614
350000 -0.473684
360000 NaN
370000 -0.318267
410000 -0.339234
420000 -0.127752
430000 -0.269569
450000 -0.091479
460000 -0.589474
480000 -0.147984
490000 -0.337726
510000 0.684211
610000 -0.684211
620000 -0.454309
630000 -0.120301
640000 0.262448
650000 -0.197368
710000 -0.105139
720000 0.064058
730000 -0.492196
2017-06-30 110000 -0.179221
210000 0.496605
... ... ...
2017-08-31 720000 -0.215646
730000 -0.297784
2017-09-30 110000 0.172619
210000 -0.214286
220000 0.240909
230000 0.950000
240000 0.009324
270000 0.019069
280000 -0.104762
330000 -0.238095
340000 -0.333333
350000 -1.000000
360000 NaN
370000 0.231336
410000 -0.348485
420000 0.331269
430000 0.110680
450000 0.476190
460000 0.500000
480000 -0.642677
490000 -0.125032
510000 -0.233333
610000 NaN
620000 -0.076007
630000 0.013217
640000 -0.277610
650000 0.063889
710000 0.164695
720000 -0.143014
730000 -0.444444

140 rows × 1 columns

calc_period_wise_weighted_signal_return

  • jaqs_fxdayu.research.signaldigger.performance.calc_period_wise_weighted_signal_return(signal_data, weight_method)

简要描述:

  • 根据signal_data构建投资组合,计算投资组合的每日调仓收益

参数:

字段 必选 类型 说明
signal_data pandas.DataFrame trade_date+symbol为MultiIndex,columns至少包含signal(因子)、return(持有期相对/绝对收益)
weight_method str 支持四种投资组合构建方式:'equal_weight'(对signal_data中的每一只股票等资金买入), 'long_only'(只做多signal值为正的股票,并按signal的大小加权构建多头组合), 'short_only'(只做空signal值为负的股票,并按signal的大小加权构建空头组合),'long_short'(做多signal为正,做空signal为负的股票,按signal的大小加权)

返回:

投资组合的每日调仓收益

示例:

from jaqs_fxdayu.research.signaldigger.performance import calc_period_wise_weighted_signal_return

daily_return = calc_period_wise_weighted_signal_return(signal_data, weight_method="long_only")
daily_return.head()
return
trade_date
20170503 -0.066372
20170504 -0.070300
20170505 -0.065394
20170508 -0.064365
20170509 -0.078423

regress_period_wise_signal_return

  • jaqs_fxdayu.research.signaldigger.performance.regress_period_wise_signal_return(signal_data)

简要描述:

  • 对signal_data中的signal和return进行横截面回归(OLS),计算每期的因子收益(回归系数)

参数:

字段 必选 类型 说明
signal_data pandas.DataFrame trade_date+symbol为MultiIndex,columns至少包含signal(因子)、return(持有期相对/绝对收益)

返回:

每期的因子收益(回归系数)

示例:

from jaqs_fxdayu.research.signaldigger.performance import regress_period_wise_signal_return

regress_period_wise_signal_return(signal_data).head()
0
trade_date
20170503 -0.000093
20170504 -0.000091
20170505 -0.000090
20170508 -0.000095
20170509 -0.000104

calc_quantile_return_mean_std

  • jaqs_fxdayu.research.signaldigger.performance.calc_quantile_return_mean_std(signal_data, time_series=False)

简要描述:

  • 将股票按quantile分组分别等权买入持有,计算每组的平均持有收益(每日)和持有收益的标准差

参数:

字段 必选 类型 说明
signal_data pandas.DataFrame trade_date+symbol为MultiIndex,columns至少包含signal(因子)、return(持有期相对/绝对收益)、quantile(按因子值分组)
time_series bool 是否展示每组每天的收益,默认为False

返回:

每组(quantile)的平均持有收益(每日)和持有收益的标准差

示例:

示例一:展示每组的平均持有收益(每日)和持有收益的标准差(time_series=False)

返回pandas.DataFrame

from jaqs_fxdayu.research.signaldigger.performance import calc_quantile_return_mean_std

calc_quantile_return_mean_std(signal_data, time_series=False)
mean std count
quantile
1 -0.000813 0.051852 6996
2 -0.000514 0.051664 6996
3 -0.005477 0.057944 6996
4 -0.010762 0.063931 6996
5 -0.000114 0.079470 6996

示例二:展示每组每日的持有收益和持有收益的标准差(time_series=True)

返回dict

result = calc_quantile_return_mean_std(signal_data, time_series=True)
print(result.keys())
result[1].head()
dict_keys([1, 2, 3, 4, 5])
mean std count
trade_date
20170503 -0.005253 0.068051 66
20170504 -0.004897 0.076375 66
20170505 -0.003048 0.074683 66
20170508 -0.001248 0.063775 66
20170509 -0.002070 0.072706 66

price2ret

  • jaqs_fxdayu.research.signaldigger.performance.price2ret(prices, period=5, axis=None, compound=True)

简要描述:

  • 将价格序列转化为定期调仓收益序列

参数:

字段 必选 类型 说明
price pandas.DataFrame/pandas.Series 时间为索引的价格表
period int 调仓周期,默认为5
axis int {0, 1, None},将表格按某个维度进行收益计算(横向/纵向),默认纵向计算
compound bool 收益计算是否为复利。单利:(相对表格第一行的收益);复利(相对上一期的收益),默认为True 复利模式

返回:

收益序列

示例:

prices = dv.get_ts("close_adj")
prices.head()
symbol 000001.SZ 000002.SZ 000008.SZ 000009.SZ 000027.SZ 000039.SZ 000060.SZ 000061.SZ 000063.SZ 000069.SZ ... 601988.SH 601989.SH 601992.SH 601997.SH 601998.SH 603000.SH 603160.SH 603858.SH 603885.SH 603993.SH
trade_date
20170502 898.67562 2373.25440 210.898632 85.962653 94.89530 378.975476 241.71550 200.562672 299.850012 318.911580 ... 5.597708 11.717117 17.382915 15.67 7.856221 60.301733 97.88 80.49 45.397002 14.498578
20170503 895.65993 2331.22802 209.312928 85.265390 93.66644 378.030400 239.12148 198.410712 302.909706 314.186964 ... 5.550537 11.532463 16.034422 15.71 7.777265 60.998626 97.67 80.53 45.498789 14.450080
20170504 878.57102 2351.00514 208.255792 85.066171 93.80298 372.123675 234.64090 196.473948 303.079689 314.974400 ... 5.550537 11.364596 16.687598 15.61 7.724627 59.276890 96.99 79.62 45.295215 14.094485
20170505 867.51349 2334.93623 199.270136 82.277117 92.84720 359.128880 232.99016 195.613164 299.170080 310.249784 ... 5.566261 11.129582 16.371545 15.20 7.685148 57.842111 95.11 78.51 45.824507 13.803544
20170508 861.48211 2283.02129 193.191604 80.284935 90.93564 355.112307 233.93344 196.689144 289.481049 308.281194 ... 5.613432 10.777061 14.812351 14.83 7.724627 57.678136 97.00 76.60 45.030569 13.868197

5 rows × 330 columns

from jaqs_fxdayu.research.signaldigger.performance import price2ret

ret = price2ret(prices, period=5, compound=True)
ret.dropna().head()
symbol 000001.SZ 000002.SZ 000008.SZ 000009.SZ 000027.SZ 000039.SZ 000060.SZ 000061.SZ 000063.SZ 000069.SZ ... 601988.SH 601989.SH 601992.SH 601997.SH 601998.SH 603000.SH 603160.SH 603858.SH 603885.SH 603993.SH
trade_date
20170509 -0.033557 -0.030208 -0.081454 -0.063731 -0.035971 -0.053616 -0.015610 -0.020386 -0.027211 -0.032099 ... 0.002809 -0.070201 -0.134545 -0.019145 -0.013400 -0.037390 -0.007662 -0.040253 -0.033632 -0.043479
20170510 -0.026936 -0.010074 -0.070707 -0.091121 -0.040816 -0.078750 -0.038462 -0.034707 -0.056678 -0.016291 ... 0.014164 -0.082969 -0.137976 0.004456 -0.003384 -0.061828 -0.058360 -0.066559 -0.052349 -0.073826
20170511 -0.004577 0.011567 -0.058376 -0.093677 -0.061135 -0.060952 -0.026149 -0.059146 -0.029725 -0.012500 ... 0.025496 -0.063516 -0.140152 0.016015 0.017036 -0.063624 -0.044334 -0.075232 -0.069213 -0.043578
20170512 0.031286 0.026998 -0.025199 -0.069007 -0.051471 -0.002632 -0.026356 -0.051705 -0.020455 0.019036 ... 0.036723 -0.051282 -0.120978 0.063816 0.051370 -0.046775 -0.016823 -0.068654 -0.084851 -0.035129
20170515 0.033839 0.047103 0.006840 -0.042184 -0.027027 0.005323 -0.026237 -0.054705 0.024075 0.040868 ... 0.025210 -0.031153 -0.036984 0.078220 0.034072 -0.039090 -0.035258 -0.041775 -0.064647 -0.025641

5 rows × 330 columns

ret2cum

  • jaqs_fxdayu.research.signaldigger.performance.ret2cum(ret, compound=True, axis=None)

简要描述:

  • 将收益序列转化为累积收益序列

参数:

字段 必选 类型 说明
ret pandas.DataFrame/pandas.Series 时间为索引的收益表
compound bool 收益计算是否为复利。单利:(每期累加的收益);复利(每期累乘的收益),默认为True 复利模式
axis int {0, 1, None},将表格按某个维度进行收益计算(横向/纵向),默认纵向计算

返回:

累积收益序列

示例:

from jaqs_fxdayu.research.signaldigger.performance import ret2cum

cum = ret2cum(ret, compound=True)
cum.dropna().head()
symbol 000001.SZ 000002.SZ 000008.SZ 000009.SZ 000027.SZ 000039.SZ 000060.SZ 000061.SZ 000063.SZ 000069.SZ ... 601988.SH 601989.SH 601992.SH 601997.SH 601998.SH 603000.SH 603160.SH 603858.SH 603885.SH 603993.SH
trade_date
20170509 -0.033557 -0.030208 -0.081454 -0.063731 -0.035971 -0.053616 -0.015610 -0.020386 -0.027211 -0.032099 ... 0.002809 -0.070201 -0.134545 -0.019145 -0.013400 -0.037390 -0.007662 -0.040253 -0.033632 -0.043479
20170510 -0.059589 -0.039978 -0.146401 -0.149045 -0.075319 -0.128144 -0.053471 -0.054386 -0.082347 -0.047867 ... 0.017013 -0.147346 -0.253958 -0.014774 -0.016739 -0.096906 -0.065575 -0.104133 -0.084221 -0.114094
20170511 -0.063893 -0.028874 -0.196231 -0.228760 -0.131850 -0.181285 -0.078221 -0.110315 -0.109624 -0.059768 ... 0.042943 -0.201502 -0.358517 0.001004 0.000012 -0.154364 -0.107002 -0.171531 -0.147605 -0.152700
20170512 -0.034606 -0.002655 -0.216485 -0.281981 -0.176534 -0.183440 -0.102515 -0.156316 -0.127836 -0.041870 ... 0.081243 -0.242451 -0.436122 0.064884 0.051382 -0.193919 -0.122025 -0.228409 -0.219932 -0.182465
20170515 -0.001938 0.044323 -0.211126 -0.312270 -0.198790 -0.179094 -0.126063 -0.202470 -0.106839 -0.002713 ... 0.108501 -0.266051 -0.456977 0.148179 0.087204 -0.225429 -0.152980 -0.260642 -0.270361 -0.203427

5 rows × 330 columns

cum2ret

  • jaqs_fxdayu.research.signaldigger.performance.cum2ret(cum, period=1, axis=None, compound=True)

简要描述:

  • 将累积收益序列转化为收益序列

参数:

字段 必选 类型 说明
cum pandas.DataFrame/pandas.Series 时间为索引的累积收益表
period int 通常为1。累积收益的累积间隔周期。默认为1
compound bool 收益计算是否为复利。单利:(每期累加的收益);复利(每期累乘的收益),默认为True 复利模式
axis int {0, 1, None},将表格按某个维度进行收益计算(横向/纵向),默认纵向计算

返回:

收益序列

示例:

from jaqs_fxdayu.research.signaldigger.performance import cum2ret

cum2ret(cum, period=1,compound=True).dropna().head()
symbol 000001.SZ 000002.SZ 000008.SZ 000009.SZ 000027.SZ 000039.SZ 000060.SZ 000061.SZ 000063.SZ 000069.SZ ... 601988.SH 601989.SH 601992.SH 601997.SH 601998.SH 603000.SH 603160.SH 603858.SH 603885.SH 603993.SH
trade_date
20170510 -0.026936 -0.010074 -0.070707 -0.091121 -0.040816 -0.078750 -0.038462 -0.034707 -0.056678 -0.016291 ... 0.014164 -0.082969 -0.137976 0.004456 -0.003384 -0.061828 -0.058360 -0.066559 -0.052349 -0.073826
20170511 -0.004577 0.011567 -0.058376 -0.093677 -0.061135 -0.060952 -0.026149 -0.059146 -0.029725 -0.012500 ... 0.025496 -0.063516 -0.140152 0.016015 0.017036 -0.063624 -0.044334 -0.075232 -0.069213 -0.043578
20170512 0.031286 0.026998 -0.025199 -0.069007 -0.051471 -0.002632 -0.026356 -0.051705 -0.020455 0.019036 ... 0.036723 -0.051282 -0.120978 0.063816 0.051370 -0.046775 -0.016823 -0.068654 -0.084851 -0.035129
20170515 0.033839 0.047103 0.006840 -0.042184 -0.027027 0.005323 -0.026237 -0.054705 0.024075 0.040868 ... 0.025210 -0.031153 -0.036984 0.078220 0.034072 -0.039090 -0.035258 -0.041775 -0.064647 -0.025641
20170516 0.023148 0.032760 0.006821 -0.024752 -0.008955 0.012516 -0.022761 -0.037240 0.103730 0.040816 ... 0.016807 -0.030817 0.029412 0.036435 0.028862 -0.027542 0.018429 -0.035728 -0.028770 0.020979

5 rows × 330 columns

calc_performance_metrics

  • jaqs_fxdayu.research.signaldigger.performance.calc_performance_metrics(ser, cum_return=False, compound=True)

简要描述:

  • 根据收益计算常见绩效——annualized return, volatility and sharpe

参数:

字段 必选 类型 说明
ser pandas.DataFrame/pandas.Series 时间为索引的收益/累积收益表。注意:只能有一列值,不支持多列收益的计算
cum_return bool 收益是否为累积收益,默认为否(False)
compound bool 收益计算是否为复利。单利:(每期累加的收益);复利(每期累乘的收益),默认为True 复利模式

返回:

绩效表

示例:

from jaqs_fxdayu.research.signaldigger.performance import calc_performance_metrics

# 多头组合的每日收益
daily_return = calc_period_wise_weighted_signal_return(signal_data, weight_method="long_only")
# 该收益的绩效表现
calc_performance_metrics(daily_return, cum_return=False, compound=True)
{'ann_ret': 0.055395156268065238,
 'ann_vol': 0.4356857810045196,
 'sharpe': 0.12714474211287285}

period_wise_ret_to_cum

  • jaqs_fxdayu.research.signaldigger.performance.period_wise_ret_to_cum(ret, period, compound=True)

简要描述:

  • 从按period周期调仓的选股方案的每日收益中计算累积收益。计算方式如下:
  • 以某个调仓周期为n天的选股方案为例:将资金等分为n分,每天取其中一份买入当天的选股并持有到5天后卖出,最后的组合累积收益。

参数:

字段 必选 类型 说明
ret pandas.DataFrame/pandas.Series 时间为索引的收益表。
period int 调仓周期
compound bool 收益计算是否为复利。单利:(每期累加的收益);复利(每期累乘的收益),默认为True 复利模式

返回:

累积收益

示例:

daily_return.head() # 每一天对应的收益代表买入股票15天后卖出的收益。如20170503的return表示20170503买入股票并在20170518卖出的收益
return
trade_date
20170503 -0.066372
20170504 -0.070300
20170505 -0.065394
20170508 -0.064365
20170509 -0.078423
from jaqs_fxdayu.research.signaldigger.performance import period_wise_ret_to_cum

period_wise_ret_to_cum(daily_return, period=15, compound=True).head()
return
trade_date
20170503 -0.004425
20170504 -0.009111
20170505 -0.013471
20170508 -0.017762
20170509 -0.022990