python量化——利⽤python构建Fama-French三因⼦模型
⼯具介绍
在构建模型之前,⾸先介绍所需的⼯具。
import pandas as pd
import tushare as ts
我国汽车排放标准接轨欧美pro = ts.pro_api()
import statsmodels.api as sm
这⾥需要⽤到的是python中的pandas和statsmodels模块,分别⽤于数据处理和做多元回归。
另外,还需要获取股票和指数的各项数据,这⾥所⽤到的是tushare,tushare拥有丰富的数据内容,如股票、基⾦等⾏情数据,公司财务理等基本⾯数据。通过tushare平台赚取⼀定的积分可以免费获取平台提供的数据。(个⼈ID:419382)
Fama-French理论介绍
Fama-French是从1993年提出来的模型,该模型建⽴了三个因⼦来解释股票的回报率。这三个因⼦分别是:市场组合(Rm-Rf),市值因⼦(SMB)以及账⾯市值⽐因⼦(HML)。
具体公式如下:
E(Rit) −Rft= βi[E(Rmt−Rft)] +siE(SMBt) +hiE(HMLt)
其中SMB的计算公式为:
(SL+SM+SH)/ 3 - (BL+BM+BH)/ 3
HML的计算公式为:
(SH+BH)/ 2 - (SL+BL)/ 2
利⽤python构建模型
获取进⾏选股的指数
这⾥使⽤上证50作为选择股票的指数。
#获取进⾏选股的股票池
#获取进⾏选股的股票池
def get_SZ50_stocks(start,end):
#获取上证50成分股
df1 = pro.index_weight(index_code="000016.SH",start_date=start,end_date=end)
SZ50_codes = df1["con_code"].tolist()
#剔除最近⼀年上市和st股票
df2 = pro.stock_basic(exchange="",list_status="L")
df2 = df2[df2["list_date"].apply(int).values<20200101]
df2 = df2[-df2["name"].apply(lambda x:x.startswith("*ST"))]
all_codes = df2["ts_code"].tolist()
stocks_codes =[]
for i in SZ50_codes:
if i in all_codes:
stocks_codes.append(i)
return stocks_codes
将股票进⾏分组
从上证50中选择出来的股票需要按照市值和账⾯市值⽐(PB ratio 的倒数)进⾏分组,其中市值划分为2组,账⾯市值⽐划分为3组,所以⼀共由2*3=6组。在进⾏市值和账⾯市值⽐划分时,需要选定⼀个基准⽇期。在构建模型时,这⾥使⽤了2020-03-10作为基准⽇期。
#将股票分为六个组
def group_stocks(stocks,date):
#划分⼤⼩市值
list_mv =[]
df_stocks = pd.DataFrame()
count =0
for i in stocks:
count +=1
a = pro.daily_basic(ts_code=i,trade_date=date)
a = a["circ_mv"].values
list_mv.append(float(a))
print("第%d⽀股票市值计算完成"%count)
df_stocks["code"]= stocks_codes
df_stocks["mv"]= list_mv
df_stocks["SB"]= df_stocks["mv"].map(lambda x:"B"if x>df_stocks["mv"].median()else"S")
#划分⾼中低账⾯市值⽐
list_bm =[]
count =0
for i in stocks_codes:
count +=1
b = pro.daily_basic(ts_code=i,trade_date=date)
b =1/b["pb"].values
比亚迪汉武大帝纯电动2021款落地价list_bm.append(float(b))
print("第%d⽀股票账⾯市值⽐计算完成"%count)
df_stocks["bm"]= list_bm
df_stocks["HML"]= df_stocks["bm"].apply(lambda x:"H"if x>=df_stocks["bm"].quantile(0.7)
else("L"if x<=df_stocks["bm"].quantile(0.3)else"M"))
return df_stocks
分组之后的结果如图:
计算SMB和HML五菱汽车
这⾥先算出六组股票的收益率,由基准⽇期往后⼀天计算⼀年内的⽇收益率。之后利⽤公式算出每⽇的SMB和HML。
#分别计算六个组的⽇收益率
def groups_return(stocks,start,end):
SL = stocks[stocks["SB"].isin(["S"])&stocks["HML"].isin(["L"])].list()
sum_SL = df_stocks[df_stocks["SB"].isin(["S"])&df_stocks["HML"].isin(["L"])]["mv"].sum()电动汽车2013价格
SM = stocks[stocks["SB"].isin(["S"])&stocks["HML"].isin(["M"])].list()
sum_SM = df_stocks[df_stocks["SB"].isin(["S"])&df_stocks["HML"].isin(["M"])]["mv"].sum() SH = stocks[stocks["SB"].isin(["S"])&stocks["HML"].isin(["H"])].list()
sum_SH = df_stocks[df_stocks["SB"].isin(["S"])&df_stocks["HML"].isin(["H"])]["mv"].sum()
BL = stocks[stocks["SB"].isin(["B"])&stocks["HML"].isin(["L"])].list()
sum_BL = df_stocks[df_stocks["SB"].isin(["B"])&df_stocks["HML"].isin(["L"])]["mv"].sum()
BM = stocks[stocks["SB"].isin(["B"])&stocks["HML"].isin(["M"])].list()
sum_BM = df_stocks[df_stocks["SB"].isin(["B"])&df_stocks["HML"].isin(["M"])]["mv"].sum() BH = stocks[stocks["SB"].isin(["B"])&stocks["HML"].isin(["H"])].list()
sum_BH = df_stocks[df_stocks["SB"].isin(["B"])&df_stocks["HML"].isin(["H"])]["mv"].sum()
groups =[SL,SM,SH,BL,BM,BH]
sums =[sum_SL,sum_SM,sum_SH,sum_BL,sum_BM,sum_BH]
groups_names =["SL","SM","SH","BL","BM","BH"]
df_groups = pd.DataFrame(columns=groups_names)
count=0
起亚吉普for group in groups:
df1 = pd.DataFrame()
for i in range(len(group)):
data = pro.daily(ts_code=group[i],start_date=start,end_date=end)
data.sort_values(by="trade_date",inplace=True)
data = data["pct_chg"]*df_stocks["mv"][i]
df1[group[i]]= data
df_groups[groups_names[count]]= df1.apply(lambda x:x.sum()/sums[count],axis=1)/100
print("%s组计算完成"%groups_names[count])
count +=1
return df_groups
#计算每⽇SMB,HML
def SMB_HML(data):奔驰e260轿跑
data["SMB"]=(data["SL"]+data["SM"]+data["SH"])/3-(data["BL"]+data["BM"]+data["BH"])/3 data["HML"]=(data["SH"]+data["BH"])/2-(data["SL"]+data["BL"])/2
return data
两个因⼦的计算结果如图:
加⼊市场组合收益和股票收益
#加⼊市场因⼦和股票收益率
def selection(data,start,end,stocks_codes):
MKT = pro.index_daily(ts_code="000016.SH",start_date=start,end_date=end)
MKT.sort_values(by="trade_date",ascending=True,inplace=True)
MKT =(MKT["pct_chg"]/100-0.035).tolist()
data["MKT"]= MKT
data.lumns[0:6],axis=1,inplace=True)
for i in range(len(stocks_codes)):
a = pro.daily(ts_code=stocks_codes[i],start_date=20200311,end_date=20210311)
if len(a)==244:
a.sort_values(by="trade_date",ascending=True,inplace=True)
a =(a["pct_chg"]/100-0.035).tolist()
data["%s"%stocks_codes[i]]= a
return data
将如图表格⽤于多元回归:
对每⽀股票收益率和三个因⼦进⾏多元回归
这⾥回归之后选择返回阿尔法值最⼤的前⼗⽀股票。
#回归出阿尔法最⼤的股票组合
def OLS(df_final):
results = pd.DataFrame()
stocks_return = df_final.iloc[:,3:50]
for i in range(len(lumns)):
x = df_final.iloc[:,0:3]
y = stocks_return.iloc[:,i]
X = sm.add_constant(x)
model = sm.OLS(y,X)
result = model.fit()
results[i]= result.params
z =results.sort_values(by="Alpha",axis=1,ascending=False)
stocks_lists = z.list()
top_stocks = stocks_lists[:10]
return top_stocks
最终返回的股票组合如图:
发布评论