量化交易:因子风险暴露

news2024/11/20 1:21:29

本文介绍了如何计算因子风险暴露的内容。

判断风险暴露的建模是否合理

通常,此分析是基于历史数据,而对历史风险暴露的估计可能会影响未来的风险暴露。 因此,计算因子风险暴露是不够的。 必须对风险暴露保持信心,并明白对风险暴露的建模是否合理。

运用多因子模型计算因子风险暴露,可以运用多因子模型分析一个组合中风险和收益的来源,多因子模型对收益的分解如下:

通过对历史收益率进行建模,可以分析出收益中有多少是来自因子收益率,有多少来自资产特质波动(epsilon)。 我们也可以研究投资组合所面临的风险来源,即投资组合的因子暴露

在风险分析中,我们经常对主动回报(相对于基准的回报)和主动风险(主动回报的标准差,也称为跟踪误差或跟踪风险)进行建模。

例如,我们可计算到一个因子对主动风险的边际贡献——FMCAR。 对于因子j,表示为:

b_j表示组合对因子j的风险暴露,b_i表示组合对因子i的风险暴露,K表示一共K个因子。FMCAR_j这项指标这告诉我们,假设其他条件不变,暴露在因子j下我们增加了多少风险。

策略案例

附件:运用Fama-French三因子模型演示因子风险暴露

# 导入要用到的模块
import numpy as np
import statsmodels.api as sm
import scipy.stats as stats
from statsmodels import regression
import matplotlib.pyplot as plt
import pandas as pd

获取总市值、总市值排序、市净率、市净率排序、日收益率

start_date = '2016-01-01'
end_date = '2017-05-10'
raw_data = D.features(D.instruments(),start_date,end_date,fields=     
                      ['market_cap_0','rank_market_cap_0','pb_lf_0','rank_pb_lf_0','daily_return_0']) 
# 每日股票数量
stock_count = raw_data[['date','instrument']].groupby('date').count()
result=raw_data.merge(stock_count.reset_index('date'), on=['date'], how='outer') 
result = result.rename(columns={'instrument_x':'instrument','instrument_y':'stock_count'})

我们将市值最小的600只股票记为smallest组,将市值最大的600只股票记为biggest组

我们将市净率最小的600股票记为lowpb组,将市净率最大的600只股票记为highpb组

def is_smallest(x): 
    if x.rank_market_cap_0 < 600/x.stock_count:
        return True
    else:
        return False
result['smallest'] = result.apply(is_smallest,axis=1)

def is_biggest(x): 
    if x.rank_market_cap_0 > 1-600/x.stock_count:
        return True
    else:
        return False
result['biggest'] = result.apply(is_biggest,axis=1)

def is_lowpb(x): 
    if x.rank_pb_lf_0 < 600/x.stock_count:
        return True
    else:
        return False
result['lowpb'] = result.apply(is_lowpb,axis=1)

def is_highpb(x): 
    if x.rank_pb_lf_0 > 1-600/x.stock_count:
        return True
    else:
        return False
result['highpb'] = result.apply(is_highpb,axis=1)

result = result.set_index('date')

计算每日因子收益率

# 因子收益的定义,以市值因子举例,市值因子收益率=biggest组的平均收益率-smallest组的平均收益率
R_biggest = result[result.biggest]['daily_return_0'].groupby(level=0).mean()
R_smallest = result[result.smallest]['daily_return_0'].groupby(level=0).mean()
R_highpb = result[result.highpb]['daily_return_0'].groupby(level=0).mean()
R_lowpb = result[result.lowpb]['daily_return_0'].groupby(level=0).mean()
# 市值因子和市净率因子收益率
SMB = R_smallest - R_biggest
HML = R_lowpb - R_highpb

因子累计收益率并绘图

SMB_CUM = np.cumprod(SMB+1)
HML_CUM = np.cumprod(HML+1)

plt.plot(SMB_CUM.index, SMB_CUM.values,)
plt.plot(HML_CUM.index, HML_CUM.values)
plt.ylabel('Cumulative Return')
plt.legend(['SMB Portfolio Returns', 'HML Portfolio Returns']);

计算风险暴露程度

下面我们运用多因素模型和线性回归工具来计算某只股票的回报率相对于这些因子的风险暴露程度。我们以某个资产组合的主动收益作为被解释变量,对因子做回归,一个因子对主动收益贡献越大,那么这个资产组合的主动收益对于该因子的暴露程度也越高。

