首页 > 其他分享 >手把手教你实现法玛三因子模型

手把手教你实现法玛三因子模型

时间:2023-09-26 19:22:06浏览次数:30  
标签:return 法玛 手把手 因子 factor date data market

更多精彩内容,欢迎关注公众号:数量技术宅,也可添加技术宅个人微信号:sljsz01,与我交流。

关于法玛三因子模型

法玛三因子模型(Fama-French Three-Factor Model)是一种资本资产定价模型(Capital Asset Pricing Model,CAPM)的扩展,用于解释股票回报的变异性。该模型由尤金·法玛(Eugene Fama)和肯尼斯·法rench(Kenneth French)于1992年提出。

该模型考虑了三个因子对股票回报的影响:市场风险因子、市值因子和价值因子。市场风险因子指的是股票市场整体的风险,可以用市场指数来代表。市值因子是指公司的市值大小,可以用市值指数来代表。价值因子是指公司的估值水平,可以用账面市值比(B/M)来代表。这三个因子被认为是影响股票回报的重要因素。

法玛三因子模型认为,股票的预期回报可以通过以下公式计算:

E(Ri) = Rf + βi(Market Risk Premium) + si(SMB) + hi(HML)

其中,E(Ri)表示股票i的预期回报,Rf表示无风险收益率,βi表示股票i的市场风险系数,Market Risk Premium表示市场风险因子的回报率减去无风险收益率,si表示股票i的市值因子系数,SMB表示市值因子的超额回报,hi表示股票i的价值因子系数,HML表示价值因子的超额回报。

通过考虑市值和价值因子,法玛三因子模型可以更好地解释股票回报的变异性。该模型被广泛应用于投资组合管理、风险管理和资产定价等领域。

Python代码实现

由于上述模型需要使用股票的市值和账面市值比等数据,我们需要先获取这些数据。以下是一种获取中国股票市值和账面市值比数据的方法:

import pandas as pd
import tushare as ts

# 获取股票列表
stock_list = ts.get_stock_basics().index.tolist()

# 获取股票市值数据
market_cap = ts.get_stock_basics().loc[:, 'totalAssets']

# 获取股票账面市值比数据
book_to_market = ts.get_stock_basics().loc[:, 'bvps'] / ts.get_stock_basics().loc[:, 'pb']

# 将市值和账面市值比数据合并到一个DataFrame中
data = pd.concat([market_cap, book_to_market], axis=1)
data.columns = ['market_cap', 'book_to_market']
data.index.name = 'code'
data = data.dropna()

接下来,我们可以使用以上获取的市值和账面市值比数据,以及股票收益率数据,来实现法玛三因子模型的计算。以下是一个简单的实现:

import numpy as np
import statsmodels.api as sm

# 获取股票收益率数据
start_date = '2020-01-01'
end_date = '2020-12-31'
return_data = pd.DataFrame()
for code in stock_list:
    try:
        stock_return = ts.pro_bar(ts_code=code, start_date=start_date, end_date=end_date, adj='qfq', 
                                   factors=['tor']).set_index('trade_date')['pct_chg']
        return_data[code] = stock_return
    except:
        pass

# 计算市场指数收益率
market_return = ts.pro_bar(ts_code='000001.SH', start_date=start_date, end_date=end_date, 
                           adj='qfq', factors=['tor']).set_index('trade_date')['pct_chg']
market_return.name = 'market_return'

# 将股票收益率和市场指数收益率合并到一个DataFrame中
data = pd.concat([return_data, market_return], axis=1)
data = data.dropna()

# 计算超额收益率
data = data.sub(data['market_return'], axis=0)

# 将市值和账面市值比数据合并到一个DataFrame中
data = pd.concat([data, market_cap, book_to_market], axis=1)
data.columns = stock_list + ['market_return', 'market_cap', 'book_to_market']

# 计算因子收益率
factor_data = pd.DataFrame()
factor_data['market_factor'] = market_return - ts.pro_bar(ts_code='000016.SH', start_date=start_date, 
                                                          end_date=end_date, adj='qfq', 
                                                          factors=['tor']).set_index('trade_date')['pct_chg']
