Skip to content

Repository files navigation

jqfactor_analyzer

jqfactor_analyzer 是提供给用户配合 jqdatasdk 进行归因分析,因子数据缓存及单因子分析的开源工具。

安装

pip install jqfactor_analyzer

升级

pip install -U jqfactor_analyzer

具体使用方法

详细用法请查看API文档

归因分析使用示例

风格模型的基本概念

归因分析旨在通过对历史投资组合的收益进行分解,明确指出各个收益来源对组合的业绩贡献,能够更好地理解组合的表现是否符合预期,以及是否存在某一风格/行业暴露过高的风险。

多因子风险模型的基础理论认为,股票的收益是由一些共同的因子 (风格,行业和国家因子) 来驱动的,不能被这些因子解释的部分被称为股票的 “特异收益”, 而每只股票的特异收益之间是互不相关的。

(1) 风格因子,即影响股票收益的风格因素,如市值、成长、杠杆等。

(2) 行业因子,不同行业在不同时期可能优于或者差于其他行业,同一行业内的股票往往涨跌具有较强的关联性。

(3) 国家因子,表示股票市场整体涨落对投资组合的收益影响,对于任意投资组合,若他们投资的都是同一市场则其承担的国家因子和收益是相同的。

(4) 特异收益,即无法被多因子风险模型解释的部分,也就是影响个股收益的特殊因素,如公司经营能力、决策等。

根据上述多因子风险模型,股票的收益可以表达为 :

$$ R_i = \underbrace{1 \cdot f_c} _{\text{国家因子收益}} + \underbrace{\sum _{j=1}^{S} f _j^{style} \cdot X _{ij}^{style}} _{\text{风格因子收益}} + \underbrace{\sum _{j=1}^{I} f _j^{industry} \cdot X _{ij}^{industry}} _{\text{行业因子收益}} + \underbrace{u _i} _{\text{个股特异收益}} $$

此公式可简化为:

$$ R_i = \underbrace{\sum_{j=1}^{K} f_j \cdot X_{ij}}_{\text{第 j 个因子 (含国家,风格和行业,总数为 K) 获得的收益}} + \underbrace{u_i} _{\text{个股特异收益}} $$

其中:

  • $R_i$ 是第 $i$ 只股票的收益
  • $f_c$ 是国家因子的回报率
  • $S$$I$ 分别是风格和行业因子的数量
  • $f_j^{style}$ 是第 $j$ 个风格因子的回报率, $f_j^{industry}$ 是第 $j$ 个行业因子的回报率
  • $X_{ij}^{style}$ 是第 $i$ 只股票在第 $j$ 个风格因子上的暴露, $X_{ij}^{industry}$ 是第 $i$ 只股票在第 $j$ 个行业因子上的暴露,因子暴露又称因子载荷/因子值 (通过jqdatasdk.get_factor_values可获取风格因子暴露及行业暴露哑变量)
  • $u_i$ 是残差项,表示无法通过模型解释的部分 (即特异收益率)

根据上述公式,对市场上的股票 (一般采用中证全指作为股票池) 使用对数市值加权在横截面上进行加权最小二乘回归,可得到 :

  • $f_j$ : 风格/行业因子和国家因子的回报率 , 通过 jqdatasdk.get_factor_style_returns 获取
  • $u_i$ : 回归残差 (无法被模型解释的部分,即特异收益率), 通过jqdatasdk.get_factor_specific_returns获取

使用上述已提供的数据进行归因分析 :

现已知你的投资组合 P 由权重 $w_n$ 构成,则投资组合第 j 个因子的暴露可表示为 :

$$ X^P_j = \sum_{i=1}^{n} w_i X_{ij} $$

  • $X^P_j$ 可通过 jqfactor_analyzer.AttributionAnalysis().exposure_portfolio获取

投资组合在第 j 个因子上获取到的收益率可以表示为 :

$$ R^P_j = X^P_j \cdot f_j $$

  • $R^P_j$ 可通过 jqfactor_analyzer.AttributionAnalysis().attr_daily_return获取

