因子特征工程:alphalens库深度解析

news2024/11/14 19:21:34

原创文章第107篇,专注“个人成长与财富自由、世界运作的逻辑, AI量化投资”。

前面的文章我们把数据,因子定制,自动标注的功能都准备好了,今天继续因子分析,分析的框架当然还是alphalens。

星球有一期研报复现讲的alphalens的使用:

【每周研报复现】AI量化特征工程之alphalens:一套用于分析 alpha 因子的通用工具

qlib因子分析之alphalens源码解读

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

alphalens的使用很简单,就是整理两个数据结构,主要是对pandas dataframe的使用要熟悉。

因子数据是以date,code为双索引的dataframe格式:

而收盘价是以日期为索引,而每个资产为单独一列:

准备好的数据之后,调用utils里的get_clear_factor_and_forward_returns:

得到未来N期(默认是1天,5天和10天的收益率),因子值,以及因子分位(factor_quantile,默认从小到大分成5份)

通过调用tears里的create_information_tear_sheet,得到信息分析的结果:

如上就是因子分析里的重要概念IC分析。

什么是IC呢?我们具体可以看alphalens的代码:

iC值等于同一横截面上收益率与因子的spearman相关性(就是我们熟悉的统计学中的相关系数):

stats.spearmanr( factor_data['5D'], factor_data['factor'])

生成IC表格的代码:

def plot_information_table(ic_data):
    ic_summary_table = pd.DataFrame()
    ic_summary_table["IC Mean"] = ic_data.mean()
    ic_summary_table["IC Std."] = ic_data.std()
    ic_summary_table["Risk-Adjusted IC"] = \
        ic_data.mean() / ic_data.std()
    t_stat, p_value = stats.ttest_1samp(ic_data, 0)
    ic_summary_table["t-stat(IC)"] = t_stat
    ic_summary_table["p-value(IC)"] = p_value
    ic_summary_table["IC Skew"] = stats.skew(ic_data)
    ic_summary_table["IC Kurtosis"] = stats.kurtosis(ic_data)

    print("Information Analysis")
    utils.print_table(ic_summary_table.apply(lambda x: x.round(3)).T)

可以看出来,IC值是每个截面的因子值与未来某期收益率的相关系数,然后对这个相关系数序列均值,标准差,偏度,峰度等等。风险调整后的IC就是IC均值/IC标准差。

一般而言,看RIC达到0.05以上认为相关性显著。

IC值越大越好。上面的例子中,20日动量与未来1天,5天及10天都有较显著的相关性,说明这是一个比较有效的因子。

收益分析:

先说后面三列,Top Quantile就是因子值最高的与最低的,两个构建组合。Spread就是两者之间的差。

Alpha与Beta:

这里的y是因子收益率,x是因子值,与IC不同,IC是两者之间的相关系数,而Alpha,Beta是二者之间的线性拟合。

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