factor_data['size_factor'] = sm.OLS(np.array(data.mean()), sm.add_constant(np.log(data['market_cap']))).fit().resid
factor_data['value_factor'] = sm.OLS(np.array(data.mean()), sm.add_constant(np.log(data['book_to_market']))).fit().resid

# 计算法玛三因子模型的参数
X = sm.add_constant(factor_data)
model = sm.OLS(np.array(data.mean()), X)
results = model.fit()
print(results.summary())

  

以上代码中,我们使用了tushare库获取股票数据,并使用statsmodels库进行回归分析。具体来说,我们首先获取了股票收益率、市场指数收益率、股票市值和账面市值比等数据,然后计算了超额收益率,并将这些数据合并到一个DataFrame中。接着,我们计算了市场因子、规模因子和价值因子的收益率,并利用OLS回归分析计算了法玛三因子模型的参数。

需要注意的是,以上代码只是一个简单的示例,实际应用中还需要考虑很多其他因素,如数据处理、缺失值处理、数据标准化等。此外,法玛三因子模型也有其局限性,如不能很好地解释一些股票市场现象等。因此,在实际应用中需要根据具体情况进行调整和改进。

因子有效性检验

当使用法玛三因子模型时,我们需要确认市场因子、规模因子和价值因子是否有效。以下是几种在Python中进行因子有效性检验的方法:

1 因子收益率的t检验

首先,我们可以使用t检验来检验市场因子、规模因子和价值因子的收益率是否显著不为零。我们可以通过计算每个因子收益率的t统计量,并检验其显著性水平,来判断该因子是否有效。以下是一个简单的示例:

import pandas as pd
import numpy as np
import statsmodels.api as sm

# 获取股票收益率数据
start_date = '2020-01-01'
end_date = '2020-12-31'
return_data = pd.DataFrame()
for code in stock_list:
    try:
        stock_return = ts.pro_bar(ts_code=code, start_date=start_date, end_date=end_date, adj='qfq', 
                                   factors=['tor']).set_index('trade_date')['pct_chg']
        return_data[code] = stock_return
    except:
        pass

# 计算市场指数收益率
market_return = ts.pro_bar(ts_code='000001.SH', start_date=start_date, end_date=end_date, 
                           adj='qfq', factors=['tor']).set_index('trade_date')['pct_chg']
market_return.name = 'market_return'

# 将股票收益率和市场指数收益率合并到一个DataFrame中
data = pd.concat([return_data, market_return], axis=1)
data = data.dropna()

# 计算超额收益率
data = data.sub(data['market_return'], axis=0)

# 将市值和账面市值比数据合并到一个DataFrame中
data = pd.concat([data, market_cap, book_to_market], axis=1)
data.columns = stock_list + ['market_return', 'market_cap', 'book_to_market']

# 计算因子收益率
factor_data = pd.DataFrame()
factor_data['market_factor'] = market_return - ts.pro_bar(ts_code='000016.SH', start_date=start_date, 
                                                          end_date=end_date, adj='qfq', 
                                                          factors=['tor']).set_index('trade_date')['pct_chg']
factor_data['size_factor'] = sm.OLS(np.array(data.mean()), sm.add_constant(np.log(data['market_cap']))).fit().resid
factor_data['value_factor'] = sm.OLS(np.array(data.mean()), sm.add_constant(np.log(data['book_to_market']))).fit().resid

# 计算t检验的p值
ttest = sm.stats.ttest_ind(factor_data, np.zeros(factor_data.shape), axis=0)

# 打印检验结果
print(ttest)

  

以上代码中,我们首先计算了每个因子的收益率,然后使用OLS回归分析计算了每个因子的残差,即每个因子收益率中的alpha值。接着,我们计算了每个因子收益率的t统计量和p值,并输出检验结果。

2 因子回归的 $R^2$ 值

除了t检验之外,我们还可以使用因子回归的 $R^2$ 值来评估市场因子、规模因子和价值因子的有效性。$R^2$ 值表示模型中因子收益率对总收益率的解释程度,值越高则说明因子对总收益率的解释程度越大。以下是一个简单的示例:

