金融资产定价常常需要用到FamaMacBeth回归。我们用python写一个模板,可以直接将数据调成需要的格式,代入代码即可出结果。所要求的数据格式,可以从链接下载。
需要注意的是,linearmodels中的FamaMacBeth( )方法一共执行了两步:第一步,在每个时间t的横截面上,用Y对X回归,然后产生一条由各个时间上的X的回归系数组成的时间序列;第二步,对X的回归系数的时间序列进行统计检验,分别计算他们的均值、t值、P值等。
首先载入代码框架
from linearmodels import FamaMacBeth
import pandas as pd
import numpy as np
class MyFamaMacBeth():
def __init__(self,
):
pass
#根据P值返回星号
def star(self,p):
if p<0.01:
return '***'
elif p<=0.05:
return '**'
elif p<=0.1:
return '*'
else:
return ''
#基本FM回归:一次只能回归一种模型
def basic_FM(self,
data,#面板数据
Cols_X=['const','X1','X2','X3','X4','X5','X6','X7','X8'],#解释变量列标题
Col_Y='Y',#被解释变量列标题
Col_date='date',#日期的列标题
Col_individual='individual',#个体的列标题
):
self.Cols_X=Cols_X
self.Col_Y=Col_Y
# 将数据格式修改为多个行标签的面板数据
data = pd.pivot_table(data, index=[Col_date,Col_individual],
values=[Col_Y]+Cols_X)
# 回归模型
model = FamaMacBeth(dependent=data[Col_Y], exog=data[Cols_X])
# 回归结果用Newey West方法进行调整,滞后阶数设置为6阶
result = model.fit(cov_type='kernel', debiased=False, bandwidth=6)
return result
def basic_FM_summary(self,result,col_result='model',path_save=False):
params=result.params
t=result.tstats
p=result.pvalues
star=[self.star(x) for x in p]
#数据合并
values=pd.DataFrame({
'Varible':params.index,
'params':params,
't':t,
'star':star
})
#保留小数位数
values['params']=values['params'].round(3).astype(str)
values['t'] = values['t'].round(2).astype(str)
#数据合并
summary=pd.DataFrame({
col_result:values['params']+values['star']+'('+values['t']+')',
})
summary=summary.append(pd.DataFrame([round(result.rsquared,3),len(result.resids)],index=[' Adj. R',' No. of obs'],columns=[col_result]))
if path_save:
summary.to_excel(path_save)
return summary
#FM回归,含有不同的模型
def FM_multiple_models(self,
data,
models=[],
Col_date='date', # 日期的列标题
Col_individual='individual', # 个体的列标题
):
all_results={}
all_summarys=[]
for model in models:
result = MFMB.basic_FM(data, # 面板数据
Cols_X=models[model]['X'],
# 解释变量列标题
Col_Y=models[model]['Y'], # 被解释变量列标题
Col_date=Col_date, # 日期的列标题
Col_individual=Col_individual, # 个体的列标题
)
all_results[model]=result
summary = MFMB.basic_FM_summary(result, col_result=model)
all_summarys.append(summary)
return all_results,all_summarys
# 为 "FM回归,含有不同的模型" 整理出简洁结果
def FM_multiple_models_summary(self,all_summarys,path_save=False):
all_summarys=pd.concat(all_summarys,axis=1)
all_summarys.sort_index(inplace=True)
#保存路径
if path_save:
all_summarys.to_excel(path_save)
return all_summarys
第一种使用方式,针对一种模型进行Fama回归:
###使用方式1:基本FM回归,一次只能回归一种模型
######################################
# 第一步,生成测试所用面板数据集,该数据集在不同的日期有不同的个体
# 期望回归模型:Y=3.4+6.6*X1-4*X2+7*X3-3*X4-4.9*X5+7.4*X6-4*X7-7.1*X8
data = [[date, i] for date in pd.date_range('20050102', end='20060908', freq='D') for i in
range(np.random.randint(20, 87))] # 生成日期和个体
data = pd.DataFrame(data, columns=['date', 'individual'])
data['const'] = 1 # 生成常数项
data[['X1', 'X2', 'X3', 'X4', 'X5', 'X6', 'X7', 'X8']] = pd.DataFrame(np.random.normal(size=[len(data), 8])) # 解释变量
data['Y'] = 3.4 * data['const'] + 6.6 * data['X1'] - 4 * data['X2'] + 7 * data['X3'] - 3 * data['X4'] - 4.9 * data[
'X5'] + 7.4 * data['X6'] - 4 * data['X7'] - 7.1 * data['X8'] + np.random.normal(size=len(data)) / 10 # 被解释变量
#第二步,回归
MFMB=MyFamaMacBeth()
result=MFMB.basic_FM(data,#面板数据
Cols_X=['const','X1','X2','X3','X4','X5','X6','X7','X8'],#解释变量列标题
Col_Y='Y',#被解释变量列标题
Col_date='date',#日期的列标题
Col_individual='individual',#个体的列标题
)
# 第三步,整理出简洁结果
summary=MFMB.basic_FM_summary(result, col_result='model',path_save='单Fama面板回归结果.xlsx')
第二种用法,可以同时针对多种模型进行回归:
###使用方式2:FM回归,含有不同的模型
######################################
# 第一步,生成测试所用面板数据集,该数据集在不同的日期有不同的个体
data = [[date, i] for date in pd.date_range('20050102', end='20060908', freq='D') for i in
range(np.random.randint(20, 87))] # 生成日期和个体
data = pd.DataFrame(data, columns=['date', 'individual'])
data['const'] = 1 # 生成常数项
data[['X1', 'X2', 'X3', 'X4', 'X5', 'X6', 'X7', 'X8']] = pd.DataFrame(np.random.normal(size=[len(data), 8])) # 解释变量
# 期望回归模型:Y1=3.4+6.6*X1-4*X2+7*X3-3*X4-4.9*X5+7.4*X6-4*X7-7.1*X8
data['Y1'] = 3.4 * data['const'] + 6.6 * data['X1'] - 4 * data['X2'] + 7 * data['X3'] - 3 * data['X4'] - 4.9 * data[
'X5'] + 7.4 * data['X6'] - 4 * data['X7'] - 7.1 * data['X8'] + np.random.normal(size=len(data)) / 10 # 被解释变量
# 期望回归模型:Y2=-7.9-2*X1-1.9*X2+7.4*X3+3.5*X4+9.4*X5-5.2*X6-4.8*X7
data['Y2'] = -7.9 * data['const'] -2 * data['X1'] - 1.9 * data['X2'] + 7.4 * data['X3'] + 3.5 * data['X4'] +9.4 * data[
'X5'] -5.2 * data['X6'] - 4.8 * data['X7'] + np.random.normal(size=len(data)) / 10 # 被解释变量
# 期望回归模型:Y3=8.4+2.1*X1+2.9*X2-2.8*X3-9.3*X4+7.7*X5
data['Y3'] = 8.4 * data['const'] + 2.1 * data['X1'] +2.9 * data['X2'] - 2.8 * data['X3'] - 9.3 * data['X4'] +7.7 * data[
'X5'] + np.random.normal(size=len(data)) / 10 # 被解释变量
# 第二步,回归
MFMB = MyFamaMacBeth()
all_results,all_summarys = MFMB.FM_multiple_models(data, # 面板数据
#将模型结构按照顺序填进来
models={
'model1':{'Y':'Y1','X':['const','X1', 'X2','X7', 'X8']},
'model2':{'Y':'Y1','X':['const','X1', 'X2', 'X5', 'X7', 'X8']},
'model3':{'Y':'Y1','X':['const','X1', 'X2', 'X3', 'X4', 'X5', 'X6', 'X7', 'X8']},
'model4':{'Y':'Y2','X':['const','X1', 'X2', 'X3', 'X4', 'X5']},
'model5': {'Y': 'Y2',
'X': ['const', 'X1', 'X2', 'X3', 'X6', 'X7']},
'model6': {'Y': 'Y3',
'X': ['const', 'X1', 'X2', 'X3', 'X4', 'X5']},
},
Col_date='date', # 日期的列标题
Col_individual='individual', # 个体的列标题
)
# 第三步,整理出简洁结果
all_summarys=MFMB.FM_multiple_models_summary(all_summarys=all_summarys,path_save='Fama面板回归结果.xlsx')