Fama-French三因子模型

Fama-French三因子模型

模型

tushare ID=399224

在多因子模型出现以前,CAPM模型被奉为典型,几乎所有定价均是按照CAPM模型计算的。后来学者们发现了各种异象,这些异象无法用CAPM模型解释。较为典型的有Basu发现的盈利市值比效应和Banz发现的小市值效应。遗憾的是,虽然单一异象被发现后都对CAPM提出了挑战,但并没有形成合力,直到Fama三因子模型出现。本文通过对沪深300指数成分的子集的三因子模型进行选股,后对筛选出的股票使用支持向量机进行短期预测。再三因子模型中以单个股票的无风险收益率作为因变量,沪深300指数日无风险收益率、SMB、HML为自变量的三因子模型。

下面为Fama-French三因子模型

E [ R i ] − R f = β i , M K T ( E [ R M ] − R f ) + β i , S M B E [ R S M B ] + β i , H M L E [ R H M L ] E[R_i]-R_f=\beta_{i,MKT}(E[R_M]-R_f)+\beta_{i,SMB}E[R_{SMB}]+\beta_{i,HML}E[R_{HML}] E[Ri]Rf=βi,MKT(E[RM]Rf)+βi,SMBE[RSMB]+βi,HMLE[RHML]

E [ R i ] 代 表 股 票 i 的 预 期 收 益 率 ; R f 代 表 无 风 险 收 益 率 ; E [ R M ] 为 市 场 组 合 预 期 收 益 率 ; E [ R S M B ] 为 规 模 因 子 收 益 率 ; E [ R H M L ] 为 价 值 因 子 预 期 收 益 率 ; E[R_i]代表股票i的预期收益率; R_f代表无风险收益率; E[R_M]为市场组合预期收益率; E[R_{SMB}]为规模因子收益率; E[R_{HML}]为价值因子预期收益率; E[Ri]i;Rf;E[RM];E[RSMB];E[RHML];

为构建价值因子和规模因子,Fama选择BM和市值两个指标进行双重排序,将股票分为大市值B和小市值S;按照账面市值将股票分为BM高于70%分位数的H组,BM低于30%分位数的L组,BM处于二者之间的记为M组。如下表

BM分组
HML
市值分组SS/HS/MS/L
BB/HB/MB/L

得到上述分组后,就可以构建规模和价值两个因子。
S M B = 1 3 ( S / H + S / M + S / L ) − 1 3 ( B / H + B / M + B / L ) SMB=\frac{1}{3}(S/H+S/M+S/L)-\frac{1}{3}(B/H+B/M+B/L) SMB=31(S/H+S/M+S/L)31(B/H+B/M+B/L)

H M L = 1 2 ( S / H + B / H ) − 1 2 ( S / L + B / L ) HML=\frac{1}{2}(S/H+B/H)-\frac{1}{2}(S/L+B/L) HML=21(S/H+B/H)21(S/L+B/L)

选股

在用三因子模型估算股票预期收益率时,经常会发现并非每只股票都能严格吻合式1,大部分股票都会存在一个Alpha_i截距项。当存在Alpha_i截距项时,说明股票当前价格偏离均衡价格。基于此,可以设计套利策略。

Alpha_i < 0时,说明股票收益率低于均衡水平,股票价格被低估,应该买入。

Alpha_i > 0时,说明股票收益率高于均衡水平,股票价格被高估,应该卖出。

因此,可以在股票池中获取Alpha_i 小于0的股票买入开仓。

加入Alpha_i后得到公式
E [ R i ] − R f = α i + β i , M K T ( E [ R M ] − R f ) + β i , S M B E [ R S M B ] + β i , H M L E [ R H M L ] E[R_i]-R_f=\alpha_{i}+\beta_{i,MKT}(E[R_M]-R_f)+\beta_{i,SMB}E[R_{SMB}]+\beta_{i,HML}E[R_{HML}] E[Ri]Rf=αi+βi,MKT(E[RM]Rf)+βi,SMBE[RSMB]+βi,HMLE[RHML]

例子

下面使用python进行建模

数据来自tushare平台

如果没有账号点击此处创建:https://tushare.pro/register?reg=399224

# coding=utf-8
import math
import tushare as ts
import pandas as pd
import matplotlib
import matplotlib.pyplot as plt
import numpy as np
#import talib
import pandas as pd
from datetime import datetime, date
from sklearn import datasets
from sklearn.model_selection import train_test_split
import matplotlib.pyplot as plt
from sklearn.linear_model import LinearRegression

matplotlib.rcParams['axes.unicode_minus']=False
plt.rcParams['font.sans-serif']=['SimHei']
ts.set_token('your token')#如果没有tushare账户需要进入平台进行注册
pro = ts.pro_api()