所以投资组合的收益率也可以被表示为 :

$$ R_P = \sum_{j=1}^{k} R^p_j \cdot f_j + \sum_{i-1}^{n} w_i u_i $$

即理论上 $\sum_n w_n u_n$ 就是投资组合的特异收益 (alpha) $R_s$ (您也可以直接获取个股特异收益率与权重相乘直接进行计算),但现实中受到仓位,调仓时间,费用等其他因素的影响,此公式并非完全成立的,AttributionAnalysis 中是使用做差的方式来计算特异收益率,即:

$$ R_s = R_P - \sum_{j=1}^{k} R^p_j \cdot f_j $$

以指数作为基准的归因分析

  • jqdatasdk 已经根据指数权重计算好了指数的风格暴露 $X^B$,可通过jqdatasdk.get_index_style_exposure 获取

投资组合 P 相对于指数的第 j 个因子的暴露可表示为 :

$$ X^{P2B}_j = X^P_j - X^B_j $$

  • $X^{P2B}_j$ 可通过jqfactor_analyzer.AttributionAnalysis().get_exposure2bench(index_symbol)获取

投资组合在第 j 个因子上相对于指数获取到的收益率可以表示为 :

$$ R^{P2B}_j = R^P_j - R^B_j = X^P_j \cdot f_j - X^B_j \cdot f_j = f_j \cdot X^{P2B}_j $$

在 AttributionAnalysis 中,风格及行业因子部分,将指数的仓位和持仓的仓位进行了对齐;同时考虑了现金产生的收益 (国家因子在仓位对齐后不会产生暴露收益,现金收益为 0,现金相对于指数的收益即为:(-1) × 剩余仓位 × 指数收益)

所以投资组合相对于指数的收益可以被表示为:

$$ R_{P2B} = \sum_{j=1}^{k} R^{P2B}_j + R^{P2B}_s + 现金相对于指数的收益 $$

  • $R_{P2B}$ 等可通过 jqfactor_analyzer.AttributionAnalysis().get_attr_daily_returns2bench(index_symbol)获取

累积收益的处理

上述 attr_daily_returnget_attr_daily_returns2bench(index_symbol) 获取到的均为单日收益率,在计算累积收益时需要考虑复利影响。

$$ N_t = \prod_{t=1}^{n} (R^p_t+1) $$$$ Rcum^p_{jt} = N_{t-1} \cdot R^P_{jt} $$

其中 :

  • $N_t$ 为投资组合在第 t 天盘后的净值
  • $R^p_t$ 为投资组合在第 t 天的日度收益率
  • $Rcum^p_{jt}$ 为投资组合 p 的第 j 个因子在 t 日的累积收益
  • $R^P_{jt}$ 为投资组合 p 的第 j 个因子在 t 日的日收益率
  • $N_t, Rcum^p_{jt}$ 均可通过jqfactor_analyzer.AttributionAnalysis().attr_returns 获取
  • 相对于基准的累积收益算法类似, 可通过 jqfactor_analyzer.AttributionAnalysis().get_attr_returns2bench获取

导入模块并登陆 jqdatasdk

importjqdatasdkimportjqfactor_analyzerasja# 获取 jqdatasdk 授权,输入用户名、密码,申请地址:https://www.joinquant.com/default/index/sdk# 聚宽官网,使用方法参见:https://www.joinquant.com/help/api/doc?name=JQDatadocjqdatasdk.auth("账号", "密码")

处理权重信息

此处使用的是 jqfactor_analyzer 提供的示例文件 数据格式要求 :

  • 权重数据, 一个 dataframe, index 为日期, columns 为标的代码 (可使用 jqdatasdk.normalize_code 转为支持的格式), values 为权重, 每日的权重和应该小于 1
  • 组合的日度收益数据, 一个 series, index 为日期, values 为日收益率
