Fama三因子数据的收集

import numpy as np
import pandas as pd
from datetime import datetime, date, timedelta, timezone
import jqdatasdk as jq
jq.auth("18351925110","925110")
auth success 

首先定义一个分组函数,方便对每年进行分组

核心思路:每年的5月末对股票池进行分组
分组策略:首先按照市值(size) 分为Big,前50%;Small ,后50%
然后按照账面价值比(bp),这里进行一个简化处理,选取pb(市净率)的相反数
分为LOW(前30%)Medium(中间40%) High(后30%)
股票组合:2*3 为BL BM BH SL SM SH

get_grooup(breakpoint): 返回6个因子组合,用来计算因子,为一个list

def get_group(breakpoint):   #breakpoint 每年进行分组的时间点  字符类型 如:“2019-05-31”
    breakpoint = jq.get_trade_days(end_date=breakpoint,count=1)[0] #获取breakpoint之前最近的一个交易日,含breakpoint
    universe = jq.get_index_stocks("000300.XSHG",date=breakpoint)   #获取沪深300指数的成分股
    ###############################取数据####################################################################
    my_query = jq.query(jq.valuation.code,jq.valuation.circulating_market_cap,jq.valuation.pb_ratio).filter(jq.valuation.code.in_(universe))                                                                                                            
    stocks_info = jq.get_fundamentals(my_query,date=breakpoint)  #获取股票的市值、PB数据
    ##################################算市值#################################################################
    ME50 = np.percentile(stocks_info["circulating_market_cap"],50)   #计算市值中位数
    S = stocks_info[stocks_info["circulating_market_cap"]<=ME50]["code"].tolist()   #获取小市值股票代码列表
    B = stocks_info[stocks_info["circulating_market_cap"]>ME50]["code"].tolist()    #获取大市值股票代码列表
    #########################################算账面市值比####################################################
    stocks_info["bp"] = 1/stocks_info["pb_ratio"]
    BP30 = np.percentile(stocks_info["bp"],30)  #计算前30%位数
    BP70 = np.percentile(stocks_info["bp"],70)  #计算后30%位数
    L = stocks_info[stocks_info["bp"]<BP30]["code"].tolist()
    H = stocks_info[stocks_info["bp"]>BP70]["code"].tolist()
    M = list(set(stocks_info["code"]).difference(set(L+H)))
    ################################################构建股票组合#############################################
    SL = list(set(S).intersection(set(L)))
    SM = list(set(S).intersection(set(M)))
    SH = list(set(S).intersection(set(H)))
    BL = list(set(B).intersection(set(L)))
    BM = list(set(B).intersection(set(M)))
    BH = list(set(B).intersection(set(H)))
    portfolios = [SL,SM,SH,BL,BM,BH]
    
    return portfolios

# SL = get_group("2018-05-31")[0]
# SL

补充:定义一个获取每月月末交易日的函数

get_lastDay(year) : year为数字,来代表年份,如2019;返回值为该年每个月最后一个交易日,是一个字符List

import calendar 
'''只能查到2005之后的数据(含2005年)'''
def get_lastDay(year): #year:指定年份 这是数字   如:2019
    #首先获取每个月份的最后一天
    last_day = {}
    for i in range(1,13):
        last_day[i] = calendar.monthrange(year,i)[1]
    #获取每月月末的交易日
    last_year_day = []
    for i in last_day:
        last_year_day.append(str(year)+"-"+str(i)+"-"+str(last_day[i]))
    result = []
    for i in last_year_day:
        a = jq.get_trade_days(end_date=i,count=1)[0]
        result.append(a)
    
    return result     #这是一个时间序列 list
    

补充:获取一个周期内,每月最后一个交易日的函数

def get_tradeDay(year):
    tradeDay_0 = get_lastDay(year-1)  #获取第一年每月最后一个交易日
    tradeDay_1 = get_lastDay(year) #获取第二年每月最后一个交易日
    tradeDay = tradeDay_0[4:] + tradeDay_1[:4]    #获取周期为一年的,交易日
    
    return tradeDay    