import pandas as pd
import numpy as np
import statsmodels.api as sm

# 获取股票收益率数据
start_date = '2020-01-01'
end_date = '2020-12-31'
return_data = pd.DataFrame()
for code in stock_list:
    try:
        stock_return = ts.pro_bar(ts_code=code, start_date=start_date, end_date=end_date, adj='qfq', 
                                   factors=['tor']).set_index('trade_date')['pct_chg']
        return_data[code] = stock_return
    except:
        pass

# 计算市场指数收益率
market_return = ts.pro_bar(ts_code='000001.SH', start_date=start_date, end_date=end_date, 
                           adj='qfq', factors=['tor']).set_index('trade_date')['pct_chg']
market_return.name = 'market_return'

# 将股票收益率和市场指数收益率合并到一个DataFrame中
data = pd.concat([return_data, market_return], axis=1)
data = data.dropna()

# 计算超额收益率
data = data.sub(data['market_return'], axis=0)

# 将市值和账面市值比数据合并到一个DataFrame中
data = pd.concat([data, market_cap, book_to_market], axis=1)
data.columns = stock_list + ['market_return', 'market_cap', 'book_to_market']

# 计算因子收益率
factor_data = pd.DataFrame()
factor_data['market_factor'] = market_return - ts.pro_bar(ts_code='000016.SH', start_date=start_date, 
                                                          end_date=end_date, adj='qfq', 
                                                          factors=['tor']).set_index('trade_date')['pct_chg']
factor_data['size_factor'] = sm.OLS(np.array(data.mean()), sm.add_constant(np.log(data['market_cap']))).fit().resid
factor_data['value_factor'] = sm.OLS(np.array(data.mean()), sm.add_constant(np.log(data['book_to_market']))).fit().resid

# 计算因子回归的R2值
y = data.mean()
X = sm.add_constant(factor_data)
model = sm.OLS(y, X).fit()
rsquared = model.rsquared

# 打印检验结果
print(rsquared)

以上代码中,我们首先计算了每个因子的收益率,然后使用OLS回归分析计算了每个因子的残差,即每个因子收益率中的alpha值。接着,我们将股票超额收益率和因子收益率合并到一个DataFrame中,然后计算因子回归的 $R^2$ 值。最后,我们输出了检验结果。

3 因子相关性分析

除了单独检验每个因子的有效性之外,我们还可以使用因子相关性分析来评估每个因子对投资组合表现的贡献程度。这里我们使用热图来显示每个因子之间的相关性。以下是一个简单的示例:

import pandas as pd
import seaborn as sns
import matplotlib.pyplot as plt

# 获取股票收益率数据
start_date = '2020-01-01'
end_date = '2020-12-31'
return_data = pd.DataFrame()
for code in stock_list:
    try:
        stock_return = ts.pro_bar(ts_code=code, start_date=start_date, end_date=end_date, adj='qfq', 
                                   factors=['tor']).set_index('trade_date')['pct_chg']
        return_data[code] = stock_return
    except:
        pass

# 计算市场指数收益率
market_return = ts.pro_bar(ts_code='000001.SH', start_date=start_date, end_date=end_date, 
                           adj='qfq', factors=['tor']).set_index('trade_date')['pct_chg']
market_return.name = 'market_return'

# 将股票收益率和市场指数收益率合并到一个DataFrame中
data = pd.concat([return_data, market_return], axis=1)
data = data.dropna()

# 计算超额收益率
data = data.sub(data['market_return'], axis=0)

# 将市值和账面市值比数据合并到一个DataFrame中
data = pd.concat([data, market_cap, book_to_market], axis=1)
data.columns = stock_list + ['market_return', 'market_cap', 'book_to_market']

# 计算因子收益率
factor_data = pd.DataFrame()
factor_data['market_factor'] = market_return - ts.pro_bar(ts_code='000016.SH', start_date=start_date, 
                                                          end_date=end_date, adj='qfq', 
                                                          factors=['tor']).set_index('trade_date')['pct_chg']