importosimportpandasaspdweight_path=os.path.join(os.path.dirname(ja.__file__), 'sample_data', 'weight_info.csv')
weight_infos=pd.read_csv(weight_path, index_col=0)
daily_return=weight_infos.pop("return")
weight_infos.head(5)
<style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }
dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
000006.XSHE000008.XSHE000009.XSHE000012.XSHE000021.XSHE000025.XSHE000027.XSHE000028.XSHE000031.XSHE000032.XSHE...603883.XSHG603885.XSHG603888.XSHG603893.XSHG603927.XSHG603939.XSHG603979.XSHG603983.XSHG605117.XSHG605358.XSHG
2020-01-020.0008730.0012440.0029340.0012190.0016140.0004330.0012740.0011810.001471NaN...0.0012940.0015360.000781NaNNaN0.001896NaN0.000482NaNNaN
2020-01-030.0008970.0012470.0026790.0012030.0017080.0004320.0012930.0011950.001463NaN...0.0012980.0015050.000824NaNNaN0.001912NaN0.000466NaNNaN
2020-01-060.0008790.0012160.0029260.0012250.0016130.0004340.0012780.0012280.001429NaN...0.0012380.0015340.000767NaNNaN0.001962NaN0.000488NaNNaN
2020-01-070.0008830.0012410.0025910.0012200.0015360.0004390.0012940.0011950.001488NaN...0.0012670.0015750.000764NaNNaN0.001959NaN0.000468NaNNaN
2020-01-080.0008770.0012310.0027580.0012050.0015280.0004290.0012700.0012080.001448NaN...0.0012770.0015540.000749NaNNaN0.001987NaN0.000474NaNNaN

5 rows × 818 columns

weight_infos.sum(axis=1).head(5)
2020-01-02 0.752196
2020-01-03 0.750206
2020-01-06 0.752375
2020-01-07 0.752054
2020-01-08 0.748039
dtype: float64

进行归因分析

具体用法请查看API文档, 此处仅作示例

An=ja.AttributionAnalysis(weight_infos, daily_return, style_type='style', industry='sw_l1', use_cn=True, show_data_progress=True)
check/save factor cache : 100%|██████████| 54/54 [00:02<00:00, 25.75it/s]
calc_style_exposure : 100%|██████████| 1087/1087 [00:27<00:00, 39.52it/s]
calc_industry_exposure : 100%|██████████| 1087/1087 [00:19<00:00, 56.53it/s]
An.exposure_portfolio.head(5) #查看暴露
<style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
sizebetamomentumresidual_volatilitynon_linear_sizebook_to_price_ratioliquidityearnings_yieldgrowthleverage...801050801040801780801970801120801790801760801890801960country
2020-01-02-0.4878160.468947-0.0482620.1045970.976877-0.1120420.278131-0.311944-0.000541-0.356787...0.0302340.0237280.010499NaN0.0170490.0322920.0424050.027871NaN0.752196
2020-01-03-0.4851280.461138-0.0444220.1042700.970710-0.1101960.271739-0.314469-0.002360-0.354623...0.0305740.0237120.010610NaN0.0170710.0332610.0414910.027631NaN0.750206
2020-01-06-0.4776580.464642-0.0349050.1162260.958563-0.1185010.277993-0.320429-0.001766-0.352186...0.0308070.0236810.010619NaN0.0169530.0332030.0424060.027906NaN0.752375
2020-01-07-0.4749130.456438-0.0305960.1188670.953152-0.1174360.274219-0.315071-0.000874-0.350100...0.0301400.0242150.010716NaN0.0172400.0330220.0428670.027853NaN0.752054
2020-01-08-0.4744130.452745-0.0264170.1239230.951369-0.1152940.271193-0.305295-0.000920-0.345431...0.0301760.0236940.010671NaN0.0173030.0327770.0409770.027820NaN0.748039

5 rows × 43 columns