data = pro.stock_basic(exchange='', list_status='L', fields='ts_code,symbol,name,area,industry,list_date')
############################读取数据类###################################
class readData:
    def read_index_daily(self,code,star,end):#指数数据
        dsb = pro.index_daily(ts_code=code, start_date=star, end_date=end,fields='ts_code,trade_date,close,change')#默认读取三个数据
        return dsb
    def read_daily(self,code,star,end):
        dsc1 = pro.daily(ts_code=code, start_date=star, end_date=end,fields='ts_code,trade_date,close')
        return dsc1
    def read_CPI(self,star,end):#时间格式start_cpi='201609'
        dc=pro.cn_cpi(start_m=star, end_m=end,fields='month,nt_yoy')
        return dc
    def read_GDP(self,star,end):#时间格式star='2016Q4'
        df1 = pro.cn_gdp(start_q=star, end_q=end,fields='quarter,gdp_yoy')
        return df1
    def read_bond(self,code,star,end):
        df=pro.cb_daily(ts_code=code,start_date=star,end_date=end)
    def read_base(self,code):
        df=pro.query('daily_basic', ts_code=code,fields='close,ts_code,pb,total_mv,trade_date')
        return df
#######################################################################################   

start_time='20200226'#发布GDP需要时间,我们延迟1个月,即第一季度的GDP4月份才发布。
end_time="20200901"
dc=readData()
dsc1=readData()
dsb1=readData()
dsc=dsc1.read_index_daily('000300.SH',start_time,end_time)
dsc.set_index(['trade_date'],inplace=True)
###################计算alpha的值###########################################################
def alpha_fun(code):
    dsb=dsb1.read_base(code) .fillna(0) 
    dsb.set_index(['trade_date'],inplace=True)
    df=pd.merge(dsc, dsb, on='trade_date').fillna(0)
    R=np.reshape(np.array([df.close_y]) , (-1,1) )
    R_f=np.reshape(np.array([(df.change/(df.close_x.shift(-1))).fillna(0)]),(-1,1))#用0 填充nan
    HMI=np.reshape(np.array([(1/df.pb).fillna(0)]),(-1,1))
    SMB=np.reshape(np.array([df.total_mv]),(-1,1))
    X=np.concatenate((R_f-4/252,HMI,SMB),axis=1) 
    y1=np.reshape(R,(1,-1)).T
    X_train, X_test, y_train, y_test = train_test_split(X, y1, test_size=0.3, random_state=0)
    linear = LinearRegression()#进行回归建模
    linear.fit(X_train, y_train)
    alpha=linear.intercept_-4/252
    return alpha,linear.intercept_ ,linear.coef_,linear.score(X_test, y_test),df
############################计算篮子里的每只股票净值###############################################
def jinzhi_fun(code,start_time,end_time):#计算净值
    df=pro.daily(ts_code=str(code), start_date=start_time, end_date=end_time) 
    df.index=pd.to_datetime(df.trade_date,format="%Y-%m-%d")
    jinzhi=(df.close/df.close[-1])
    return jinzhi
######################选股条件####################################################
co=pro.query('daily_basic', ts_code="",trade_date="20200226",fields='ts_code')
print(co.shape)
code_list=[]
N=40#股票池
k=0
JZ=0#组合净值
cum=0

for i in co.ts_code.values[0:N]:
    
    try:
        if alpha_fun(i)[0]<0:
            k+=1
            JZ=jinzhi_fun(str(i) ,start_time,end_time)+JZ
            JZ=JZ.fillna( method='bfill')#用前后数据特征填充
            print(str(i)[0:6])
            code_list.append([str(i),alpha_fun(i)[0][0]])
            
    except ValueError:
        pass
    continue 
#########################计算权重收益净值#########################################      
JZ=JZ.sort_index(axis=0,ascending=True) 
JZ_avg=JZ/k#平均净值
cum=np.cumprod(JZ_avg)# 累计收益 
####################计算收益率函数,如沪深300#####################################
def JZ_function(code,star,end):
    df12 = pro.index_daily( ts_code=code, start_date=star, end_date=end)
    df12=df12.sort_index( )
    df12.index=pd.to_datetime(df12.trade_date,format='%Y-%m-%d')#设置日期索引
    ret12=df12.close/df12.close[-1]
    return ret12.dropna()
#############################策略的年化统计######################################
def Tongji(jz):
    NH=(jz.dropna()[-1]-1)*100*252/len(jz.index)
    BD=np.std(jz)*100*np.sqrt(252)
    SR=(NH-400/252)/BD
    return_list=jz.dropna()
    MHC=((np.maximum.accumulate(return_list) - return_list) / np.maximum.accumulate(return_list)).max()*100
    print("年化收益率:{:.2f}%:,年化夏普率:{:.2f},波动率为:{:.2f}%,最大回撤:{:.2f}%".format( NH,SR,BD,MHC))
############################################################################
if __name__=="__main__":
    cum12=JZ_function('000300.SH',start_time,end_time)
    Tongji(JZ_avg)
    plt.plot(cum12,label="沪深300",color='b')
    plt.plot(JZ_avg,label="股票组合",color='r')
    plt.title("alpha股+指期对冲策略")
    plt.legend()
    plt.show()

结果

在这里插入图片描述
年化收益率:25.57%:
年化夏普率:0.21;
波动率为:114.43%;
最大回撤:14.14%;

  • 4
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值