factor_data['size_factor'] = sm.OLS(np.array(data.mean()), sm.add_constant(np.log(data['market_cap']))).fit().resid
factor_data['value_factor'] = sm.OLS(np.array(data.mean()), sm.add_constant(np.log(data['book_to_market']))).fit().resid

# 计算因子相关性
corr_matrix = factor_data.corr()

# 绘制热图
sns.heatmap(corr_matrix, annot=True, cmap='RdYlBu')
plt.show()

  

以上代码中,我们首先计算了每个因子的收益率和超额收益率,然后将这些数据合并到一个DataFrame中。接着,我们使用OLS回归分析计算了每个因子的残差,即每个因子收益率中的alpha值。然后,我们计算了每个因子之间的相关性,并使用热图可视化了结果。

法玛三因子模型的优缺点

法玛三因子模型的优点:

  1. 解释力强:相较于CAPM模型,法玛三因子模型的解释力更强,能够更好地解释股票收益率的变化。

  2. 考虑了多个因素:相较于单因子模型,法玛三因子模型考虑了市场因子、规模因子和价值因子,更全面地考虑了股票收益率的影响因素。

  3. 可解释性强:法玛三因子模型中的三个因子,即市场因子、规模因子和价值因子,都是经济学上有实际意义的因素,因此其结果更容易被解释。

法玛三因子模型的缺点:

  1. 忽略了其他因素:法玛三因子模型只考虑了市场因子、规模因子和价值因子,忽略了其他可能对股票收益率有影响的因素,如流动性、动量等。

  2. 样本限制:法玛三因子模型的样本通常是历史股票数据,而历史表现并不能保证未来表现,因此其预测能力有限。

  3. 可能存在共线性问题:法玛三因子模型中的因子可能存在共线性问题,导致其解释能力下降。

  4. 不适用于所有市场:法玛三因子模型的适用范围有限,可能无法适用于所有市场。例如,一些新兴市场可能存在不同的因子影响股票收益率,无法使用法玛三因子模型来解释其表现。

综上所述,法玛三因子模型虽然具有一定的局限性,但在投资组合管理和股票选择方面仍然具有一定的实用性和可靠性。

如何改进提升

虽然法玛三因子模型具有较好的解释股票收益率的能力,但是其仍然存在一些缺点和局限性。下面是一些改进和提升三因子模型的方法:

1 添加其他因子:法玛三因子模型只考虑了市场因子、规模因子和价值因子,可以添加其他因子,如动量、流动性等,来提升模型的解释能力。可以使用pyfolio库中的get_factor_returns函数获取更多的因子数据,例如动量因子和波动率因子:

import pyfolio as pf

start_date = '2015-01-01'
end_date = '2021-12-31'
tickers = ['AAPL', 'MSFT', 'AMZN', 'GOOG', 'FB']
factor_names = ['market_beta', 'size_factor', 'value_factor', 'momentum_factor', 'volatility_factor']

factor_data = pf.utils.get_factor_returns(factor_names, start_date=start_date, end_date=end_date)

2 考虑时间变化:股票市场中因子的影响可能会随着时间变化而变化,可以建立时间变化的因子模型,或者采用滚动回归来考虑时间变化对因子的影响。 可以使用rolling函数进行滚动回归,并将时间窗口设置为1年或更长时间:

import pandas as pd
import statsmodels.api as sm

rolling_window = 252
factor_data_rolling = pd.DataFrame(index=factor_data.index)
for factor_name in factor_names:
    factor_data_rolling[factor_name] = factor_data[factor_name].rolling(window=rolling_window).apply(lambda x: sm.OLS(x, sm.add_constant(factor_data[['market_beta', 'size_factor', 'value_factor']]).loc[x.index]).fit().params)

factor_data_rolling = factor_data_rolling.dropna()

3 考虑非线性关系:股票收益率和因子之间可能存在非线性关系,可以使用非线性回归模型来建立因子模型,或者使用机器学习方法来建立预测模型。 可以使用scikit-learn库中的多项式回归模型来建立非线性关系的因子模型:

from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures

poly_degree = 2
poly_features = PolynomialFeatures(poly_degree, include_bias=False)
X_poly = poly_features.fit_transform(factor_data[['market_beta', 'size_factor', 'value_factor']])
model = LinearRegression().fit(X_poly, factor_data['returns'])

  或者使用scikit-learn库中的机器学习模型来建立因子模型,例如随机森林模型:

from sklearn.ensemble import RandomForestRegressor

model = RandomForestRegressor(n_estimators=100, random_state=0)
model.fit(factor_data[['market_beta', 'size_factor', 'value_factor']], factor_data['returns'])

4 解决共线性问题:法玛三因子模型中的因子可能存在共线性问题,可以使用主成分分析等方法来减少因子之间的共线性,提高模型的解释能力。 可以使用scikit-learn库中的主成分分析模型来减少因子之间的共线性:

from sklearn.decomposition import PCA

n_components = 3
pca = PCA(n_components=n_components)
X_pca = pca.fit_transform(factor_data[['market_beta', 'size_factor', 'value_factor']])

5 使用更多数据:使用更多的数据来建立因子模型,可以提高模型的预测能力和稳健性。 可以使用Quandl等数据源获取更多的历史数据来建立因子模型:

import quandl

quandl.ApiConfig.api_key = 'your_api_key'
data = quandl.get_table('SHARADAR/SF1', ticker=tickers, dimension='MRY', qopts={'columns': ['ticker', 'date', 'marketcap', 'roe', 'pb']})
data = data.pivot(index='date', columns='ticker')
data.columns = [f"{col[0]}_{col[1]}" for col in data.columns]
data = data.dropna()

6 考虑国别和行业因素:股票收益率受到不同国别和行业因素的影响,可以建立考虑国别和行业因素的多因子模型,来提高模型的解释能力。 可以使用pyfolio库中的get_industry_returns函数获取行业因子数据,并使用alpha_vantage等数据源获取国别因子数据:

import alpha_vantage
from alpha_vantage.timeseries import TimeSeries
import pyfolio as pf

# 使用alpha_vantage获取国别因子数据
ts = TimeSeries(key='YOUR_API_KEY', output_format='pandas')
data, meta_data = ts.get_daily(symbol='SPY', outputsize='full')
data.columns = ['open', 'high', 'low', 'close', 'volume']
data = data[['close']]
data = data.pct_change().dropna()
data.columns = ['market_factor']

# 使用pyfolio获取行业因子数据
industry_data = pf.utils.get_industry_returns('morningstar', 'usa')
industry_data.columns = ['industry_factor']

# 合并国别和行业因子数据
factor_data = pd.concat([data, industry_data], axis=1).dropna()
factor_data = factor_data.resample('M').last()

# 运用法玛三因子模型进行分析
...

7 考虑投资组合构建方法:可以使用优化模型来构建投资组合,例如使用CVXPY库中的优化模型:

pythonCopy codeimport cvxpy as cp

weights = cp.Variable(3)
constraints = [cp.sum(weights) == 1, weights >= 0]
expected_return = factor_data_rolling['returns'].mean()
cov_matrix = factor_data_rolling[['market_beta', 'size_factor', 'value_factor']].cov()
risk = cp.quad_form(weights, cov_matrix)
objective = cp.Minimize(risk - 0.5 * gamma * expected_return * cp.quad_form(weights, cov_matrix))
problem = cp.Problem(objective, constraints)
problem.solve()

 

标签:return,法玛,手把手,因子,factor,date,data,market
From: https://www.cnblogs.com/sljsz/p/17730966.html