An.attr_daily_returns.head(5) #查看日度收益拆解
<style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
sizebetamomentumresidual_volatilitynon_linear_sizebook_to_price_ratioliquidityearnings_yieldgrowthleverage...801970801120801790801760801890801960countrycommon_returnspecific_returntotal_return
2020-01-02NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN...NaNNaNNaNNaNNaNNaNNaN0.000000NaNNaN
2020-01-030.000241-0.0001440.0001300.0000900.000955-0.000039-0.0000450.0001747.907650e-080.000148...NaN-0.000168-0.0000190.000500-0.000050NaN0.0008600.003030-0.0010830.001948
2020-01-06-0.0000140.0001510.0001190.0001990.002035-0.0000170.0000250.000573-1.457480e-070.000160...NaN-0.000178-0.0001450.0002860.000015NaN0.0009490.0049900.0023580.007348
2020-01-070.0001760.0012080.0000020.0002360.0015330.000012-0.000213-0.0006278.726552e-070.000250...NaN0.000077-0.0000030.000834-0.000008NaN0.0068750.009541-0.0006210.008920
2020-01-08-0.000190-0.001919-0.0000070.0000190.0001990.000027-0.0001340.000400-8.393073e-09-0.000140...NaN0.000038-0.000384-0.0004140.000104NaN-0.009655-0.010019-0.000516-0.010535

5 rows × 46 columns

An.attr_returns.head(5) #查看累积收益
<style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
sizebetamomentumresidual_volatilitynon_linear_sizebook_to_price_ratioliquidityearnings_yieldgrowthleverage...801970801120801790801760801890801960countrycommon_returnspecific_returntotal_return
2020-01-02NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN...NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN
2020-01-030.000241-0.0001440.0001300.0000900.000955-0.000039-0.0000450.0001747.907650e-080.000148...NaN-0.000168-0.0000190.000500-0.000050NaN0.0008600.003030-0.0010830.001948
2020-01-060.0002270.0000070.0002490.0002900.002994-0.000056-0.0000200.000748-6.695534e-080.000308...NaN-0.000346-0.0001640.000787-0.000035NaN0.0018120.0080300.0012800.009310
2020-01-070.0004050.0012260.0002520.0005280.004541-0.000044-0.0002340.0001158.138242e-070.000560...NaN-0.000268-0.0001680.001629-0.000043NaN0.0087500.0176600.0006530.018313
2020-01-080.000212-0.0007280.0002450.0005470.004744-0.000016-0.0003710.0005228.052775e-070.000418...NaN-0.000229-0.0005590.0012070.000064NaN-0.0010810.0074570.0001280.007585

5 rows × 46 columns

An.get_attr_returns2bench('000905.XSHG').head(5) #查看相对指数的累积收益
<style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
sizebetamomentumresidual_volatilitynon_linear_sizebook_to_price_ratioliquidityearnings_yieldgrowthleverage...801970801120801790801760801890801960common_returncashspecific_returntotal_return
2020-01-02NaNNaNNaNNaNNaNNaNNaNNaNNaNNaN...NaNNaNNaNNaNNaNNaN0.0000000.0000000.0000000.000000
2020-01-032.247752e-085.274612e-07-1.010579e-06-1.780933e-07-5.018849e-09-1.576053e-071.815168e-073.067299e-07-8.676436e-083.843589e-07...NaN-8.367921e-072.211999e-072.512287e-07-2.031997e-07NaN-0.000006-0.000670-0.000079-0.000755
2020-01-063.139000e-09-2.167887e-061.005890e-06-9.837778e-061.803920e-063.592758e-07-3.082887e-07-4.489268e-06-1.570012e-07-7.565016e-07...NaN-4.620739e-06-2.607788e-06-8.734669e-06-1.166518e-07NaN-0.000063-0.003198-0.000234-0.003494
2020-01-07-5.129552e-08-2.485408e-059.140735e-07-2.227106e-051.453669e-06-5.066033e-084.500972e-064.348111e-061.794315e-07-3.707358e-06...NaN-1.876927e-06-2.703177e-06-3.476170e-05-2.429496e-07NaN-0.000095-0.006224-0.000283-0.006603
2020-01-08-1.236180e-074.020758e-051.082783e-06-2.386474e-051.502709e-06-1.806807e-061.001751e-05-7.241071e-061.893800e-07-1.425501e-06...NaN2.019730e-07-1.379156e-05-1.232299e-051.799073e-06NaN-0.000087-0.002647-0.000427-0.003160