计算每个月的组合收益率

get_returnMonthly(x,year,j),x:指定组合;year:哪一年,j:哪一月 j的具体含义见some_month相关语句

#以下的构造思路:以一个月为出发点进行函数编写
def get_returnMonthly(x,year,j):   #x:指定组合(SM、SL....) year:数字年份,如2018 j=[0,1,2,3,...,11]某一数字
##########################获取每年5.31到次年5.31的交易日期########################
    tradeDay_0 = get_lastDay(year-1)  #获取第一年每月最后一个交易日
    tradeDay_1 = get_lastDay(year) #获取第二年每月最后一个交易日
    tradeDay = tradeDay_0[4:] + tradeDay_1[:5]    #获取周期为一年的,交易日
    some_month = tradeDay[j]

    
##########################计算组合某个月的收益率##################################
    return_list = []
    for i in x:
        p0 = jq.get_price(i,end_date=some_month-timedelta(30),count=1,fields=["close"])
        p1 = jq.get_price(i,end_date=some_month,count=1,fields=["close"])
        ret = p1["close"].iloc[0]/p0["close"].iloc[0] - 1
        return_list.append((i,ret))
        
    return_df = pd.DataFrame(return_list,columns=["code","ret"])
        
###############################计算组合某个月的市值####################################

    my_query = jq.query(jq.valuation.code,jq.valuation.circulating_market_cap).filter(jq.valuation.code.in_(x))

    market_value_df = pd.DataFrame()
    market_value = jq.get_fundamentals(my_query,date=some_month)
    market_value["market_value_ratio"] = market_value["circulating_market_cap"]/market_value["circulating_market_cap"].sum()
    market_value_df = pd.concat([market_value_df,market_value])
    
######################################合并两个df,并计算加权收益率##############################   

    final_result = pd.merge(market_value_df,return_df,on="code").dropna()
    final_result["wret"] = final_result["ret"] * final_result["market_value_ratio"]
    
    monthly_ret = final_result["wret"].sum()
    
        
    return monthly_ret
# get_returnMonthly(SL,2006,0)

算因子(记得手动调一下参数!!!!!)

#假设就以2018.5.31为例,来算这个周期(2017.5.31-2018.5.31)的因子---SMB  HML
#首先是获得2018年股票分组  
portfolios = get_group("2013-05-31")   #portfolios = [SL,SM,SH,BL,BM,BH]
#获取每个分组12个月的收益率

ret_dict = {}

for i in portfolios:
    ret_ls = []
    for j in range(12):
        a = get_returnMonthly(i,2013,j)   #这里还有一个年份参数
        ret_ls.append(a)
    ret_dict[str(i)] = ret_ls
    
    
result = ret_dict.values()   #6个list 每个list里有12个收益率!
ret_ll = list(result)
a = pd.DataFrame(ret_ll,index=["SL","SM","SH","BL","BM","BH"]).T
a["SMB"] = (a["SL"]+a["SM"]+a["SH"]-a["BL"]-a["BM"]-a["BH"])/3
a["HML"] = (a["SH"]+a["BH"]-a["SL"]-a["BL"])/2
a.to_excel(r"C:\Users\Administrator\Desktop\论文\因子数据\因子_2013.xlsx")

计算沪深300指数,每个月的收益率

思路:(月末指数-月初指数)/月初指数 - 1

df = pd.DataFrame()
for i in get_tradeDay(2013):
    df1 = jq.get_price("000300.XSHG",end_date=i,count=1,fields=["close"])
    df = pd.concat([df,df1])
df["close2"] = df.shift(1)["close"]
df["ret"] = (df["close"]/df["close2"])-1
df = df[["ret"]].bfill()
df.to_excel(r"C:\Users\Administrator\Desktop\论文\因子数据\沪深300_2013.xlsx")       #记得此处的参数也得改

测试区




你可能感兴趣的:(Fama三因子数据的收集)