【宽客学院】单因子分析


(iQuant) #1

导语:了解了因子、标注和机器学习模型算法的基本知识后,面临的就是如何开发好的策略。寻找的因子是建立策略的基础,通过组合多个有效因子可以构建比较好的策略。本文主要介绍单因子分析模块的使用,通过该模块可以帮助大家检测评判单个因子的质量,为策略构建夯实基础。

一、因子、风险与阿尔法

因子的本质是一个信息流,也可以看做一个数学表达式,数据的变化反应并包含了投资信息,同时也代表了一个投资模式。

例如:收盘价close这个因子表达式,背后的假设就是股价越高未来收益越大,以此因子构建组合的权重比例其实就是定期轮仓购买高价股的投资模式/策略。

通常而言那些能够持续产生超额收益的因子或者投资模式是稀缺而少为人知的,这些因子又常被称为Alpha。例如市值因子、动量因子等都被学术界和投资界验证过是曾经有效的因子。

一个非常复杂的系统会表现出某种程度的可预测性。市场不断诞生有效的alpha(投资模式)并随着资金的介入而逐渐缩小,直到其逐渐失效。但这一过程将在市场上引入/创造其它的模式,从而诞生新的alpha
良好的样本内性能无法保证良好的样本外性能。历史数据的校验越多,对alpha的信心越大,但基本市场结构的变化也会让alpha无法继续有效,就比如2017年的白马股行情其实就是小市值因子/投资模式的失效。因此,需要不断在对alpha的验证和使用之间权衡和尝试。

二、怎样快速验证因子的优劣呢?

通常可以使用信息比率(alpha的平均值/标准差)来粗略评估其预测能力。此外还可以考察:

  • 因子的表达式相对简单;
  • 具有良好的样本内和样本外的sharpe;
  • 对于数据和参数的微小变化不敏感,例如回测时间段等;
  • 适用于多个市场;
  • 适用于多个地区;
  • 最近的收益曲线创新高

三、怎样判断因子失效呢?

既然有效的因子Alpha在市场中是不断的产生和消亡,如何判断一个因子是否失效了呢?

  • 回撤超过正常水平
  • 夏普比率下降

四、单因子的开发、检验和改进

1、首先确定表达式,通常变量来自于:

  • 价格/成交量
  • 基本面
  • 宏观数据
  • 文本:如期刊、新闻、会议记录、社交媒体信息

2、检验因子:
一个有效的因子选出的股票应该尽可能地分布在尽可能多的行业上,而不是过于集中。此外分层回测也是检验alpha的一个好方法,可以辅助我们查看alpha的头部或者尾部的预测能力。如果多空收益大部分来源于头部分组的盈利,那么如果头部分组收益下降就可能对此阿尔法的性能造成较大的影响。

敏感性测试和显着性测试是很重要的。 一个好的因子应该对噪声不敏感。测试稳健性的最常用技术包括对不同时间段、不同持续时间、随机数据子集、每个股票部门等的数据进行测试,我们对那些对这些输入变化不敏感的信号更有信心。

3、改进因子:

从因子数据处理角度可以如下改进:

  • 去除原始数据的异常值
  • 改变数据表达方式
    例如: 将一个绝对数量含义的变量转化为当前值与其历史值的比值,用来表示该变量的变动
  • 数据的中性化处理
    通常市场风险和行业风险是最大的风险,我们通过中性化保证每个行业内的alpha总和为0,同时保证全市场的所有股票alpha的总和为0,这样可以有效消除市场风险和行业风险从而降低最大回撤,提高信息比率。此外通过采用alpha值的rank可以进一步提高信息比率。如果换手率偏高,可以通过利用衰变(时间尺度上的长周期均匀化)在一个时间窗口内平均这个alpha。
  • 提高alpha的鲁棒性
    排序:使用因子的排序将原始alpha转换到[0,1]区间
    分位数:使用因子分位数
    Fisher变换:将原始alpha转换为近似服从正态分布。
    Z变换:将原始alpha转化为零均值和单位标准差的分布

此外可以通过非线性算法提升因子收益,例如利用因子数据训练一个AI算法模型,找到因子与收益之间的非线性关系。

本文着重介绍BigQuant平台在单因子分析方面的工具及使用。

五、单因子分析模块

该模块用于检验在月度数据尺度上,因子表达式与收益之间的线性关系

我们以市值因子为例,输入marker_cap_0因子表达式和回测起止时间,运行模块可得到分析结果。

模块使用案例如下:

克隆策略

单因子分析

版本v1.0

1、新建空白可视化策略

2、从左侧的模块列表“用户模块”——“共享模块”中拖入“单因子分析”模块,输入指定的因子表达式和回测起止时间