5 rows × 46 columns

An.plot_exposure(factors='style',index_symbol=None,figsize=(15,7))

Img

An.plot_returns(factors='style',index_symbol=None,figsize=(15,7))

Img

An.plot_exposure_and_returns(factors='style',index_symbol=None,show_factor_perf=False,figsize=(12,6))

Img

因子数据本地缓存使用示例

具体用法请查看API文档, 此处仅作示例

设置缓存目录

fromjqfactor_analyzer.factor_cacheimportset_cache_dir,get_cache_dir# my_path = 'E:\\jqfactor_cache'# set_cache_dir(my_path) #设置缓存目录为my_pathprint(get_cache_dir()) #输出缓存目录
C:\Users\wq\jqfactor_datacache\bundle

缓存/检查缓存和读取已缓存数据

fromjqfactor_analyzer.factor_cacheimportsave_factor_values_by_group,get_factor_values_by_cache,get_factor_folder,get_cache_dir# import jqdatasdk as jq# jq.auth("账号",'密码') #登陆jqdatasdk来从服务端缓存数据all_factors=jqdatasdk.get_all_factors()
factor_names=all_factors[all_factors.category=='growth'].factor.tolist() #将聚宽因子库中的成长类因子作为一组因子group_name='growth_factors'#因子组名定义为'growth_factors'start_date='2021-01-01'end_date='2021-06-01'# 检查/缓存因子数据factor_path=save_factor_values_by_group(start_date,end_date,factor_names=factor_names,group_name=group_name,overwrite=False,show_progress=True)
# factor_path = os.path.join(get_cache_dir(), get_factor_folder(factor_names,group_name=group_name) #等同于save_factor_values_by_group返回的路径
check/save factor cache : 100%|██████████| 6/6 [00:01<00:00, 5.87it/s]
# 循环获取缓存的因子数据,并拼接trade_days=jqdatasdk.get_trade_days(start_date,end_date)
factor_values= {}
fordateintrade_days:
factor_values[date] =get_factor_values_by_cache(date,codes=None,factor_names=factor_names,group_name=group_name, factor_path=factor_path)#这里实际只需要指定group_name,factor_names参数的其中一个,缓存时指定了group_name时,factor_names不生效factor_values=pd.concat(factor_values)
factor_values.head(5)
<style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
financing_cash_growth_ratenet_asset_growth_ratenet_operate_cashflow_growth_ratenet_profit_growth_ratenp_parent_company_owners_growth_rateoperating_revenue_growth_ratePEGtotal_asset_growth_ratetotal_profit_growth_rate
code
2021-01-04000001.XSHE4.2186070.245417-3.438636-0.036129-0.0361290.139493NaN0.172409-0.053686
000002.XSHE-1.0593060.2360220.2660200.0097710.0648280.1154571.2294230.107217-0.013790
000004.XSHENaN11.430834-0.019530-3.350306-3.551808-0.328126NaN10.912087-3.888289
000005.XSHE-1.0143410.052103-2.331018-0.480705-0.461062-0.700859NaN-0.040798-0.567470
000006.XSHE-0.9787570.112236-1.5097280.0830890.0448690.1700411.931730-0.0056110.113066

单因子分析使用示例

具体用法请查看API文档, 此处仅作示例

示例:5日平均换手率因子分析