@plotting.customize
def create_returns_tear_sheet(
    factor_data, long_short=True, group_neutral=False, by_group=False
):

    factor_returns = perf.factor_returns(
        factor_data, long_short, group_neutral
    )

    mean_quant_ret, std_quantile = perf.mean_return_by_quantile(
        factor_data,
        by_group=False,
        demeaned=long_short,
        group_adjust=group_neutral,
    )

    mean_quant_rateret = mean_quant_ret.apply(
        utils.rate_of_return, axis=0, base_period=mean_quant_ret.columns[0]
    )

    mean_quant_ret_bydate, std_quant_daily = perf.mean_return_by_quantile(
        factor_data,
        by_date=True,
        by_group=False,
        demeaned=long_short,
        group_adjust=group_neutral,
    )

    mean_quant_rateret_bydate = mean_quant_ret_bydate.apply(
        utils.rate_of_return,
        axis=0,
        base_period=mean_quant_ret_bydate.columns[0],
    )

    compstd_quant_daily = std_quant_daily.apply(
        utils.std_conversion, axis=0, base_period=std_quant_daily.columns[0]
    )

    alpha_beta = perf.factor_alpha_beta(
        factor_data, factor_returns, long_short, group_neutral
    )

    mean_ret_spread_quant, std_spread_quant = perf.compute_mean_returns_spread(
        mean_quant_rateret_bydate,
        factor_data["factor_quantile"].max(),
        factor_data["factor_quantile"].min(),
        std_err=compstd_quant_daily,
    )

    fr_cols = len(factor_returns.columns)
    vertical_sections = 2 + fr_cols * 3
    gf = GridFigure(rows=vertical_sections, cols=1)

    plotting.plot_returns_table(
        alpha_beta, mean_quant_rateret, mean_ret_spread_quant
    )

    plotting.plot_quantile_returns_bar(
        mean_quant_rateret,
        by_group=False,
        ylim_percentiles=None,
        ax=gf.next_row(),
    )

    plotting.plot_quantile_returns_violin(
        mean_quant_rateret_bydate, ylim_percentiles=(1, 99), ax=gf.next_row()
    )

    trading_calendar = factor_data.index.levels[0].freq
    if trading_calendar is None:
        trading_calendar = pd.tseries.offsets.BDay()
        warnings.warn(
            "'freq' not set in factor_data index: assuming business day",
            UserWarning,
        )

    # Compute cumulative returns from daily simple returns, if '1D'
    # returns are provided.
    if "1D" in factor_returns:
        title = (
            "Factor Weighted "
            + ("Group Neutral " if group_neutral else "")
            + ("Long/Short " if long_short else "")
            + "Portfolio Cumulative Return (1D Period)"
        )

        plotting.plot_cumulative_returns(
            factor_returns["1D"], period="1D", title=title, ax=gf.next_row()
        )

        plotting.plot_cumulative_returns_by_quantile(
            mean_quant_ret_bydate["1D"], period="1D", ax=gf.next_row()
        )

    ax_mean_quantile_returns_spread_ts = [
        gf.next_row() for x in range(fr_cols)
    ]
    plotting.plot_mean_quantile_returns_spread_time_series(
        mean_ret_spread_quant,
        std_err=std_spread_quant,
        bandwidth=0.5,
        ax=ax_mean_quantile_returns_spread_ts,
    )

    plt.show()
    gf.close()

    if by_group:
        (
            mean_return_quantile_group,
            mean_return_quantile_group_std_err,
        ) = perf.mean_return_by_quantile(
            factor_data,
            by_date=False,
            by_group=True,
            demeaned=long_short,
            group_adjust=group_neutral,
        )

        mean_quant_rateret_group = mean_return_quantile_group.apply(
            utils.rate_of_return,
            axis=0,
            base_period=mean_return_quantile_group.columns[0],
        )

        num_groups = len(
            mean_quant_rateret_group.index.get_level_values("group").unique()
        )

        vertical_sections = 1 + (((num_groups - 1) // 2) + 1)
        gf = GridFigure(rows=vertical_sections, cols=2)

        ax_quantile_returns_bar_by_group = [
            gf.next_cell() for _ in range(num_groups)
        ]
        plotting.plot_quantile_returns_bar(
            mean_quant_rateret_group,
            by_group=True,
            ylim_percentiles=(5, 95),
            ax=ax_quantile_returns_bar_by_group,
        )
        plt.show()
        gf.close()

不同分位计算收益率;

按分位数做投资组合,比如quantile=1的加权平均做一个组合,quanttile=5的做另一个组合。

我们只有3支,只形成三个分位段,这样形成按分位的组合序列:

小结:

今天重点分析了alphalens的IC分析与收益分析。IC分析是其中最重要的,就是单因子与预期收益之间的相关关系。

而收益分析类似“回测”,即买入因子最高分位的收益率是多少,最低分位的收益率是多少,两者多空的利差是多少。另外收益率与因子值做线性拟合,得到alpha和beta。
最新代码与数据,请前往星球量化专栏下载。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/12591.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Babel插件指南

Babel插件指南 文章目录Babel插件指南Babel简介AST(Abstract syntax tree)简介ESTree AST NodeVisitors(访问者)Babel APIbabylonbabel-traversebabel generator项目中实践引用自定义的babel插件新增插件js文件确定要实现的功能,编译成AST进行…

绘制花朵-第13届蓝桥杯Scratch选拔赛真题精选

[导读]:超平老师计划推出Scratch蓝桥杯真题解析100讲,这是超平老师解读Scratch蓝桥真题系列的第78讲。 蓝桥杯选拔赛每一届都要举行4~5次,和省赛、国赛相比,题目要简单不少,再加上篇幅有限,因此我精挑细选…

OpenYurt v1.1.0: 新增 DaemonSet 的 OTA 和 Auto 升级策略

作者:昌蒲、侯雪城 边缘计算云原生平台、CNCF SandBox 项目 - OpenYurt [1 ] ,近期发布了 v1.1.0 版本。 OpenYurt 作为边缘云原生领域的开源项目,采用云管边的云边一体化架构,致力于解决云原生落地边缘计算场景的痛点问题。针对…

扩充antd的Icon图标库

一、功能介绍 项目中有个菜单图标支持配置的功能,如下 二、遇到的问题 上面的图标都是antdIcon组件自带的,只需要给Icon传不同的type就可以显示出来不同的图标,但是我现在需要将自己的图标也放到这个里面,而且实现通过传个type…

asp.net+sqlserver个人简历生成系统C#项目

目 录 1 项目来源 1 1.1 项目背景 1 1.2目的和意义 1 1.3研究成果 2 2 系统开发环境 3 2.1 Visual Studio.NET开发平台 3 2.2 ASP.NET 2.0开发技术 3 2.3 ADO.NET数据访问技术 4 2.4 Microsoft SQL Server简介 4 2.5 B/S结构 5 3 需求分析 6…

服务端Skynet(五)——如何搭建一个实例

服务端Skynet(五)——如何搭建一个实例 文章目录服务端Skynet(五)——如何搭建一个实例1、配置文件2、服务消息分发与回应(call/send)3、通信(server/client)4、Mysql连接1、配置文件 ​ 搭建一个实例 主要看 config 文件的设置,如下: --config inclu…

RK3399驱动开发 | 15 - RTC实时时钟芯片HYM8563S调试(基于linux5.4.32内核)

文章目录 一、Linux RTC设备驱动框架二、HYM8563实时时钟芯片1. 简介2. 引脚图3. 连接原理图三、设备驱动调试1. 设备树节点描述2. 使能内核驱动3. 测试四、hym8563驱动实现分析1. i2c设备驱动框架2. rtc设备注册流程3. 通过i2c驱动操作硬件一、Linux RTC设备驱动框架 Linux内…

宝塔防火墙必要的快速操作指令

重新启动、禁止固定ip等 重启firewall-cmd --reload 禁止固定ip:firewall-cmd --permanent --add-rich-rulerule family"ipv4" source address"192.168.1.1" reject 取消富规则:firewall-cmd --list-rich-rules 删除富规则&#…

Java#9(文字格斗游戏和对象数组练习)

目录 一.文字格斗游戏 二.对象数组 三.键盘录入练习 四.复杂对象数组练习 题目要求: 一.文字格斗游戏 Role类的代码 package Game;import java.util.Random;public class Role {String name;int blood;public Role() {}public Role(String name, int blood) {this.name na…

Node.js 流 Stream【详解】

什么是流? 流是一种将整体数据分割成多个小块依次进行处理的方式。 举个形象的例子: 山上有1000颗拳头大的小石子,需要搬下山。 传统的处理方式:安排一辆大卡车,一次性将石子全部运下山。流的处理方式:修…

Nginx制作下载站点

nginx使用的是模块ngx_http_autoindex_module来实现的,该模块处理以斜杠(“/”)结尾的请求,并生成目录列表。 nginx编译的时候会自动加载该模块,但是该模块默认是关闭的,使用下来指令来完成对应的配置 autoindex 启用或禁用目录…

医疗器械许可证怎么办理

医疗器械经营许可证申请条件 1.有两个与业务规模和业务范围相适应的质量管理机构或大专以上学历的质量管理人员。质量管理人员应具有国家认可的相关专业资格或职称; 2.具有与经营规模和范围相适应的相对独立的经营场所; 3.具备与经营规模和经营范围相…

解读OpenShift的逻辑架构和技术架构

01 OpenShift的逻辑架构 OpenShift的逻辑架构图如图2-6所示。 ▲图2-6 OpenShift逻辑架构 图2-6中的关键组件介绍如下。 底层基础设施:OpenShift可以运行在公有云(AWS、Azure、Google等)、私有云(OpenStack)、虚拟机(vSphere、RHV、红帽KVM)、X86、IBM Power/Z服务器上。…

跨域及cors解决跨域

1.什么是跨域 出于浏览器的同源策略限制。同源策略(Sameoriginpolicy)是一种约定,它是浏览器最核心也最基本的安全功能,如果缺少了同源策略,则浏览器的正常功能可能都会受到影响。可以说Web是构建在同源策略基础之上的…

DJ11 8086系列处理器(第二节课)

目录 一、8088CPU的系统总线 1. 最小模式 2. 最大模式 二、8086/8088 CPU 的功能结构 1. 8086/8088 CPU 的内部结构 2. 8086/8088 CPU 的内部寄存器 1)通用寄存器 2)段寄存器 3)控制寄存器 三、8086/8088 CPU 的存储器组织 1. 物…

超级账本Fabric的世界状态操作与账本操作

在 Hyperledger Fabric 中,账本由两个不同但相关的部分组成 - 世界状态和区块链。 世界状态: 一个数据库,其中存储了一组帐本状态的当前值的缓存。世界状态使程序可以轻松地直接访问状态的当前值,而不必通过遍历整个交易日志来计…

PROTAC与抗体偶联药物的结合

PROTAC 的靶点真核生物的蛋白降解途径主要分为溶酶体途径、泛素蛋白酶体途径、胞液蛋白酶水解途径和线粒体蛋白酶途径等四种 (图1)。其中,PROTAC 所依赖的蛋白酶体途径主要针对细胞周期蛋白、转录因子、细胞表面受体以及胞内变性蛋白等进行降解。 图 1. 不同蛋白降…

《安富莱嵌入式周报》第291期:分分钟设计数字芯片,单片机版JS,神经网络DSP,microPLC,FatFS升级至V0.15,微软Arm64 VS正式版发布

往期周报汇总地址:嵌入式周报 - uCOS & uCGUI & emWin & embOS & TouchGFX & ThreadX - 硬汉嵌入式论坛 - Powered by Discuz! 视频版: https://www.bilibili.com/video/BV1Dd4y1b74x 《安富莱嵌入式周报》第291期:分分…

分享几个小技巧教你图片怎么加边框

大家平时出去玩的时候,肯定没少拍摄照片吧?那你们都是怎么对图片进行修饰的呢?我比较喜欢给图片加上一些边框线条,这样子的图片会比较有意境,能凸显我想要表达的意思。那么大家知道怎么在图片里加边框吗?今…

【Vue.js设计与实现】第4章 响应系统的作用与实现

前言: 本文是我看的Vue.js设计与实现这本书第二篇 响应系统 的第4章 响应系统的作用与实现的一些总结与收获。 第4章从宏观视角讲述了Vue.js 3.0中响应系统的实现机制。从副作用函数开始,逐步实现一个完善的响应系统,还讲述了计算属性和watch…