3、计算后可以获取指定因子在测试时间段内:

  • 月度因子暴露值: 按月度频率使用全市场股票数据计算因子暴露值
  • 因子暴露时序序列:按月度频率使用全市场股票数据计算的因子暴露值序列
  • 指定因子与九大类因子的相关系数:九大类因子分别为规模因子、成长因子、贝塔因子、流动性因子、杠杆因子、价值因子、反转因子、动量因子和波动性因子
  • 因子暴露值在各行业的分布:各行业内股票计算各行业的因子暴露值
  • 因子的Rank_IC值序列:按月度频率使用全市场股票数据计算因子的Rank_IC值序列
  • 因子分组收益:按股票因子值降序排列,利用因子值的分位数将全市场股票分为5组,计算分别持有5组股票组合的净值曲线
  • 多空组合收益:按股票因子值降序排列,利用因子值的分位数将全市场股票分为5组,计算做多第一组股票同时做空第五组股票(多空组合)的净值曲线
  • 因子收益:按月度频率使用全市场股票数据计算每月的因子收益
  • 因子收益t检验:对因子收益计算t检验统计量的值

    {"Description":"实验创建于2017/8/26","Summary":"","Graph":{"EdgesInternal":[],"ModuleNodes":[{"Id":"-2434","ModuleId":"BigQuantSpace.single_factor_analysis.single_factor_analysis-v2","ModuleParameters":[{"Name":"factor","Value":"market_cap_0","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"start_date","Value":"2010-01-01","ValueType":"Literal","LinkedGlobalParameter":null},{"Name":"end_date","Value":"2018-10-31","ValueType":"Literal","LinkedGlobalParameter":null}],"InputPortsInternal":[],"OutputPortsInternal":[],"UsePreviousResults":true,"moduleIdForCode":1,"IsPartOfPartialRun":null,"Comment":"","CommentCollapsed":true}],"SerializedClientData":"<?xml version='1.0' encoding='utf-16'?><DataV1 xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'><Meta /><NodePositions><NodePosition Node='-2434' Position='-78,35,200,200'/></NodePositions><NodeGroups /></DataV1>"},"IsDraft":true,"ParentExperimentId":null,"WebService":{"IsWebServiceExperiment":false,"Inputs":[],"Outputs":[],"Parameters":[{"Name":"交易日期","Value":"","ParameterDefinition":{"Name":"交易日期","FriendlyName":"交易日期","DefaultValue":"","ParameterType":"String","HasDefaultValue":true,"IsOptional":true,"ParameterRules":[],"HasRules":false,"MarkupType":0,"CredentialDescriptor":null}}],"WebServiceGroupId":null,"SerializedClientData":"<?xml version='1.0' encoding='utf-16'?><DataV1 xmlns:xsd='http://www.w3.org/2001/XMLSchema' xmlns:xsi='http://www.w3.org/2001/XMLSchema-instance'><Meta /><NodePositions></NodePositions><NodeGroups /></DataV1>"},"DisableNodesUpdate":false,"Category":"user","Tags":[],"IsPartialRun":true}
    In [1]:
    # 本代码由可视化策略环境自动生成 2019年1月25日 16:25
    # 本代码单元只能在可视化模式下编辑。您也可以拷贝代码,粘贴到新建的代码单元或者策略,然后修改。
    
    
    m1 = M.single_factor_analysis.v2(
        factor='market_cap_0',
        start_date='2010-01-01',
        end_date='2018-10-31'
    )
    
    [2018-11-30 14:06:02.284340] INFO: bigquant: single_factor_analysis.v2 开始运行..
    [2018-11-30 14:06:57.962667] INFO: bigquant: instruments.v2 开始运行..
    [2018-11-30 14:06:58.016276] INFO: bigquant: instruments.v2 运行完成[0.053617s].
    [2018-11-30 14:06:58.020468] INFO: bigquant: input_features.v1 开始运行..
    [2018-11-30 14:06:58.025927] INFO: bigquant: 命中缓存
    [2018-11-30 14:06:58.027025] INFO: bigquant: input_features.v1 运行完成[0.006559s].
    [2018-11-30 14:06:58.071922] INFO: bigquant: general_feature_extractor.v7 开始运行..
    [2018-11-30 14:06:58.843374] INFO: 基础特征抽取: 年份 2010, 特征行数=431567
    [2018-11-30 14:06:59.703015] INFO: 基础特征抽取: 年份 2011, 特征行数=511455
    [2018-11-30 14:07:00.810772] INFO: 基础特征抽取: 年份 2012, 特征行数=565675
    [2018-11-30 14:07:01.753242] INFO: 基础特征抽取: 年份 2013, 特征行数=564168
    [2018-11-30 14:07:02.755395] INFO: 基础特征抽取: 年份 2014, 特征行数=569948
    [2018-11-30 14:07:03.965461] INFO: 基础特征抽取: 年份 2015, 特征行数=569698
    [2018-11-30 14:07:05.073574] INFO: 基础特征抽取: 年份 2016, 特征行数=641546
    [2018-11-30 14:07:07.392636] INFO: 基础特征抽取: 年份 2017, 特征行数=743233
    [2018-11-30 14:07:09.282098] INFO: 基础特征抽取: 年份 2018, 特征行数=668868
    [2018-11-30 14:07:09.310713] INFO: 基础特征抽取: 总行数: 5266158
    [2018-11-30 14:07:09.320754] INFO: bigquant: general_feature_extractor.v7 运行完成[11.248843s].
    [2018-11-30 14:07:09.322999] INFO: bigquant: input_features.v1 开始运行..
    [2018-11-30 14:07:09.326800] INFO: bigquant: 命中缓存
    [2018-11-30 14:07:09.327628] INFO: bigquant: input_features.v1 运行完成[0.004604s].
    [2018-11-30 14:07:09.331002] INFO: bigquant: derived_feature_extractor.v3 开始运行..
    [2018-11-30 14:07:11.216944] INFO: derived_feature_extractor: /y_2010, 431567
    [2018-11-30 14:07:11.486771] INFO: derived_feature_extractor: /y_2011, 511455
    [2018-11-30 14:07:11.817230] INFO: derived_feature_extractor: /y_2012, 565675
    [2018-11-30 14:07:12.290917] INFO: derived_feature_extractor: /y_2013, 564168
    [2018-11-30 14:07:12.658485] INFO: derived_feature_extractor: /y_2014, 569948
    [2018-11-30 14:07:13.033632] INFO: derived_feature_extractor: /y_2015, 569698
    [2018-11-30 14:07:13.394164] INFO: derived_feature_extractor: /y_2016, 641546
    [2018-11-30 14:07:13.805529] INFO: derived_feature_extractor: /y_2017, 743233
    [2018-11-30 14:07:14.377223] INFO: derived_feature_extractor: /y_2018, 668868
    [2018-11-30 14:07:14.730382] INFO: bigquant: derived_feature_extractor.v3 运行完成[5.399343s].
    [2018-11-30 14:08:1543558087] INFO: factor_df loaded
    [2018-11-30 14:08:1543558101] INFO: processed_df loaded
    [2018-11-30 14:08:1543558101] INFO: ols loaded
    [2018-11-30 14:08:1543558111] INFO: factor_industry_dist_df loaded
    [2018-11-30 14:08:1543558124] INFO: rank_IC loaded
    [2018-11-30 14:13:1543558436] INFO: LIQUIDITY factor completed
    [2018-11-30 14:20:1543558804] INFO: REVERSAL factor completed
    [2018-11-30 14:20:1543558811] INFO: benchmark_factors_df completed
    [2018-11-30 14:23:1543558981] INFO: benchmark_factors_df resampled
    [2018-11-30 14:23:1543558982] INFO: benchmark_factors_df processed
    [2018-11-30 14:23:1543558982] INFO: corr_process loaded
    
    After runner done!
    [2018-11-30 14:23:04.498967] INFO: bigquant: single_factor_analysis.v2 运行完成[1022.214651s].
    

    结语: 本文以市值因子为例,展示了如何使用单因子分析模块进行月频尺度上因子的有效性评估。大家也可以使用StockRanker等模型放入单因子采用月度轮仓策略逻辑测试一下非线性模型训练的效果。


    (Plenari) #2

    用AI分析单因子的时候,大部分数据用于训练,怎么证明他在长时间有效呢?


    (达达) #3

    金融市场是时间变化的,政策或者结构变化都可能会导致一个因子的失效,比如高频交易中的手续费。
    具备一定的经济学逻辑基础的因子,在给定的条件下是大概率有效的,但是由于金融市场的时变性也无法保证能长时间有效。


    (liu) #4

    请问小白想做一个反转因子分析,怎么弄啊,什么思路都没有。快哭了。。求大神帮帮忙。


    (小Q) #5

    可以造一个和动量因子相反的因子。可以参考更多的研报内容。


    (liu) #6

    可以详细说说吗,比如什么地方的研报,名称等等的。。谢谢


    (达达) #7

    很多吧,例如东方证券


    (liu) #8

    但是不知道怎么编写代码,回测。而且代码都没有注解,感觉好难看懂代码。更不知道如何编写。


    (liu) #9

    我看这个研报对初学者难度很大。。


    (达达) #10

    简单的讲,对过去N日收益率排序,取前几名买入就可以认为是一个动量策略,取后几名买入就可以认为是个反转策略。
    关于测试可以有两种思路:
    单因子测试模板中因子写一个return_30,就可以测试出这个因子在线性模型下的效果和对应这个因子分层排序的回测结果,分层的回测结果差距越大说明因子的选股能力越强,或者看IC值。但任何因子存在一个有效/失效的波动,也就是IC值的波动越小越稳定,或者看多空收益曲线的回撤越小说明这个因子有效性比较稳定。

    如果做非线性分析,也就是说如果你画出return_30因子和收益率之间变量分布,两者不是线性关系,那么通过StockRanker等算法可以挖掘这种非线性关系,直接用AI模板策略填入return_30因子,回测看效果。


    (cash01) #11

    单因子分析是不是只能用与一些基本因子,wq101 和gtja191里的因子不能直接拿来用,还有能不能以数字的形式显示结果,例如Rank_IC,这样方便统计和分析