# 载入函数库importpandasaspdimportjqfactor_analyzerasja# 获取5日平均换手率因子2018-01-01到2018-12-31之间的数据(示例用从库中直接调取)# 聚宽因子库数据获取方法在下方fromjqfactor_analyzer.sampleimportVOL5factor_data=VOL5# 对因子进行分析far=ja.analyze_factor(
factor_data, # factor_data 为因子值的 pandas.DataFramequantiles=10,
periods=(1, 10),
industry='jq_l1',
weight_method='avg',
max_loss=0.1
)
# 获取整理后的因子的IC值far.ic
check/save price cache : 100%|██████████| 13/13 [00:00<00:00, 25.60it/s]
load price info : 100%|██████████| 253/253 [00:06<00:00, 38.09it/s]
load industry info : 100%|██████████| 243/243 [00:00<00:00, 331.46it/s]
<style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
period_1period_10
date
2018-01-020.141204-0.058936
2018-01-030.082738-0.176327
2018-01-04-0.183788-0.196901
2018-01-050.057023-0.180102
2018-01-08-0.025403-0.187145
.........
2018-12-240.098161-0.198127
2018-12-25-0.269072-0.166092
2018-12-26-0.430034-0.117108
2018-12-27-0.107514-0.040684
2018-12-28-0.0132240.039446

243 rows × 2 columns

# 生成统计图表far.create_full_tear_sheet(
demeaned=False, group_adjust=False, by_group=False,
turnover_periods=None, avgretplot=(5, 15), std_bar=False
)
分位数统计
<style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
minmaxmeanstdcountcount %
factor_quantile
10.000000.300460.0720190.056611729310.054595
20.088460.490340.1988440.066169726610.017371
30.149540.659840.3099610.08931072199.952574
40.225940.801360.4239780.11114172489.992555
50.309040.994000.5536840.133578728010.036672
60.388601.237600.6965310.16634172119.941545
70.483941.565020.8744880.20482872409.981526
80.619002.095601.1322610.26573972269.962225
90.849843.307901.6398630.436992726110.010478
101.2317240.477264.2762703.640945729010.050459

​ ​ ------------------------- ​ ​ 收益分析

<style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
period_1period_10
Ann. alpha-0.087-0.060
beta1.2181.238
Mean Period Wise Return Top Quantile (bps)-20.913-18.530
Mean Period Wise Return Bottom Quantile (bps)-6.156-6.452
Mean Period Wise Spread (bps)-14.757-13.177
<Figure size 640x480 with 0 Axes>

Img

<Figure size 640x480 with 0 Axes>

Img

......(图片过多,此处内容演示已省略,请参考api说明使用)

Img

​ ​ ------------------------- ​ ​ IC 分析

<style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
period_1period_10
IC Mean-0.030-0.085
IC Std.0.2130.176
IR-0.140-0.487
t-stat(IC)-2.180-7.587
p-value(IC)0.0300.000
IC Skew0.2400.091
IC Kurtosis-0.420-0.485
<Figure size 640x480 with 0 Axes>

Img

<Figure size 640x480 with 0 Axes>

​ ​ ------------------------- ​ ​ 换手率分析

<style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
period_1period_10
Quantile 1 Mean Turnover0.0550.222
Quantile 2 Mean Turnover0.1360.447
Quantile 3 Mean Turnover0.2060.599
Quantile 4 Mean Turnover0.2680.680
Quantile 5 Mean Turnover0.3070.730
Quantile 6 Mean Turnover0.3370.742
Quantile 7 Mean Turnover0.3260.735
Quantile 8 Mean Turnover0.2790.708
Quantile 9 Mean Turnover0.1960.593
Quantile 10 Mean Turnover0.0730.283
<style scoped> .dataframe tbody tr th:only-of-type { vertical-align: middle; }
.dataframe tbody tr th {
vertical-align: top;
}
.dataframe thead th {
text-align: right;
}
</style>
period_1period_10
Mean Factor Rank Autocorrelation0.9910.884

......(图片过多,此处内容演示已省略,请参考api说明使用)

获取聚宽因子库数据的方法

聚宽因子库包含数百个质量、情绪、风险等其他类目的因子

连接jqdatasdk获取数据包,数据接口需调用聚宽 jqdatasdk 接口获取金融数据 (试用注册地址)

# 获取因子数据:以5日平均换手率为例,该数据可以直接用于因子分析# 具体使用方法可以参照jqdatasdk的API文档importjqdatasdkjqdatasdk.auth('username', 'password')
# 获取聚宽因子库中的VOL5数据factor_data=jqdatasdk.get_factor_values(
securities=jqdatasdk.get_index_stocks('000300.XSHG'),
factors=['VOL5'],
start_date='2018-01-01',
end_date='2018-12-31')['VOL5']

