您好, 欢迎来到 !    登录 | 注册 | | 设为首页 | 收藏本站

Python中的Fama Macbeth回归(pandas或Statsmodels)

Python中的Fama Macbeth回归(pandas或Statsmodels)

更新以反映截至2018年秋季的Fama-MacBeth的库状况。此fama_macbeth功能删除pandas了一段时间。那么您有什么选择呢?

如果您使用的是python 3,则可以在LinearModels中使用Fama-MacBeth方法https : //github.com/bashtage/linearmodels/blob/master/linearmodels/panel/model.py

如果您使用的是python 2或只是不想使用LinearModels,那么最好的选择就是自己动手。

例如,假设您在类似以下的面板中拥有Fama-French行业投资组合(您还计算了一些变量,例如过往的beta或过往的收益用作x变量):

In [1]: import pandas as pd
        import numpy as np
        import statsmodels.formula.api as smf

In [4]: df = pd.read_csv('industry.csv',parse_dates=['caldt'])
        df.query("caldt == '1995-07-01'")

In [5]: Out[5]: 
      industry      caldt    ret    beta  r12to2  r36to13
18432     Aero 1995-07-01   6.26  0.9696  0.2755   0.3466
18433    Agric 1995-07-01   3.37  1.0412  0.1260   0.0581
18434    Autos 1995-07-01   2.42  1.0274  0.0293   0.2902
18435    Banks 1995-07-01   4.82  1.4985  0.1659   0.2951

Fama- MacBeth主要涉及逐月计算相同的横截面回归模型,因此您可以使用来实现groupby。您可以创建一个函数dataframe(该函数来自groupby)和patsy公式;然后拟合模型并返回参数估计值。这是如何实现它的准系统版本(请注意,这是几年前原始提问者试图做的事情……不确定为什么它不起作用,尽管可能那时statsmodels结果对象方法params未返回pandasSeries因此需要将返回值Series显式转换为…在当前版本的pandas0.23.4中确实可以正常工作):

def ols_coef(x,formula):
    return smf.ols(formula,data=x).fit().params

In [9]: gamma = (df.groupby('caldt')
                .apply(ols_coef,'ret ~ 1 + beta + r12to2 + r36to13'))
        gamma.head()

In [10]: Out[10]: 
            Intercept      beta     r12to2   r36to13
caldt                                               
1963-07-01  -1.497012 -0.765721   4.379128 -1.918083
1963-08-01  11.144169 -6.506291   5.961584 -2.598048
1963-09-01  -2.330966 -0.741550  10.508617 -4.377293
1963-10-01   0.441941  1.127567   5.478114 -2.057173
1963-11-01   3.380485 -4.792643   3.660940 -1.210426

然后只需计算均值,均值的标准误和t检验(或所需的任何统计数据)即可。类似于以下内容

def fm_summary(p):
    s = p.describe().T
    s['std_error'] = s['std']/np.sqrt(s['count'])
    s['tstat'] = s['mean']/s['std_error']
    return s[['mean','std_error','tstat']]

In [12]: fm_summary(gamma)
Out[12]: 
               mean  std_error     tstat
Intercept  0.754904   0.177291  4.258000
beta      -0.012176   0.202629 -0.060092
r12to2     1.794548   0.356069  5.039896
r36to13    0.237873   0.186680  1.274230

使用statsmodels的回归有显著的开销(特别是考虑到你只需要估计系数)。如果您想提高效率,则可以从切换statsmodelsnumpy.linalg.lstsq。编写一个执行ols估计的新函数…类似以下内容(注意,我没有做类似检查这些矩阵的等级的操作…):

def ols_np(data,yvar,xvar):
    gamma,_,_,_ = np.linalg.lstsq(data[xvar],data[yvar],rcond=None)
    return pd.Series(gamma)

如果您仍在使用旧版本的pandas,则可以使用以下功能

这是在中使用fama_macbeth函数的示例pandas

>>> df

                y    x
date       id
2012-01-01 1   0.1  0.4
           2   0.3  0.6
           3   0.4  0.2
           4   0.0  1.2
2012-02-01 1   0.2  0.7
           2   0.4  0.5
           3   0.2  0.1
           4   0.1  0.0
2012-03-01 1   0.4  0.8
           2   0.6  0.1
           3   0.7  0.6
           4   0.4 -0.1

注意,结构。该fama_macbeth函数期望y-var和x-vars具有一个以日期为第一个变量,以股票/公司/实体id为第二个变量的多重索引:

>>> fm  = pd.fama_macbeth(y=df['y'],x=df[['x']])
>>> fm


----------------------Summary of Fama-MacBeth Analysis-------------------------

Formula: Y ~ x + intercept
# betas :   3

----------------------Summary of Estimated Coefficients------------------------
     Variable          Beta       Std Err        t-stat       CI 2.5%      CI 97.5%
          (x)       -0.0227        0.1276         -0.18       -0.2728        0.2273
  (intercept)        0.3531        0.0842          4.19        0.1881        0.5181

--------------------------------End of Summary---------------------------------

请注意,仅打印fm调用fm.summary

>>> fm.summary

----------------------Summary of Fama-MacBeth Analysis-------------------------

Formula: Y ~ x + intercept
# betas :   3

----------------------Summary of Estimated Coefficients------------------------
     Variable          Beta       Std Err        t-stat       CI 2.5%      CI 97.5%
          (x)       -0.0227        0.1276         -0.18       -0.2728        0.2273
  (intercept)        0.3531        0.0842          4.19        0.1881        0.5181

--------------------------------End of Summary---------------------------------

另外,请注意,该fama_macbeth函数自动添加一个拦截器(与statsmodels例程相反)。而且x- var必须是a,dataframe因此,如果您仅传递一列,则需要将其传递为df[['x']]

如果您不想拦截,则必须执行以下操作:

>>> fm  = pd.fama_macbeth(y=df['y'],x=df[['x']],intercept=False)
python 2022/1/1 18:26:42 有343人围观

撰写回答


你尚未登录,登录后可以

和开发者交流问题的细节

关注并接收问题和回答的更新提醒

参与内容的编辑和改进,让解决方法与时俱进

请先登录

推荐问题


联系我
置顶