# 我们以5只股票的组合(portfolio)举例
instruments = D.instruments()[:5]
Stock_matrix = D.history_data(instruments,start_date,end_date,fields=['close'])
Stock_matrix = pd.pivot_table(Stock_matrix,values='close',index=['date'],columns=['instrument'])
portfolio = Stock_matrix.pct_change()[1:]
# 组合的每日收益率(等权重组合)
R = np.mean(portfolio, axis=1)
# 基准收益率
bench = D.history_data('000300.SHA',start_date, end_date, fields=['close']).set_index('date')['close'].pct_change()[1:]
# 主动收益率
active = R - bench
# 建立一个常数项,为下文回归做准备
constant = pd.TimeSeries(np.ones(len(active.index)), index=active.index)
df = pd.DataFrame({'R': active,
              'F1': SMB,
              'F2': HML,
              'Constant': constant})
# 删除含有缺失值的行
df = df.dropna()

线性回归并获取回归系数

b1, b2 = regression.linear_model.OLS(df['R'], df[['F1', 'F2']]).fit().params
# 因子对于主动收益的敏感性(即因子暴露)
print('Sensitivities of active returns to factors:\nSMB: %f\nHML: %f' %  (b1, b2))

边际贡献

利用前文中的公式,计算因子对主动收益风险平方的边际贡献(factors' marginal contributions to active risk squared,FMCAR )

# 计算因子风险贡献
F1 = df['F1']
F2 = df['F2']
cov = np.cov(F1, F2)
ar_squared = (active.std())**2
fmcar1 = (b1*(b2*cov[0,1] + b1*cov[0,0]))/ar_squared
fmcar2 = (b2*(b1*cov[0,1] + b2*cov[1,1]))/ar_squared
print('SMB Risk Contribution:', fmcar1)
print('HML Risk Contribution:', fmcar2)

余下的风险可以归结于一些特有的风险因素,即我们没有加入模型的因子或者资产组合本身独有的某种风险。 通常我们会关注一下对这些因子的风险暴露随时间如何变化。让我们rolling一下~

# 计算滚动的beta
model = pd.stats.ols.MovingOLS(y = df['R'], x=df[['F1', 'F2']], 
                             window_type='rolling', 
                             window=100)   
rolling_parameter_estimates = model.beta
rolling_parameter_estimates.plot()
plt.title('Computed Betas');
plt.legend(['F1 Beta', 'F2 Beta', 'Intercept']);

现在我们来看看FMCAR是如何随时间变化的

# 计算方差协方差
# 去除有缺省值的日期,从有实际有效值的日期开始
covariances = pd.rolling_cov(df[['F1', 'F2']], window=100)[99:]
# 计算主动风险
active_risk_squared = pd.rolling_std(active, window = 100)[99:]**2
# 计算beta
betas = rolling_parameter_estimates[['F1', 'F2']]

# 新建一个空的dataframe
FMCAR = pd.DataFrame(index=betas.index, columns=betas.columns)

# 每个因子循环
for factor in betas.columns:
    # 每一天循环
    for t in betas.index:
        # 求beta与协方差之积的和,见公式
        s = np.sum(betas.loc[t] * covariances[t][factor])
        # 获取beta
        b = betas.loc[t][factor]
        # 获取主动风险
        AR = active_risk_squared.loc[t]
        # 估计当天的FMCAR
        FMCAR[factor][t] = b * s / AR

因子对于主动收益风险的边际贡献

plt.plot(FMCAR['F1'].index, FMCAR['F1'].values)
plt.plot(FMCAR['F2'].index, FMCAR['F2'].values)

plt.ylabel('Marginal Contribution to Active Risk Squared')
plt.legend(['F1 FMCAR', 'F2 FMCAR'])

存在的问题

了解历史数据中组合对各个因子的暴露程度是很有趣的,但只有将它用在对未来预测上时,它才有用武之地。但我们不是总能够放心地认为未来的情况与现在相同,由于随时间会变化,对风险暴露程度取平均值也很容易出现问题。我们可以给均值加上一个置信区间,但只有当其分布是正态分布或者表现很稳健才行。我们来看看Jarque-Bera测验的结果。

from statsmodels.stats.stattools import jarque_bera
_, pvalue1, _, _ = jarque_bera(FMCAR['F1'].dropna().values)
_, pvalue2, _, _ = jarque_bera(FMCAR['F2'].dropna().values)

print('p-value F1_FMCAR is normally distributed', pvalue1)
print('p-value F2_FMCAR is normally distributed', pvalue2)

p_value显示我们可以显著的拒绝其为正态分布,可见对于未来这些因素会导致多少风险暴露是很难估计的,所以在使用这些统计模型去估计风险暴露并以此为依据来对冲是需要万分小心的。

 

 

 

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

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

相关文章

Compose入门

​ 本篇文章主要是为了对Compose有一个初步了解。知道Compose是做什么的&#xff0c;用Compose能干什么&#xff0c;在目前的各种UI框架下面有些优势&#xff0c;参考Google官网的解释加上一些自己的理解生成的一篇文章。本人也是Compose初学者&#xff0c;通过每一步学习遇到哪…

带你用uniapp从零开发一个仿小米商场_2.创建空白项目及公共样式引入

创建空白项目 打开uniapp 点击新建->项目 如下, 是编辑你项目的名字的地方是你项目存放地址,可以点击浏览器去文件管理里面选地址是模板选择,这里选择默认模板就好是一些其他选择比如uvue能让你项目在编译成软件时运行更快,unicloud能让你用js写后端,且直接就是云开发,g…

【WSA】无法打开 适用于 Android™ 的 Windows 子系统,因为它处于脱机状态。可能缺少存储设备,或者存储设备已断开连接。

问题描述 之前可以正常使用适用于 Android™ 的 Windows 子系统&#xff08;WSA&#xff09;&#xff0c;但突然间无法启动了。 当尝试启动WSA中的软件时&#xff0c;都会出现以下错误提示&#xff1a; 无法打开 适用于 Android™ 的 Windows 子系统&#xff0c;因为它处于脱…

基于springboot实现留守儿童爱心网站项目【项目源码+论文说明】计算机毕业设计

基于springboot实现留守儿童爱心网站演示 摘要 随着留守儿童爱心管理的不断发展&#xff0c;留守儿童爱心网站在现实生活中的使用和普及&#xff0c;留守儿童爱心管理成为近年内出现的一个热门话题&#xff0c;并且能够成为大众广为认可和接受的行为和选择。设计留守儿童爱心网…

数字逻辑电路基础-时序逻辑电路之移位寄存器

文章目录 一、移位寄存器定义二、verilog源码三、仿真结果一、移位寄存器定义 移位寄存器定义 A shift register is a type of digital circuit using a cascade of flip flops where the output of one flip-flop is connected to the input of the next. 移位寄存器是一种将…

js逆向-某敏感网站登录参数分析

声明 本文仅供学习参考&#xff0c;如有侵权可私信本人删除&#xff0c;请勿用于其他途径&#xff0c;违者后果自负&#xff01; 如果觉得文章对你有所帮助&#xff0c;可以给博主点击关注和收藏哦&#xff01; 前言 目标网站&#xff1a;aHR0cHM6Ly9tZGZnaGcuNXhwb2lqaHRm…

LED面板显示屏驱动芯片

一、基本概述 TM1638是一种带键盘扫描接口的LED&#xff08;发光二极管显示器&#xff09;驱动控制专用IC,内部集成有MCU数字接口、数据锁存器、LED驱动、键盘扫描等电路。本产品质量可靠、稳定性好、抗干扰能力强。 二、主要应用场合 主要适用于家电设备(智能热水器、微波炉…

leetcode刷题:17.电话号码的字母组合

leetcode原题网页 题目描述&#xff1a;给定一个仅包含数字 2-9 的字符串&#xff0c;返回所有它能表示的字母组合。答案可以按 任意顺序 返回。 给出数字到字母的映射如下&#xff08;与电话按键相同&#xff09;。注意 1 不对应任何字母。 思路&#xff1a;使用vector&#x…

基于51单片机超市快递寄存自动柜设计源程序

一、系统方案 1、本设计采用这51单片机作为主控器。 2、存包&#xff0c;GSM短信取件码。 3、液晶1620显示。 4、矩阵键盘输入取件码&#xff0c;完成取包。 二、硬件设计 原理图如下&#xff1a; 三、单片机软件设计 1、首先是系统初始化 /******************************…

#BUG SHOW# 深挖一个6年前的老“bug”

引言 最近参与了一个业务迁移的项目&#xff0c;需要把站点A迁移到站点B。不同的站点拥有各自独立的服务和数据库&#xff0c;可以说是毫无关联。为了兼容迁移过程中的存在的一部分特殊交易数据&#xff08;正向[支付]交易在站点A&#xff0c;但逆向[退款]操作在站点B操作&…

Oracle 最终抛弃了 Sun !

随着 Solaris 团队的彻底完蛋&#xff0c;看起来 Sun 微系统公司最终连块骨头都没剩下。 来自前 Sun 社区的消息表明&#xff0c;一月份的传闻&#xff08;Oracle 裁员 450 人&#xff09;成为了现实&#xff0c;上周五&#xff0c;Oracle 裁掉了 Solaris 和 SPARC 团队的核心员…

交换机的VRRP主备配置例子

拓朴如下&#xff1a; 主要配置如下&#xff1a; [S1] vlan batch 10 20 # interface Vlanif10ip address 10.1.1.1 255.255.255.0vrrp vrid 1 virtual-ip 10.1.1.254vrrp vrid 1 priority 200vrrp vrid 1 preempt-mode timer delay 20 # interface Vlanif20ip address 13.1.1…

QT visual stdio加载动态库报错126问题

报错126是找不到指定的模块 QT 查看构建目录&#xff0c;将依赖的动态库放到该目录下即可成功 visual stdio将依赖的动态库放到运行目录 在vs中使用导出类的动态库时&#xff0c;不但需要将对应的.dll放到对应的目录下&#xff0c;还需要将该动态库对应的.lib添加到如下配置才…

ChatGLM-6B下载安装

ChatGLM-6B下载安装 项目指向 想把模型下载本地微调 通过官网指引需要先下载git-lfs #Linux 下载安装 curl -s https://packagecloud.io/install/repositories/github/git-lfs/script.deb.sh | sudo bash sudo apt-get install git-lfs git lfs install如果是docker中的虚拟机…

物流单打印模板下载,佳易王物流托运单打印软件

物流单打印模板下载&#xff0c;佳易王物流托运单打印软件 上图是常用的物流单打印模板&#xff0c;佳易王物流单打印软件打印格式可以根据需要定制更改。 软件特色&#xff1a; 1、功能实用&#xff0c;操作简单&#xff0c;不会电脑也会操作&#xff0c;软件免安装&#xff…

Halcon [fill_up_shape],[close_circle],[dilation_circle]和[shape_trans]图像处理时填充区别

文章目录 文章专栏前言两者的区别fill_up_shapeshape_transclose_circledilation_circle 总结 文章专栏 我的Halcon开发 CSDN专栏 前言 本文用的案例是&#xff1a;Example: %HALCONEXAMPLES%/hdevelop/Applications/Completeness-Check/ball.hdev 两者的区别 [shape_trans]是…

【LLM】chatglm3的agent应用和微调实践

note 知识库和微调并不是冲突的&#xff0c;它们是两种相辅相成的行业解决方案。开发者可以同时使用两种方案来优化模型。例如&#xff1a; 使用微调的技术微调ChatGLM3-6B大模型模拟客服的回答的语气和基础的客服思维。接着&#xff0c;外挂知识库将最新的问答数据外挂给Chat…

vue2-006——使用脚手架搭建vue2项目+项目结构分析

一、创建项目&#xff1a;vue create 项目名 D:\EnyiWang\Documents\myStudy\vue>vue create vue_testVue CLI v5.0.8 ? Please pick a preset: Default ([Vue 2] babel, eslint)Vue CLI v5.0.8 ✨ Creating project in D:\EnyiWang\Documents\myStudy\vue\vue_test. &am…

批量按顺序1、2、3...重命名所有文件夹里的文件

最新&#xff1a; 最快方法&#xff1a;先用这个教程http://文件重命名1,2......nhttps://jingyan.baidu.com/article/495ba841281b7079b20ede2c.html再用这个教程去空格&#xff1a;利用批处理去掉文件名中的空格-百度经验 (baidu.com) 以下为原回答 注意文件名有空格会失败…

张弛声音变现课,惊悚电影配音篇

在提供惊悚片的声音配音服务时&#xff0c;配音员旨在制造一种让观众的心率加快、情绪紧张的气氛。惊悚片侧重于心理层面的紧张和预期的恐怖&#xff0c;声音在塑造这种心理效应中起到了至关重要的作用。演员需通过对声音的精细雕琢和调整来强化电影的悬念和紧迫感。以下是为惊…