前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Fama-Macbeth 回归和Newey-West调整

Fama-Macbeth 回归和Newey-West调整

作者头像
量化小白
发布2019-12-30 10:12:11
11.3K23
发布2019-12-30 10:12:11
举报

1. 综述

Fama Macbeth是一种通过回归方法做因子检验,并且可以剔除残差截面上自相关性的回归方法,同时为了剔除因子时序上的自相关性,可以通过Newey West调整对回归的协方差进行调整。

2. 原理

2.1 系数估计

Fama Macbeth回归分为两步,第一步是横截面回归 ,在截面上用股票收益率对各因子暴露做回归,得到各因子的收益率;第二部是对系数的时间序列取平均得到作为参数的估计值,并进行t检验,t检验用到的标准误经过Newey West调整,总结如下

2.2 标准误估计

  • 简单估计

其中,分子上为回归系列的标准差,可以直接计算,也可以进行Newey West调整消除异方差和序列自相关。

  • Newey West 调整

Newey West的原理主要参考了石川大佬的文章[2][3],简单说明,考虑一个线性模型

当残差不存在异方差和自相关性时,残差协方差阵为单位阵的倍数,回归系数的协方差估计是一致估计量,当残差存在异方差或自相关性时,协方差阵估计有问题,可以通过Newey West调整解决,具体来说是估计上式中的

Newey West调整即对Q进行估计,最终给出的估计量具有一致性,表达式如下,用S表示

上式中,括号中第一项为仅有异方差时的调整,后面一项为针对自相关的调整,其中,e为样本残差,L为计算自相关性影响的最大滞后阶数,w_l是滞后期l的系数,从公式来看,随着滞后期数的增加,影响减小。将S带入系数协方差阵的估计可以得到协方差的Newey West估计量

其中,L常用的取法有很多种,python的famamacbeth函数的取法包括

以上是对于OLS的Newey West调整,对于Fama Macbeth回归,是对已经回归出来的一堆beta系数序列的方差进行调整,跟回归有一定差别,可以做一个转换:用回归出来的所有beta做因变量,1做自变量,做一个回归,这样回归出来的系数是所有beta的均值,残差也捕捉了beta中的异方差性和自相关性,对这个回归方程做newey west即可,这个在石川大佬的文章中有更细致的说明。

3. Python实现

Python的linearmodels中自带FamaMacBeth函数,本文一方面调用这一函数,另一方面自己写,用两种方法实现Fama Macbeth回归,确保结果的准确性。

数据使用2010-2018年全A股的市值、动量、PB、roe因子进行测试。

3.1 数据载入

from linearmodels import FamaMacBeth
import numpy as np
import pandas as pd

import datetime

import statsmodels.api as sm
import statsmodels.formula.api as sml

def getICSeries(factors,ret,method):
    

    icall = pd.DataFrame()
    fall = pd.merge(factors,ret,left_on = ['tradedate','stockcode'],right_on = ['tradedate','stockcode'])
    icall = fall.groupby('tradedate').apply(lambda x:x.corr(method = method)['ret']).reset_index()
    icall = icall.drop(['ret'],axis = 1).set_index('tradedate')

    return icall


def ifst(x):
    if pd.isnull(x.entry_dt):
        return 0
    elif (x.tradedate < x.entry_dt) |(x.tradedate > x.remove_dt):
        return 0
    else:
        return 1


def ols_coef(x,y):
    x = x.astype('float64')
    y = y.astype('float64')

    return sm.OLS(y,sm.add_constant(x),missing = 'drop').fit().params



def ols_coef1(x,formula):
    return sml.ols(formula, data=x).fit(missing = 'drop').params
price = pd.read_csv('price.csv',index_col = 0)
pb = pd.read_csv('pb.csv',index_col = 0)
roe = pd.read_csv('roe.csv',index_col = 0)
mkt = pd.read_csv('mkt.csv',index_col = 0)
ST = pd.read_excel('ST.xlsx')

'''
收益率计算
'''

price['tradedate'] = price.tradedate.apply(getdate)
ret_m = getRet(price,freq ='m',if_shift = True)
mom1 = getRet(price,freq ='m',if_shift = False)
mom1 = mom1.rename(columns = {'ret':'mom1'})

