当前位置: 首页 > news >正文

qlib因子分析之alphalens源码解读

百天计划第33篇,不知不觉一个多月。

"N阶行动"计划第2阶,这一阶就告诉自己要坚持,差不多可以挺过去。

坚持并不容易,早上起来心情有起伏。

投资说简单非常简单,就是低卖高卖;往难里说可能扯到宇宙星辰,人性善恶。

在量化人的眼中,一切都是因子。

技术面是因子,基本面也是因子。

有点像体验里验血、尿,B超等,给出一系列量化指标,再结合你的表述,症状,有经验的医生就可以给出结果。

当然总有很多信息是难以量化的,人是一个复杂系统。

股票也一样,所以才需要医生的存在。

量化投资本质上就是“找因子”,技术分析里可以量化的部分都是因子,因子进入模型不是hard-code的,而是以概率的形式,这就存在可以学习和优化的空间。

传统动量模型,比如20日动量>0.02就买入,小于0就卖出,和MACD>0一样,在大牛市非常好,震荡市让你怀疑人生,关键是你不知道当前是什么趋势。拉开了周期,这些因子都是alpha。

01 因子数据准备

alphalens的代码量不大,一共就4个文件:

get_clean_factor_and_forward_returns,在utils.py里。

这个函数返回如下格式的数据,它基于的输入:

因子值,这个还在下表中未动,但给因子分5层(quantile)。

基于价格prices,计算出未来1天(D),5天和20天的收益率。

具体想计算多少天都行,用periods=(1,5,20)来设置即可。

改成periods=(1,5,10,15,20),其实就是计算N天的预期收益率。

核心代码如下:

forward_returns = compute_forward_returns(
    factor,
    prices,
    periods,
    filter_zscore,
    cumulative_returns,
)

factor_data = get_clean_factor(factor, forward_returns, groupby=groupby,
                               groupby_labels=groupby_labels,
                               quantiles=quantiles, bins=bins,
                               binning_by_group=binning_by_group,
                               max_loss=max_loss, zero_aware=zero_aware)

compute_forward_returns就是计算“预期收益率”。

使用dataframe的 N期“变化率”,就是收益率。

for period in sorted(periods):
    if cumulative_returns:
        returns = prices.pct_change(period)

然后使用pandas的qcut函数,把因子分成5等分。

def quantile_calc(x, _quantiles, _bins, _zero_aware, _no_raise):
    try:
        if _quantiles is not None and _bins is None and not _zero_aware:
            return pd.qcut(x, _quantiles, labels=False) + 1
        elif _quantiles is not None and _bins is None and _zero_aware:
            pos_quantiles = pd.qcut(x[x >= 0], _quantiles // 2,
                                    labels=False) + _quantiles // 2 + 1
            neg_quantiles = pd.qcut(x[x < 0], _quantiles // 2,
                                    labels=False) + 1
            return pd.concat([pos_quantiles, neg_quantiles]).sort_index()
        elif _bins is not None and _quantiles is None and not _zero_aware:
            return pd.cut(x, _bins, labels=False) + 1
        elif _bins is not None and _quantiles is None and _zero_aware:
            pos_bins = pd.cut(x[x >= 0], _bins // 2,
                              labels=False) + _bins // 2 + 1
            neg_bins = pd.cut(x[x < 0], _bins // 2,
                              labels=False) + 1
            return pd.concat([pos_bins, neg_bins]).sort_index()
    except Exception as e:
        if _no_raise:
            return pd.Series(index=x.index)
        raise e

02 因子分析

create_full_tear_sheet这个函数是总体分析入口。

一共做了四件事:

统计分位表:

plotting.plot_quantile_statistics_table(factor_data)

一共就两行代码:

quantile_stats = factor_data.groupby('factor_quantile') \
    .agg(['min', 'max', 'mean', 'std', 'count'])['factor']
quantile_stats['count %'] = quantile_stats['count'] \
    / quantile_stats['count'].sum() * 100.

就是因子值,按分位分组后,计算“最小值min”,"最大值max",“均值mean”,"标准差std"。大约每个分位占20%,符合预期。

这里可能会引发一个困惑:第一分位的max不应该 <= 第二分位的min嘛 ,怎么有这么多重叠?——按天分的,每天都分5段,总体来看,就会有区间重叠。

第二步:收益分析:

create_returns_tear_sheet(
    factor_data, long_short, group_neutral, by_group, set_context=False
)

等权买入5个分位的股票后,可以计算各周期的收益率。

平均收益与分位收益之间的回归分析:

universe_ret = factor_data.groupby(level='date')[
    utils.get_forward_returns_columns(factor_data.columns)] \
    .mean().loc[returns.index]

使用线性回归OLS:

alpha_beta = pd.DataFrame()
for period in returns.columns.values:
    x = universe_ret[period].values
    y = returns[period].values

x = add_constant(x)

  reg_fit = OLS(y, x).fit()
    try:
        alpha, beta = reg_fit.params

计算出alpha和beta。

收益分析看起来有点类似“回测”,按因子高低买卖,看回测结果——结果都不错,但似乎没什么用,关键还看“信息分析”。

第三步:信息分析:

def src_ic(group):
    f = group['factor']
    _ic = group[utils.get_forward_returns_columns(factor_data.columns)] \
        .apply(lambda x: stats.spearmanr(x, f)[0])
    return _ic

IC值就是相关系数,这个之前文章说过了。

相关系数都是负的,且绝对值小于0.05,就是不显著,或者说这个因子没啥用。

第四:换手率分析:

create_turnover_tear_sheet(factor_data, set_context=False)

小结:

基本把目前传统的因子分析说完了,展开代码来看,没有什么神秘的,就是基础统计分析和线性回归

单因子分析的逻辑是这样的,把因子从小到大分成5组,每天等权买这组,看period=1,5,10...之后的收益率情况。这是收益分析;把因子值直接与收益序列做相关性分析,得到IC值。最后交易会有换手率的问题。

最近文章:

基于alphalens对qlib的alpha158做单因子分析

人生B计划,不确定时代的应对之道

持续行动——从想到到做到

飞狐,科技公司CTO,用AI技术做量化投资;以投资视角观历史,解时事;专注个人成长与财富自由。

相关文章:

  • springboot企业人力资源管理系统毕业设计源码291816
  • cadence SPB17.4 - allegro - 手工放置过孔
  • ElasticSearch (ES)学习之路(六)Springboot2.3.1整合ES 7.6.1
  • 人类历史上第一个人工神经元模型为mp模型有何不提出
  • 独角兽资深架构师用7大部分13章节,彻底讲透SpringBoot生态体系
  • 【web-攻击web服务器】(13.1)Web服务器配置缺陷
  • 人工神经元网络基本构成,人工神经网络主要有
  • elasticsearch 相似度计算
  • linux驱动开发:中断和时间管理
  • (173)FPGA约束:单周期时序分析或默认时序分析
  • eclipse使用maven教程
  • 学生成绩查询(查最大值,最小值,平均值,升序,降序)
  • ElasticSearch 批量查询
  • Linux 系统调用的来龙去脉 (上)
  • Elasticsearch 查询时 判断不为null或不为空字符串
  • 网络传输文件的问题
  • [原]深入对比数据科学工具箱:Python和R 非结构化数据的结构化
  • Angular 响应式表单之下拉框
  • CentOS从零开始部署Nodejs项目
  • js 实现textarea输入字数提示
  • React-生命周期杂记
  • session共享问题解决方案
  • 动态规划入门(以爬楼梯为例)
  • 如何解决微信端直接跳WAP端
  • 入手阿里云新服务器的部署NODE
  • LIGO、Virgo第三轮探测告捷,同时探测到一对黑洞合并产生的引力波事件 ...
  • #考研#计算机文化知识1(局域网及网络互联)
  • (2022 CVPR) Unbiased Teacher v2
  • (C++20) consteval立即函数
  • (ZT)薛涌:谈贫说富
  • (定时器/计数器)中断系统(详解与使用)
  • (二)c52学习之旅-简单了解单片机
  • (一)80c52学习之旅-起始篇
  • (一)Neo4j下载安装以及初次使用
  • (一)基于IDEA的JAVA基础10
  • (转)c++ std::pair 与 std::make
  • ***监测系统的构建(chkrootkit )
  • .equal()和==的区别 怎样判断字符串为空问题: Illegal invoke-super to void nio.file.AccessDeniedException
  • .net MVC中使用angularJs刷新页面数据列表
  • .net on S60 ---- Net60 1.1发布 支持VS2008以及新的特性
  • .net 受管制代码
  • .Net程序帮助文档制作
  • .net分布式压力测试工具(Beetle.DT)
  • .Net通用分页类(存储过程分页版,可以选择页码的显示样式,且有中英选择)
  • .NET学习全景图
  • :O)修改linux硬件时间
  • []C/C++读取串口接收到的数据程序
  • [2018][note]用于超快偏振开关和动态光束分裂的all-optical有源THz超表——
  • [2019.2.28]BZOJ4033 [HAOI2015]树上染色
  • [ai笔记9] openAI Sora技术文档引用文献汇总
  • [bbk5179]第66集 第7章 - 数据库的维护 03
  • [ccc3.0][数字钥匙] UWB配置和使用(二)
  • [C语言]——函数递归
  • [ffmpeg] av_opt_set 解析
  • [hihocoder1395] 最大权闭合子图