myfama-five factors,五因子模型因子计算验证与研究
综述
五因子模型中因子的计算,t1为分类所需数据的初始时间,使用 t1, t1+1, t1+2年的季度数据来进行分类和收益率计算(流通市值加权)。本人采用并没有采用预测的方式进行因子检测,首先因为五因子模型的预测能力会影响到对因子计算的检验,所以本文采用的是将计算出来的因子和csmar中的标准五因子进行相关性分析,结果显示市值因子(smb)、账面市值比因子(hml)和标准库的拟合程度高于0.9,计算效果良好、盈利能力因子(rmw)的拟合度达到0.75左右,说明采用的营业能力指标过于单一,因子构造水平有待提高,投资模式因子和标准因子差异较大,说明对股票的投资模式的界定和csmar有较大的出入,本代码采用的是用该投资年的年末市值相较于年前市值的增长比例,该比例大的说明投资风格比较激进,小的说明投资比较保守。
第一部分 数据的读取
本代码采用的数据集为: A类资产负债表 , 沪深A股的公司历史(2010-06 — 2022-12)数据
import pandas as pd
import numpy as np
import datetime
import dateutil
import matplotlib.pyplot as plt
import matplotlib.ticker as ticker
import pprint
#get data,change csv to dataframe
#Stkcd[证券代码] Accper[统计截止日期] Typrep[报表类型] using'A'
combas = pd.read_csv("FS_Combas.csv")
# A001000000[资产总计] A002000000[负债合计] A003000000[所有者权益合计]
comins = pd.read_csv("FS_Comins.csv")
# B001300000[营业利润] - 与经营业务有关的利润。
cnmont = pd.read_csv("TRD_Cnmont.csv")
#Markettype[市场类型] - 5 = 沪深A股市场(不包含科创板、创业板), 10 = 沪深B股市场, 15 = 沪深AB股市场, 21 = 沪深A股和创业板, 31 = 沪深AB股和创业板,
# 37 = 沪深A股和科创板, 47 = 沪深AB股和科创板, 53 = 沪深A股和创业板和科创板, 63 = 沪深AB股和创业板和科创板,33 = 上证A股和科创板,20 = 深证A股和创业板,
# 69 = 沪深京A股市场,79 = 沪深京AB股市场,85 = 沪深京A股和创业板,95 = 沪深京AB股和创业板, 101 = 沪深京A股和科创板, 111 = 沪深京AB股和科创板,
# 117 = 沪深京A股和创业板和科创板,127 = 沪深京AB股和创业板和科创板。
#Trdmnt[交易月份] - 以YYYY-MM表示
#Cmretwdos[考虑现金红利再投资的综合月市场回报率(流通市值加权平均法)] - 字段说明见说明书“3.4 市场回报率的计算方法”。
mnth = pd.read_csv("TRD_Mnth.csv")
#Trdmnt[交易月份] - 以YYYY-MM表示
#Msmvosd[月个股流通市值] - 个股的流通股数与月收盘价的乘积。计算公式为:个股的流通股数与月收盘价的乘积。 A股以人民币元计,上海B以美元计,深圳B以港币计,注意单位是千
#Mretwd[考虑现金红利再投资的月个股回报率] - 字段说明见“3.3 周、月、年个股回报率的计算方法”。
# Markettype[市场类型] - 1 = 上证A股市场(不包含科创板),2=上证B股市场,4=深证A股市场(不包含创业板),8=深证B股市场,16=创业板, 32=科创板,64=北证A股市场。
nrrate = pd.read_csv("TRD_Nrrate.csv")
#Nrr1 [无风险利率基准] - NRI01=定期-整存整取-一年利率
#Clsdt[统计日期] - 统计截止日期,YYYY-MM-DD
#Nrrmtdt [月度化无风险利率( % )] - 根据复利计算方法,将年度的无风险利率转化为月度数据。计算公式为:(POWER(1+Nrrdata/100, 1/12)-1)*100
#filter the data according to stock type ,we just want A stocks
groups = combas.groupby(combas.Typrep)
combas = groups.get_group('A')
groups = comins.groupby(comins.Typrep)
comins = groups.get_group('A')
groups = cnmont.groupby(cnmont.Markettype)
cnmont = groups.get_group(21)
#set the datatime as the index , but i don't change it to the datatime format
combas = combas.set_index('Accper')
comins = comins.set_index('Accper')
mnth = mnth.set_index('Trdmnt')
第二部分 时间的确定
所有的时间可以通过更改 t1, t2 来进行更改,只需更改这两个时间就可。
t1为因子分类所需数据的初始时间,t2为数据读取的截止时间,计算因子采用的数据是 t1 - t1+2 年间的季度数据。
# set the time to create the model
#the time to sort the stocks
t1 = '2011-06'
t2 = '2019-06'
pried = 10
t11 = pd.date_range(t1, t2, freq='6M')
t11 = t11.astype(str)
t12 = []
for row in t11:
t12.append(row[0:7])
t = pd.to_datetime(t1)
moduletime = str(t.year+2)+'-12'
beforeAyear = str(t.year+1)+'-12'
beforeAyearDay = str(t.year+1)+'-12-31'
beforeTyearDay = str(t.year)+'-12-31'
# the time to calculate the revenue rate
mrdate = pd.date_range(t1, moduletime, freq='M')
mrdatebk = list(mrdate.astype(str))
mrdate = list(mrdate.astype(str))
i = 0
for row in mrdate:
mrdate[i] = row[0:7]
i += 1
第三部分 对原始数据的处理
从原始数据中截取 t1 - t2 年间的季度数据,根据分类的要求进行数据的提取(从最初始的dataframe中进行提取数据),此处的功能主要是数据的整合规范和null值的处理,以及所需要的特殊指标的计算,比如账面市值比。
#change the datatime format for using easily, and drop nan values
asset = pd.DataFrame()
for index,row in combas.iterrows():
if index in t11:
asset.loc[row['Stkcd'],index] = row['A001000000']
asset = asset.dropna(axis=0,how='any')
liability = pd.DataFrame()
for index, row in combas.iterrows():
if index in t11:
liability.loc[row['Stkcd'], index] = row['A002000000']
liability = liability.dropna(axis=0, how='any')
equity = pd.DataFrame()
for index, row in combas.iterrows():
if index in t11:
equity.loc[row['Stkcd'], index] = row['A003000000']
equity = equity.dropna(axis=0, how='any')
msmvois = pd.DataFrame()
for index,row in mnth.iterrows()