fall = pd.merge(pb,roe,left_on = ['tradedate','stockcode'],right_on = ['tradedate','stockcode'])
fall = pd.merge(fall,mkt,left_on = ['tradedate','stockcode'],right_on = ['tradedate','stockcode'])
fall['tradedate'] = fall.tradedate.apply(getdate)
fall = pd.merge(fall,mom1,left_on = ['tradedate','stockcode'],right_on = ['tradedate','stockcode'])
del fall['rptdate']




fall = pd.merge(fall,ST,left_on = 'stockcode',right_on = 'stockcode',how = 'left')
fall['if_st'] = fall.apply(ifst,axis = 1)
fall = fall.loc[fall.if_st == 0].reset_index(drop = True)
fall = fall.drop(['if_st','entry_dt','remove_dt'],axis = 1)


alldata = pd.merge(fall,ret_m,left_on = ['tradedate','stockcode'],right_on = ['tradedate','stockcode'])
alldata['mktcap'] = np.log(alldata.mktcap)

3.2 计算因子IC

alldata中包含所有的因子和收益率数据,并且已经剔除了ST,用alldata做测试。首先用alldata计算因子的IC,ICIR结果如下

ics = getICSeries(fall,ret_m,'spearman')
icir = ics.mean()/ics.std()*np.sqrt(12)
ics.cumsum().plot()

3.3 Fama macbeth回归

接下来用这四个因子做FamaMacbeth回归,首先用python自带的函数FamaMacbeth

这个函数用法和statsmodels中的OLS基本一致,输入因变量(dependent),自变量(exog)和样本权重(weights),需要注意的是因变量、自变量都是面板数据,或者用MultiIndex的dataframe,日期在前,个体编码在后。生成FamaMacbeth对象后用fit方法进行系数估计,fit的输入参数较多

  • cov_type表示是否对方差进行调整,'unadjusted'表示不调整,默认为不调整。'kernel'表示调整,即用Newey West方法进行调整
  • debiased:是否对协方差进行自由度调整,即分母用n还是n-1
  • bandwitdh:窗宽,即上文NW调整中的L,如果不设置会通过算法自动生成最优的,也可以根据上面L的公式手动输入。

关于这两个函数的细致说明可以参考[1],这里首先给出不进行调整的回归结果

fmdata = alldata.set_index(['stockcode','tradedate'])
fm = FamaMacBeth(dependent = fmdata['ret'],
                 exog = sm.add_constant(fmdata[['pb','mktcap','mom1','roe_ttm']]))
res_fm = fm.fit(debiased=False)
res_fm
手动回归并与上述结果相对比
  • 回归系数
  • 回归标准误

接下来看Newey West调整后的结果,这里根据上面的公式计算最优的L

T = res.shape[0]
L = int(np.ceil(4 * (T / 100) ** (2 / 9)))

取bandwidth = 5,NW调整后的回归结果如下

res_fm = fm.fit(cov_type= 'kernel',debiased = False,bandwidth = 5)
res_fm

手动回归,用beta序列对1进行回归,对结果做NW调整,这里回归用statsmodels中的OLS函数构造辅助函数ols_nw_se完成,最大滞后阶数也设置为5,返回标准误

最后对回归结果做简单分析,从FM结果来看,市值和动量通过了显著性检验,方向与IC的方向一致,表明因子对股票收益率有一定的解释力,pb、roe未能通过检验,表明这两个因子中的信息有跟其他两个重叠了,没有信息增益。但是要说明本文建模整个过程都比较粗糙,只是为实现FM回归,结论不具有一般性。

获取数据源码,后台回复"famamacbeth"

参考文献

[1]https://bashtage.github.io/linearmodels/panel/models.html#linearmodels.panel.model.FamaMacBeth

[2] https://zhuanlan.zhihu.com/p/40984029

[3] https://zhuanlan.zhihu.com/p/54913149

[4] Fama E F, MacBeth J D. Risk, return, and equilibrium: Empirical tests[J]. Journal of political economy, 1973, 81(3): 607-636.

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2019-12-16,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 量化小白躺平记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 1. 综述
  • 2. 原理
    • 2.1 系数估计
      • 2.2 标准误估计
      • 3. Python实现
        • 3.1 数据载入
          • 3.2 计算因子IC
          • 参考文献
          领券
          问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档