相关文章

  • VINS中的IMU因子(一)
    VINS中的IMU因子(一)在这篇文章中我们分析一些VINS中对于IMU因子的处理和构建方式。首先来看一下再estimator类中关于预积分因子的几个重要成员变量。pre_integrations存储了滑动窗口中相邻两帧之间的预积分增量。acc_0,gyr_0则保存了当前时刻的角速度和加速度值。IntegrationBas......
  • SCI期刊影响因子(Journal Impact Factor,简称JIF)
    SCI期刊影响因子(JournalImpactFactor,简称JIF)是指某一期刊在特定年份内被引用的次数(包括引用期刊内的文章和其他期刊对该期刊的引用),除以该期刊在同一年发表的总论文数目。该值反映了该期刊上一年发表的论文平均被引用的频率。   全球公认的期刊学术影响力评价指标......
  • 手把手教你如何下载学浪(抖音课堂)上已购买的视频课程
    前言:很多同学都想知道抖音课堂(学浪)中视频课程怎么下载,但是学浪上面已购买的视频课程是不提供直接下载方式的,所以下面就教大家如何用学无止下载器下载学浪和抖音课堂上面已购买的视频课程。一、在下载器首页输入“X”,回车进入学浪下载。二、提示是否登录学浪账号,输入“Y”回车,弹......
  • 【原创】手把手教你如何测试宽带网速
     大家好,我是你们的好朋友:人见人爱、花见花开、车见爆胎、猪见拜拜的龙少一郎,例行介绍如上,严归正传如下:    我们经常上网,无论是公司网速快慢,还是家庭小区宽带共享,困扰我们的一直是网速,可是我们又怎么知道网速快慢呢?是如何计算出网速的实际大小,从而确定实实在在的网速呢?且......
  • 手把手教你模拟 JVM 内存溢出场景
    Java全能学习+面试指南:https://javaxiaobear.cn今天我们主要自己模拟一个JVM内存溢出的场景。在模拟JVM内存溢出之前我们先来看下这样的几个问题。老年代溢出为什么那么可怕?元空间也有溢出?怎么优化?如何配置栈大小?避免栈溢出?进程突然死掉,没有留下任何信息时如何进......
  • Linux系列教程(二)——Linux系统安装(手把手学安装centos6.8)
    目录1、安装VMware2、在VMware上安装CentOS第1步:打开VMware,点击创建新的虚拟机第2步:选择典型,点击下一步。出现如下界面,然后选择第三个选项:稍后安装操作系统,点击下一步第3步:客户机安装操作系统选择Linux,版本根据自己下载的Linux镜像文件来选择......
  • 用Rust手把手编写一个Proxy(代理), 准备篇, 动手造轮子
    用Rust手把手编写一个Proxy(代理),准备篇,动手造轮子wmproxy将实现http/https代理,socks5代理,后续将实现websocket代理,内外网穿透等,会将实现过程分享出来,希望感兴趣的可以一起参与参与项目++wmproxy++gite:https://gitee.com/tickbh/wmproxygithub:https://git......
  • 【DSP视频教程】DSP视频教程第12期:TI开源分享IQmath DSP源码,适用于所有Cortex-M内核,本
     今年TI推出MSPM0系列产品配套的SDK软件包里面将此库开源了,之前的时候也移植过IQmatb,不过只有库版本,这次竟然开源了,确实是不可多得的好资源。这个是定点库,非常适合用于M0,  M0+,  M3和不带硬件FPU的M4内核上,当然,用在M4F,M7,M33等器件上也是没问题的。本次视频配套的例子将ARMDS......
  • 程序设计之——手把手教你如何从Excel文件中读取学生信息
    在当今信息化时代,计算机技术已经深入到各个领域,而程序设计则成为推动信息化建设的关键技术之一。在众多领域中,学生信息管理系统无疑是其中一个重要的应用。本文将从学生信息管理系统的开发入手,探讨开如何高效且保证质量的完成开发。假设有一个学生信息管理系统,需要从Excel文件中......
  • 程序设计之——手把手教你如何从Excel文件中读取学生信息
    在当今信息化时代,计算机技术已经深入到各个领域,而程序设计则成为推动信息化建设的关键技术之一。在众多领域中,学生信息管理系统无疑是其中一个重要的应用。本文将从学生信息管理系统的开发入手,探讨开如何高效且保证质量的完成开发。假设有一个学生信息管理系统,需要从Excel文件中读......