将自有因子值转换成 DataFrame 格式的数据

  • index 为日期,格式为 pandas 日期通用的 DatetimeIndex

  • columns 为股票代码,格式要求符合聚宽的代码定义规则(如:平安银行的股票代码为 000001.XSHE)

    • 如果是深交所上市的股票,在股票代码后面需要加入 .XSHE
    • 如果是上交所上市的股票,在股票代码后面需要加入 .XSHG
  • 将 pandas.DataFrame 转换成满足格式要求数据格式

    首先要保证 index 为 DatetimeIndex 格式,一般是通过 pandas 提供的 pandas.to_datetime 函数进行转换,在转换前应确保 index 中的值都为合理的日期格式, 如 '2018-01-01' / '20180101',之后再调用 pandas.to_datetime 进行转换;另外应确保 index 的日期是按照从小到大的顺序排列的,可以通过 sort_index 进行排序;最后请检查 columns 中的股票代码是否都满足聚宽的代码定义。

importpandasaspdsample_data=pd.DataFrame(
[[0.84, 0.43, 2.33, 0.86, 0.96],
[1.06, 0.51, 2.60, 0.90, 1.09],
[1.12, 0.54, 2.68, 0.94, 1.12],
[1.07, 0.64, 2.65, 1.33, 1.15],
[1.21, 0.73, 2.97, 1.65, 1.19]],
index=['2018-01-02', '2018-01-03', '2018-01-04', '2018-01-05', '2018-01-08'],
columns=['000001.XSHE', '000002.XSHE', '000063.XSHE', '000069.XSHE', '000100.XSHE']
)
print(sample_data)
factor_data=sample_data.copy()
# 将 index 转换为 DatetimeIndexfactor_data.index=pd.to_datetime(factor_data.index)
# 将 DataFrame 按照日期顺序排列factor_data=factor_data.sort_index()
# 检查 columns 是否满足聚宽股票代码格式ifnotsample_data.columns.astype(str).str.match('\d{6}\.XSH[EG]').all():
print("有不满足聚宽股票代码格式的股票")
print(sample_data.columns[~sample_data.columns.astype(str).str.match('\d{6}\.XSH[EG]')])
print(factor_data)
  • 将键为日期,值为各股票因子值的 Series 的 dict 转换成 pandas.DataFrame,可以直接利用 pandas.DataFrame 生成
sample_data= \
{'2018-01-02': pd.Seris([0.84, 0.43, 2.33, 0.86, 0.96],
index=['000001.XSHE', '000002.XSHE', '000063.XSHE', '000069.XSHE', '000100.XSHE']),
'2018-01-03': pd.Seris([1.06, 0.51, 2.60, 0.90, 1.09],
index=['000001.XSHE', '000002.XSHE', '000063.XSHE', '000069.XSHE', '000100.XSHE']),
'2018-01-04': pd.Seris([1.12, 0.54, 2.68, 0.94, 1.12],
index=['000001.XSHE', '000002.XSHE', '000063.XSHE', '000069.XSHE', '000100.XSHE']),
'2018-01-05': pd.Seris([1.07, 0.64, 2.65, 1.33, 1.15],
index=['000001.XSHE', '000002.XSHE', '000063.XSHE', '000069.XSHE', '000100.XSHE']),
'2018-01-08': pd.Seris([1.21, 0.73, 2.97, 1.65, 1.19],
index=['000001.XSHE', '000002.XSHE', '000063.XSHE', '000069.XSHE', '000100.XSHE'])}
importpandasaspd# 直接调用 pd.DataFrame 将 dict 转换为 DataFramefactor_data=pd.DataFrame(data).Tprint(factor_data)
# 之后请按照 DataFrae 的方法转换成满足格式要求数据格式

About

聚宽单因子分析工具

Resources

Stars

690 stars

Watchers

25 watching

Forks

Releases

Packages

Used by

Contributors

Languages