├── README.md ├── code ├── #关于Miya_Tes.py文件说明# │ ├── Miya_Test.py │ └── README.md ├── 116_Factor_Test │ ├── Classification-分类 │ │ └── 116FactorTest_Classifier.ipynb │ ├── README.md │ └── Regression-回归 │ │ └── 116FactorTest_Regressor.ipynb ├── 150_Factor_Test │ ├── 150Factor_Test.ipynb │ └── README.md ├── 158_Factor_Test │ ├── 158Factor_Test.ipynb │ └── README.md ├── Alpha191_Facor_Test │ ├── Alpha191.ipynb │ └── README.md ├── 基于股价大幅波动的另类选股因子研究 │ ├── LR_Predict.ipynb │ └── README.md ├── 神经网络初步搭建测试 │ ├── README.md │ └── Tensorflow_Test.ipynb └── 风险因子测试 │ ├── 10Risk_Factor_Test.ipynb │ ├── 4Risk_Factor_Test.ipynb │ └── README.md ├── data ├── 116_Factor_Test │ ├── 116Mfactor1_lgb3 │ ├── 116Mfactor1_lgb4 │ ├── 116Mfactor1_xgb3 │ ├── 116Mfactor1_xgb4 │ ├── 116Wfactor1_lgb3 │ ├── 116Wfactor1_lgb4 │ ├── 116Wfactor1_xgb3 │ └── 116Wfactor1_xgb4 ├── 158_Factor_Test │ ├── 158Wfactor1_lgb3 │ └── 158Wfactor1_lgb4 ├── 191_Factor_Test │ ├── 191Alpha+10Risk │ │ ├── 191Wfactor1_Rlgb3 │ │ ├── 191Wfactor1_Rlgb4 │ │ └── 191Wfactor1_Rxgb4 │ └── 191Alpha │ │ ├── 191Wfactor1_lgb3 │ │ ├── 191Wfactor1_lgb4 │ │ ├── 191Wfactor1_xgb3 │ │ └── 191Wfactor1_xgb4 └── 数据说明.md ├── image ├── 代码说明01.png ├── 代码说明02.png ├── 代码说明03.png ├── 代码说明04.png ├── 基于股价大幅波动的另类选股因子研究01.png ├── 多因子模型01.png ├── 多因子模型02.png ├── 多因子模型03.png ├── 多因子模型04.png ├── 实习总结.png ├── 量化基础知识01.png ├── 量化基础知识02.png ├── 量化基础知识03.png ├── 量化基础知识04.png ├── 量化基础知识05.png ├── 量化基础知识06.png ├── 量化基础知识07.png └── 量化基础知识08.png ├── notebook ├── 1.量化基础知识总结.md ├── 2.多因子模型构建.md ├── 3.因子处理.md └── 4.代码说明.md └── research ├── 17_A股市场风险分析——《因子选股系列研究之十七》.pdf ├── 20150426-国泰君安-数量化专题之五十七:基于组合权重优化的风格中性多因子选股策略.pdf ├── 20160219-东方证券-《因子选股系列研究之六》:用组合优化构建更精确多样的投资组合.pdf ├── 20160523-长江证券-多因子模型系列报告之一:模型理论随想和纯因子组合构建.pdf ├── 20160812-东方证券-《因子选股系列研究之十》:Alpha因子库精简与优化.pdf ├── 20161023-长江证券-多因子模型系列报告之二:利用纯因子组合检验因子有效性.pdf ├── 20161026-长江证券-多因子模型系列报告之三:利用纯因子组合进行因子投资.pdf ├── 20180301-东方证券-因子选股系列研究之三十五:组合优化的若干问题.pdf ├── 21_组合优化是与非——因子选股系列研究之二十一.pdf ├── Barra China Equity Model Descriptor details.pdf ├── Barra China Equity Model.pdf ├── Fama-MacBeth-1973-Risk--return--and-equilibrium-empirical-tests.pdf ├── The Cross-Section of expected stock return.pdf └── fama_common risk factors in the returns on stock and bonds.pdf /README.md: -------------------------------------------------------------------------------- 1 | # 量化投资 2 | 3 | 内容为2018年在私募公司实习,所学习知识、所完成工作任务的总结。 4 | 5 | 6 | 7 | ## 主题 8 | 9 | 一共包括以下四部分: 10 | 11 | - Part1:量化投资基础知识学习 12 | - Part2:因子测试流程学习 13 | - Part3:公司因子测试库学习 14 | - Part4:独立完成的因子测试任务 15 | 16 | 17 | 18 | 前三部分均为md文件,存放在notebook文件夹,主要是平时学习内容的框架总结,基于简单明了的快速学习,因此其中涉及到具体的金融理论模型,还有待研习。 19 | 20 | 第四部分是实习的主要工作,也是在完成前三部分学习后,开展的因子挖掘和因子测试任务,包括说明和代码,存放在code文件夹。 21 | 22 | 23 | 24 | ## 流程 25 | 26 | | 一般工作流程 | 阅读证券公司研报+因子测试验证 | 27 | | ------------ | ------------------------------------------------------------ | 28 | | 整体思路: | 根据不同的特征组合,使用机器学习算法预测股票涨跌幅的概率,将预测概率值作为因子进行测试。 | 29 | | 滚动预测周期 | 一般采用股票信息的月频数据或者周频数据,前12个月的数据作为训练集,预测下一个月的概率值 | 30 | | 主要使用工具 | jupyter notebook | 31 | 32 | 33 | 34 | (PS:因为测试股票数据全部来源于公司<公司数据购买于choice金融终端和聚宽>,不能进行公布,因此只提供数据说明和流程代码。) 35 | 36 | 37 | 38 | ## 任务 39 | 40 | 主要完成任务 41 | 42 | - 基于股价大幅波动的另类选股因子研究:采用logistic 模型估计股票在未来1个月的大幅下跌概率,并以此作为选股因子;在15%、20%、25%、30%、35%和40%(5%,10%)等阈值计算下跌概率的选股因子 43 | - 116组合因子测试(根据公司现有的116个因子进行特征组合,完成预测) 44 | 45 | - 分类:根据股票涨跌幅分类(上涨的前30%划为1,后30%为-1) 46 | 47 | - 回归:预测股票涨跌幅度的具体数值 48 | - 150组合因子测试:根据150个已有的特征值进行股价涨跌幅的分类预测,完成概率因子的测试 49 | - 158组合因子测试:根据['mom','emotion', 'pricevol', 'minute', 'finance', 'valuation', 'alpha191','growth'] 八大类因子组合测试(共计158个因子)进行股价涨跌幅的2分类预测,完成概率因子的测试 50 | - 风险因子测试:根据10个风险因子进行股价涨跌幅的分类预测,完成概率因子的测试 51 | - Alpha测试:根据192个Alpha因子进行股价涨跌幅的2分类预测,完成概率因子的测试。 52 | 53 | <每个任务对应code中相应文件> 54 | 55 | 56 | 57 | -------------------------------------------------------------------------------- /code/#关于Miya_Tes.py文件说明#/Miya_Test.py: -------------------------------------------------------------------------------- 1 | import pandas as pd 2 | import numpy as np 3 | import datetime as dt 4 | import daolib.dao as dao 5 | import daolib.dso as dso 6 | import util.sectool as sectool 7 | import util.operatetool as optool 8 | import matplotlib.pyplot as plt 9 | import pickle 10 | import time 11 | from tqdm import tqdm 12 | 13 | #分类预测 14 | def predict_probo_class(data,model,loop,date_list,T,x): 15 | train,test=data_input_class(data,date_list,T,x) 16 | predict_value=[] 17 | test_accuracy=[] 18 | train_accuracy=[] 19 | start_clock = time.time() 20 | for m in range(len(date_list)-loop): 21 | X_train, X_test, Y_train, Y_test,Xx_test= splitdata(data,train,test,m+loop-1,m,m+loop-1,m+loop) 22 | model.fit(X_train,Y_train) 23 | predict=model.predict_proba(X_test) 24 | predict=pd.DataFrame(predict) 25 | score_test=model.score(X_test,Y_test) 26 | score_train=model.score(X_train,Y_train) 27 | predict['stock']=Xx_test[:,-2] 28 | predict['date']=Xx_test[:,-1] 29 | predict_value.append(predict) 30 | test_accuracy.append(score_test) 31 | train_accuracy.append(score_train) 32 | end_clock = time.time() 33 | print('cpu cost time: ', end_clock - start_clock) 34 | factor0_df,factor1_df=changeindex2(data,predict_value,loop,date_list) 35 | return factor0_df,factor1_df,test_accuracy,train_accuracy 36 | 37 | 38 | 39 | 40 | #数据构造 41 | 42 | #加入十个风险因子 43 | def risk_factor(alpha_factor_series): 44 | alpha_factor_series['beta'] = dao.get_style_risk_factor('risk_beta', 'def') 45 | alpha_factor_series['mv'] = dao.get_style_risk_factor('risk_mv', 'def') 46 | alpha_factor_series['vol'] = dao.get_style_risk_factor('risk_vol', 'def') 47 | alpha_factor_series['liq'] = dao.get_style_risk_factor('risk_liq', 'def') 48 | alpha_factor_series['ey'] = dao.get_style_risk_factor('risk_ey', 'def') 49 | alpha_factor_series['bp'] = dao.get_style_risk_factor('risk_bp', 'def') 50 | alpha_factor_series['mom'] = dao.get_style_risk_factor('risk_mom', 'def') 51 | alpha_factor_series['lev'] = dao.get_style_risk_factor('risk_lev', 'def') 52 | alpha_factor_series['nlmv'] = dao.get_style_risk_factor('risk_nlmv', 'def') 53 | alpha_factor_series['gro'] = dao.get_style_risk_factor('risk_gro', 'def') 54 | alpha_factor_series['trade_status'] = trade_status_df 55 | return alpha_factor_series 56 | 57 | #标签值 - -分类 58 | 59 | def rise_fall_class(trade_date_m_series, T): 60 | zz_df = dao.get_index_component_data('ZZ') 61 | stock_price_df = dao.get_security_info('stock_price_info')[trade_date_m_series] 62 | stock_close_df = stock_price_df.xs('close', level=1)[trade_date_m_series] 63 | trade_status_df = stock_price_df.xs('trade_status', level=1)[trade_date_m_series] 64 | pause_df = trade_status_df.copy() 65 | pause_df[pause_df == 1] = np.nan 66 | pause_df[pause_df == 0] = 1 67 | 68 | stock_chg_df = stock_close_df.pct_change(axis=1) 69 | stock_return_df = stock_chg_df * pause_df * zz_df 70 | stock_return_df = stock_return_df.shift(-1, axis=1) 71 | 72 | is_rise_df = stock_return_df.copy() 73 | rise_quatile_percent = T 74 | rise_quan30_series = is_rise_df.quantile(rise_quatile_percent) 75 | rise_quan70_series = is_rise_df.quantile(1.0 - rise_quatile_percent) 76 | 77 | is_rise_df[is_rise_df > rise_quan70_series] = 999 78 | is_rise_df[is_rise_df < rise_quan30_series] = -999 79 | is_rise_df[is_rise_df.abs() != 999] = np.nan 80 | 81 | is_rise_df.replace(to_replace=[-999, 999], value=[-1, 1], inplace=True) 82 | return is_rise_df 83 | 84 | 85 | # 划分测试集和训练集 86 | def concat_data(data, date_list, is_rise_df): 87 | factor_class_series = data.map(lambda x: x.loc[:, date_list[0]:date_list[-1]]) 88 | data_df = pd.DataFrame() 89 | factor_name_list = factor_class_series.index.tolist() 90 | data_dict = {} 91 | for trade_date in tqdm(date_list[:]): 92 | data_section_series = factor_class_series.map(lambda x: x[trade_date] if trade_date in x.columns else None) 93 | data_section_df = pd.DataFrame(data_section_series.to_dict()) 94 | data_section_df = data_section_df.reindex(columns=factor_name_list) 95 | data_section_df['rise_fall'] = is_rise_df[trade_date] 96 | data_dict[trade_date] = data_section_df 97 | data_section_df['date'] = trade_date 98 | return data_dict 99 | 100 | 101 | def data_train_test(data_pct, x): 102 | data_pct['rise_fall'] = data_pct['rise_fall'].fillna(x) # 注意fillna填充!!!(x=-1是标志值二分类,分为“-1,1”两类) 103 | # data_pct['rise_fall']=data_pct['rise_fall'].fillna(0) #x=0是标志值三分类,分为“-1,0,1”两类 104 | data_pct_test = data_pct # 包含0,-1,1的三种分类的全部数据预测集 105 | data_pct_test = data_pct[data_pct['trade_status'] == 0] # 选择正常股票状态的数据 106 | # data_pct_test=data_pct_test.dropna() #删除空值 107 | data_pct_train = data_pct[~data_pct['rise_fall'].isin([0])] # 不包含0的训练集 108 | data_pct_train = data_pct_train[data_pct_train['trade_status'] == 0] # 选择正常股票状态的数据 109 | # data_pct_dropna_train=data_pct_train.dropna() 110 | return data_pct_train, data_pct_test 111 | 112 | 113 | def data_input_class(data, date_list, T, x): 114 | is_rise_df = rise_fall_class(date_list, T) 115 | data_dict = concat_data(data, date_list, is_rise_df) 116 | data_df = pd.concat([data_dict[frame] for frame in data_dict.keys()]) 117 | train1, test1 = data_train_test(data_df, x) 118 | return train1, test1 119 | 120 | 121 | # 数据标准化,可以处理空值 122 | def standard(X_train, X_test): 123 | X_train_scaled = 1.0 * (X_train - X_train.mean()) / X_train.std() # 数据标准化 124 | X_test_scaled = 1.0 * (X_test - X_test.mean()) / X_test.std() # 数据标准化 125 | return X_train_scaled, X_test_scaled 126 | 127 | 128 | def countsum(data): 129 | a = data.reset_index() 130 | a.rename(columns=lambda x: x.replace('index', 'stock'), inplace=True) 131 | resultdata = (a['stock'].groupby(a['date'])).describe() 132 | resultdata['sum'] = resultdata['count'].cumsum() 133 | return resultdata, a 134 | 135 | 136 | # 两分类划分,划分训练集data,测试集alldata(训练集的类别只有(0,1),测试集包含所有类别(0,1,-1)) 137 | def splitdata(data,train,test, i, j, x, y): 138 | resultdata, a = countsum(train) 139 | resultalldata, b = countsum(test) 140 | i = resultdata['sum'][i] 141 | j = resultdata['sum'][j] 142 | x = resultalldata['sum'][x] 143 | y = resultalldata['sum'][y] 144 | 145 | newname = data.index.tolist() 146 | newname.append('stock') 147 | newname.append('date') 148 | 149 | X_train = np.array(a[newname][j:i]) 150 | Y_train = np.array(a['rise_fall'][j:i]) 151 | # 第x个月,测试集 152 | X_test = np.array(b[newname][x:y]) 153 | Y_test = np.array(b['rise_fall'][x:y]) 154 | X_train_scaled, X_test_scaled = X_train[:, :-3], X_test[:, :-3] 155 | 156 | return X_train_scaled, X_test_scaled, Y_train, Y_test, X_test 157 | 158 | #缺失值填充 159 | #按照行业均值进行填充 160 | def fillna_ind_mean(data,date_list): 161 | industry_class_df=dao.get_stock_industry_data('CS') #股票行业信息----周频信息 162 | industry_class_m_df=industry_class_df.loc[:,date_list] #股票行业信息----月频信息 163 | #按照行进行填充,下一个值 164 | industry_class_m_df=industry_class_m_df.fillna(method='bfill',axis=1) 165 | industry_class_m_df=industry_class_m_df.fillna('未知') 166 | 167 | for i in range(1,len(date_list)): 168 | resl_series = pd.Series() 169 | industry_series=industry_class_m_df.iloc[:,i] 170 | group_data = industry_series.index.groupby(industry_series.values) 171 | industry_list = list(group_data.keys()) 172 | data_series=data.iloc[:,i] 173 | for industry_name in industry_list: 174 | industry_temp = data_series.loc[group_data[industry_name]] 175 | industry_temp = industry_temp.fillna(industry_temp.mean()) 176 | resl_series = resl_series.append(industry_temp) 177 | stock_list = list(set(data_series.index) - set(industry_series.dropna().index)) 178 | resl_series = resl_series.append(data_series.loc[stock_list]) 179 | data.iloc[:,i]=resl_series 180 | return data 181 | 182 | #只做均值填充 183 | def data_fillna_mean(df,date_list): 184 | df=fillna_ind_mean(df,date_list) 185 | return df 186 | 187 | #空值填充,行业均值填充 188 | def nonefill(data,date_list): 189 | tempdata=data 190 | for i in tempdata: 191 | i=data_fillna_mean(i,date_list) 192 | return tempdata 193 | 194 | #预测准确率分析 195 | def accu_score(score,name): 196 | plt.axhline(0.5,color='red') 197 | plt.plot(score) 198 | plt.text(score[1],score[1],name,fontdict={'size':'16','color':'black'}) 199 | plt.title("Accuracy on TestData", fontsize=15) 200 | 201 | #因子数据合成 202 | import itertools 203 | def change(alldata,data,n,m,M,date_list): 204 | date=date_list[M:] 205 | factor_df=pd.DataFrame(columns=date) 206 | factor_df['stock']=list(alldata[100].index) 207 | for i,t in itertools.zip_longest(data,date): 208 | temp=factor_df[['stock']] 209 | temp[t]=np.nan 210 | u=i.iloc[:,[n,m]] 211 | u.columns=[t,'stock'] 212 | factor_Crash=pd.concat([u,temp],join='inner',ignore_index=True) 213 | factor_Crash.sort_values(t,inplace=True) 214 | factor_Crash.drop_duplicates(['stock'],inplace=True) 215 | factor_Crash.sort_values('stock',inplace=True) 216 | factor_Crash.reset_index(inplace=True) 217 | factor_df[t]= factor_Crash[t] 218 | factorF_df=factor_df.set_index(['stock']) 219 | return factorF_df 220 | 221 | def changeindex2(alldata,data,M,date_list): 222 | factor0_df=change(alldata,data,0,2,M,date_list) 223 | factor1_df=change(alldata,data,1,2,M,date_list) 224 | return factor0_df,factor1_df 225 | 226 | 227 | #因子T显著度 228 | import util.factortool as ftool 229 | def factor_test_T(factor_list,factor_name): 230 | risk_test=pd.DataFrame() 231 | for i ,n in itertools.zip_longest(factor_list,factor_name): 232 | risk_test[n]=ftool.factor_risk_test_tvalue(i) 233 | return risk_test 234 | 235 | 236 | import alphafactors.factorprepro_class as fp 237 | import alphafactors.factoranalyse as fa 238 | 239 | #因子处理(分成两种方向) 240 | def factor_analyse(name,factor): # 0-positive , 1-negetive 241 | factor_prepro_obj = fp.FactorPrePro(factor_name=name, factor_data_df=factor, universe='ZZ', neutral_list=None) 242 | factor_prepro_obj.run_process(start_date=max(factor.columns[0], dt.datetime(2007,1,5)), end_date=factor.columns[-1]) 243 | df = factor_prepro_obj.factor_pro_df 244 | factor_test_obj = fa.FactorAnalyse(factor_name=name, factor_data_df=df, factor_dr=0) # 0-positive , 1-negetive 245 | factor_test_obj.run_analyse_new(start_date=dt.datetime(2009,1,23), universe='ZZ') 246 | return factor_test_obj 247 | 248 | #因子测试画图显示 249 | def show1(factor_test_obj): 250 | factor_test_obj.net_value_df.iloc[:,-3:].plot(figsize=(20,10)) 251 | def show2(factor_test_obj): 252 | factor_test_obj.factor_perform_df 253 | return factor_test_obj.factor_perform_df 254 | def show3(factor_test_obj): 255 | factor_test_obj.factor_para_df 256 | return factor_test_obj.factor_para_df 257 | def show4(factor_test_obj): 258 | factor_test_obj.port_perform_df 259 | return factor_test_obj.port_perform_df 260 | def show5(factor_test_obj): 261 | factor_test_obj.port_perform_df['annual_return'].plot(kind='bar') 262 | return factor_test_obj.port_perform_df['annual_return'].plot(kind='bar') 263 | def show6(factor_test_obj): 264 | factor_test_obj.factor_index_df['IC值'].plot(kind='bar', figsize=(20,10), color='blue') 265 | return factor_test_obj.factor_index_df['IC值'].plot(kind='bar', figsize=(20,10), color='blue') 266 | 267 | 268 | import util.evalstat as evl 269 | 270 | 271 | def factor_test_pre(factor): # 因子中性化预处理 272 | factor_prepro_obj = fp.FactorPrePro(factor_name='factor_test', factor_data_df=factor, universe='ZZ', 273 | neutral_list=None) 274 | factor_prepro_obj.run_process(start_date=max(factor.columns[0], dt.datetime(2007, 1, 5)), 275 | end_date=factor.columns[-1]) 276 | df = factor_prepro_obj.factor_pro_df 277 | return df 278 | 279 | 280 | def factor_test(stock_weighted_series): 281 | perform_obj = evl.PortPerform(port_series=stock_weighted_series, ret_type='open', fee=0.0035) 282 | perform_obj.run() 283 | return perform_obj 284 | 285 | 286 | def show01(perform_obj): 287 | perform_obj.net_value_plot() 288 | 289 | 290 | def show02(perform_obj): 291 | perform_obj.get_strategy_perform() 292 | return perform_obj.get_strategy_perform() 293 | 294 | 295 | def show03(perform_obj): 296 | perform_obj.get_avg_turnover() 297 | return perform_obj.get_avg_turnover() 298 | 299 | 300 | def show04(perform_obj): 301 | perform_obj.get_annual_perform() 302 | return perform_obj.get_annual_perform() 303 | 304 | #投资组合构建 305 | def stock_choice(data, num): # 直接挑选概率值前100支股票,等权 306 | stock_series = pd.Series() 307 | for i in data.columns: 308 | stock_series.loc[i] = pd.Series(index=[data[i].sort_values(ascending=False).head(num).index], data=1 / num) 309 | stock_choice_obj = factor_test(stock_series) 310 | 311 | return stock_choice_obj 312 | 313 | 314 | def stock_bench_ind(data, num): # 行业中性,基准权重后挑选100支股票 315 | stock_series = pd.Series() 316 | for i in data.columns: 317 | set_date = i 318 | stock_series[i] = get_industry_stock(data[i], set_date, stock_num=num) 319 | stock_choice_obj = factor_test(stock_series) 320 | 321 | return stock_choice_obj 322 | 323 | 324 | def factor_stock_choose(factor, num): 325 | factor_obj = factor_test_pre(factor) # 做因子预处理 326 | # 等权选num支 327 | samew_pre = stock_choice(factor_obj, num) 328 | samew_unpre = stock_choice(factor, num) # 不做因子预处理,等权直接选100支 329 | # 不等权选num支 330 | unw_pre = stock_bench_ind(factor_obj, num) 331 | unw_unpre = stock_bench_ind(factor, num) 332 | return samew_pre, samew_unpre, unw_pre, unw_unpre 333 | 334 | #行业基准权重 335 | 336 | def get_bench_ind_weight(set_date, bench_code='ZZ500'): 337 | industry_series = optool.get_series_from_df(data_df=stock_industry_df, set_date=set_date, axis=1).dropna() 338 | group_data = industry_series.index.groupby(industry_series) 339 | # 基准行业权重 340 | bench_component_df = dao.get_index_component_data(bench_code) 341 | bench_series = pd.Series(bench_component_df[set_date].set_index('code')['weight']) 342 | bench_series = bench_series / bench_series.sum() 343 | bench_ind_weight_series = pd.Series(index=stock_industry_list) 344 | for industry_name in stock_industry_list: 345 | ind_stock_list = group_data[industry_name] 346 | temp_series = bench_series.copy() 347 | bench_ind_weight_series.loc[industry_name] = temp_series.reindex(ind_stock_list).sum() 348 | bench_ind_weight_series.fillna(0, inplace=True) 349 | return bench_ind_weight_series 350 | 351 | 352 | def get_industry_stock(stock_factor_series, set_date, stock_num=100): 353 | industry_series = optool.get_series_from_df(data_df=stock_industry_df, set_date=set_date, axis=1).dropna() 354 | stock_series = stock_pool_df[set_date] 355 | stock_list = industry_series.index.intersection(stock_series.dropna().index).tolist() 356 | industry_series = industry_series.loc[stock_list] 357 | 358 | group_data = industry_series.index.groupby(industry_series) 359 | 360 | # 基准行业权重 361 | bench_ind_weight_series = get_bench_ind_weight(set_date=set_date) 362 | bench_ind_num_series = round(bench_ind_weight_series * stock_num).astype(int) 363 | 364 | port_series = pd.Series() 365 | # 得到行业中性组合 366 | for industry_name in stock_industry_list[:]: 367 | if bench_ind_weight_series[industry_name] <= 0.0: 368 | continue 369 | ind_stock_list = group_data[industry_name] 370 | ind_stock_series = pd.Series(stock_factor_series.loc[ind_stock_list]).reindex(ind_stock_list).sort_values( 371 | ascending=False) 372 | 373 | ind_stock_num = bench_ind_num_series[industry_name] 374 | if ind_stock_num < 1: 375 | ind_stock_num += 1 376 | 377 | if ind_stock_series.shape[0] >= ind_stock_num: 378 | xx = ind_stock_series.head(ind_stock_num) 379 | temp_series = xx / xx.sum() * bench_ind_weight_series[industry_name] 380 | else: 381 | temp_series = ind_stock_series / ind_stock_series.sum() * bench_ind_weight_series[industry_name] 382 | 383 | temp_series = pd.Series(index=ind_stock_series.index[:ind_stock_num], data=1.0 / ind_stock_num) * \ 384 | bench_ind_weight_series[industry_name] 385 | port_series = port_series.append(temp_series) 386 | return port_series 387 | 388 | -------------------------------------------------------------------------------- /code/#关于Miya_Tes.py文件说明#/README.md: -------------------------------------------------------------------------------- 1 | # Miya_Test.py 2 | 3 | Miya_Test.py文件为封装包文件,包含下面34个函数,用于分类预测,二分类时直接调用。 4 | 5 | 可以直接导入使用,完成概率因子的测试。 6 | 7 | *code文件夹中158Factor_Test和150Factor_Test均导入Miya_Test.py进行测试 8 | 9 | 10 | 11 | ## 使用说明 12 | 13 | 下面以周频数据为例,调用Miya_Test.py一共分为4部分: 14 | 15 | ``` 16 | import Miya-Test as miya 17 | ``` 18 | 19 | 1.调用miya.predict_probo_class进行概率预测得到二分类的两种概率因子 20 | 21 | 2.调用miya.factor_analyse将概率因子做因子处理 22 | 23 | 3.调用miya.factor_stock_choose将概率因子用作投资组合检验 24 | 25 | 4.调用miya.show01,miya.show1进行图像分析 26 | 27 | 代码例如下: 28 | 29 | ``` 30 | import Miya-Test as miya 31 | 32 | #预测概率,使用lgb分类模型,涨跌幅按照前30%划分为1类,其余为0,滚动预测周期为前48期预测后一期 33 | Wfactor0_lgb3,Wfactor1_lgb3,Wtest_accuracy_lgb3,Wtrain_accuracy_lgb3=miya.predict_probo_class(week_data,model_lgb,48,week_list,0.3,-1) 34 | #因子检验 35 | Wfactor1_lgb3_obj=miya.factor_analyse("test1",Wfactor1_lgb3) 36 | #画图显示 37 | miya.show1(Wfactor1_lgb3_obj) 38 | #投资组合检验 39 | Wsamew_lgb3_pre,Wsamew_lgb3_unpre,Wunw_lgb3_pre,Wunw_lgb3_unpre=miya.factor_stock_choose(Wfactor1_lgb3,100) 40 | #画图显示 41 | miya.show01(Wsamew_lgb3_pre) 42 | ``` 43 | 44 | Wfactor0_lgb3:概率为0的因子 45 | 46 | Wfactor1_lgb3:概率为1的因子 47 | 48 | Wtest_accuracy_lgb3:滚动预测测试集的准确率 49 | 50 | Wtrain_accuracy_lgb3:滚动预测验证集的准确率 51 | 52 | Wfactor1_lgb3_obj: 经过因子检验1预处理后的因子 53 | 54 | Wsamew_lgb3_pre:等权构建投资组合选取100支后的因子表现,经过中性化处理 55 | 56 | Wsamew_lgb3_unpre:等权构建投资组合选取100支后的因子表现,没有经过中性化处理 57 | 58 | Wunw_lgb3_pre:不等权构建投资组合选取100支后的因子表现,经过中性化处理 59 | 60 | Wunw_lgb3_unpre:不等权构建投资组合选取100支后的因子表现,没有经过中性化处理 61 | 62 | 63 | 64 | ## 函数说明 65 | 66 | ### 分类预测 67 | 68 | ##### 1.def predict_probo_class(data,model,loop,date_list,T,x) 69 | 70 | ​ return factor0_df,factor1_df,test_accuracy,train_accuracy 71 | 72 | 73 | 74 | ### 数据构造 75 | 76 | #加入十个风险因子 77 | 78 | ##### 2.def risk_factor(data): 79 | 80 | return data 81 | 82 | ##### 3.def rise_fall_class(trade_date_m_series, T): 83 | 84 | ​ return is_rise_df #标签值-分类 85 | 86 | 87 | #### 划分测试集和训练集 88 | ##### 4.def concat_data(data, date_list, is_rise_df): 89 | 90 | ​ return data_dict 91 | 92 | ##### 5.def data_train_test(data_pct, x): 93 | 94 | ​ return data_pct_train, data_pct_test 95 | 96 | ##### 6.def data_input_class(data, date_list, T, x): 97 | 98 | ​ return train1, test1 99 | 100 | 101 | #### 数据标准化,可以处理空值 102 | ##### 7.def standard(X_train, X_test): 103 | 104 | ​ return X_train_scaled, X_test_scaled 105 | 106 | ##### 8.def countsum(data): 107 | 108 | ​ return resultdata, a 109 | 110 | #### 两分类划分,划分训练集data,测试集alldata 111 | 112 | (训练集的类别只有(0,1),测试集包含所有类别(0,1,-1)) 113 | 114 | ##### 9.def splitdata(data,train,test, i, j, x, y): 115 | 116 | ​ return X_train_scaled, X_test_scaled, Y_train, Y_test, X_test 117 | 118 | 119 | 120 | ### 缺失值填充 121 | 122 | #### 按照行业均值进行填充 123 | 124 | ##### 10.def fillna_ind_mean(data,date_list): 125 | 126 | ​ return data #只做均值填充 127 | 128 | ##### 11.def data_fillna_mean(df,date_list): 129 | 130 | return df #空值填充,行业均值填充 131 | 132 | ##### 12.def nonefill(data,date_list): 133 | 134 | ​ return tempdata 135 | 136 | 137 | 138 | ### 预测准确率分析 139 | 140 | ##### 13.def accu_score(score,name): 141 | 142 | 143 | 144 | ### 因子数据合成 145 | 146 | ##### 14.def change(data,n,m,M,date_list): 147 | 148 | ​ return factorF_df 149 | 150 | ##### 15.def changeindex2(data,M,date_list): 151 | 152 | ​ return factor0_df,factor1_df 153 | 154 | #### 因子T显著度 155 | 156 | ##### 16.def factor_test_T(factor_list,factor_name): 157 | 158 | ​ return risk_test 159 | 160 | #### 因子处理(分成两种方向) 161 | 162 | ##### 17.def factor_analyse(name,factor): 163 | 164 | ​ 0-positive , 1-negetive 165 | 166 | ​ return factor_test_obj 167 | 168 | #### 因子测试画图显示 169 | 170 | ##### 18.def show1(factor_test_obj): 171 | 172 | ##### 19.def show2(factor_test_obj): 173 | 174 | ##### 20.def show3(factor_test_obj): 175 | 176 | ##### 21.def show4(factor_test_obj): 177 | 178 | ##### 22.def show5(factor_test_obj): 179 | 180 | ##### 23.def show6(factor_test_obj): 181 | 182 | 183 | 184 | #### 因子中性化预处理 185 | 186 | ##### 23.def factor_test_pre(factor): 187 | 188 | ​ return df 189 | 190 | ##### 25.def factor_test(stock_weighted_series): 191 | 192 | ​ return perform_obj 193 | 194 | ##### 26.def show01(perform_obj): 195 | 196 | ​ perform_obj.net_value_plot() 197 | 198 | ##### 27.def show02(perform_obj): 199 | 200 | ​ perform_obj.get_strategy_perform() 201 | ​ return perform_obj.get_strategy_perform() 202 | 203 | ##### 28.def show03(perform_obj): 204 | 205 | ​ perform_obj.get_avg_turnover() 206 | ​ return perform_obj.get_avg_turnover() 207 | 208 | ##### 29.def show04(perform_obj): 209 | 210 | ​ perform_obj.get_annual_perform() 211 | ​ return perform_obj.get_annual_perform() 212 | 213 | 214 | 215 | ### 投资组合构建 216 | 217 | ##### 30.def stock_choice(data, num): 218 | 219 | ​ return stock_choice_obj #直接挑选概率值前100支股票,等权 220 | 221 | ##### 31.def stock_bench_ind(data, num): 222 | 223 | ​ return stock_choice_obj #行业中性,基准权重后挑选100支股票 224 | 225 | ##### 32.def factor_stock_choose(factor, num): 226 | 227 | ​ return samew_pre, samew_unpre, unw_pre, unw_unpre 228 | 229 | #### 行业基准权重 230 | 231 | ##### 33.def get_bench_ind_weight(set_date, bench_code='ZZ500'): 232 | 233 | ​ return bench_ind_weight_series 234 | 235 | ##### 34.def get_industry_stock(stock_factor_series, set_date, stock_num=100): 236 | 237 | ​ return port_series -------------------------------------------------------------------------------- /code/116_Factor_Test/Classification-分类/116FactorTest_Classifier.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "一共选取六大类因子中的106个特征值+10个风险因子,使用LightGBM来进行2分类概率预测(分为两种标签值构造)\n", 8 | "二分类:\n", 9 | "1.按照股票涨跌幅排序,收益前T%标记为1, 其余标记为0\n", 10 | "2.按照股票涨跌幅排序,收益前T%标记为1, 后T%标记为-1,中间为0(训练集只用“1,-1”类,删除“0”类,测试集用全部)" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": null, 16 | "metadata": { 17 | "collapsed": true 18 | }, 19 | "outputs": [], 20 | "source": [ 21 | "import pandas as pd\n", 22 | "import numpy as np\n", 23 | "import datetime as dt\n", 24 | "import daolib.dao as dao\n", 25 | "import daolib.dso as dso\n", 26 | "import util.sectool as sectool\n", 27 | "import util.operatetool as optool\n", 28 | "import matplotlib.pyplot as plt\n", 29 | "import pickle\n", 30 | "import time\n", 31 | "from tqdm import tqdm\n", 32 | "%matplotlib inline" 33 | ] 34 | }, 35 | { 36 | "cell_type": "markdown", 37 | "metadata": {}, 38 | "source": [ 39 | "## 读取数据" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": null, 45 | "metadata": { 46 | "collapsed": true 47 | }, 48 | "outputs": [], 49 | "source": [ 50 | "stock_price_df = dao.get_security_info('stock_price_info')\n", 51 | "all_stock_list = stock_price_df.index.get_level_values(0).drop_duplicates().tolist()\n", 52 | "#六大类因子106个\n", 53 | "pricevol_factors_list = ['pv_clo_ratemean_1m', 'pv_clo_ratemean_3m', 'pv_clo_ratemean_6m', 'pv_corr_clo_turn_1m',\n", 54 | " 'pv_corr_clo_turn_3m', 'pv_max_ret_1m', 'pv_max_ret_3m', 'pv_cgo_3m', 'pv_iv_capm_hs_3m', 'pv_iv_capm_r2_hs_3m', 'pv_iv_capm_r2_zz_3m',\n", 55 | " 'pv_iv_capm_zz_3m', 'pv_iv_ff_hs_3m', 'pv_iv_ff_r2_hs_3m', 'pv_iv_ff_r2_zz_3m', 'pv_iv_ff_zz_3m',\n", 56 | " 'pv_cgo_1m', 'pv_cgo_6m', 'pv_iv_capm_hs_1m', 'pv_iv_capm_r2_hs_1m', 'pv_iv_capm_r2_zz_1m',\n", 57 | " 'pv_iv_capm_zz_1m', 'pv_iv_ff_hs_1m', 'pv_iv_ff_r2_hs_1m', 'pv_iv_ff_r2_zz_1m', 'pv_iv_ff_zz_1m']\n", 58 | "\n", 59 | "mom_factors_list = ['mm_mom_1m', 'mm_mom_1m_weighted', 'mm_mom_1m_weightedexp',\n", 60 | " 'mm_mom_1y_weightedexp', 'mm_mom_3m', 'mm_mom_3m_weighted', 'mm_mom_3m_weightedexp',\n", 61 | " 'mm_mom_6m_weighted', 'mm_mom_6m_weightedexp']\n", 62 | "\n", 63 | "emotion_factors_list = ['em_cov_volume_1m','em_cov_volume_3m','em_ret_amt_1m',\\\n", 64 | " 'em_ret_amt_3m', 'em_ret_amt_6m','em_sl_volume_1m','em_turn_cov_1m',\\\n", 65 | " 'em_turn_cov_3m','em_turn_mean_1m', 'em_turn_mean_3m','em_turn_mean_6m',\\\n", 66 | " 'em_turn_std_1m', 'em_turn_std_3m','em_turn_std_6m', 'em_turn_stdrate_1m','em_turn_stdrate_3m',\\\n", 67 | " ]\n", 68 | "\n", 69 | "finance_factors_list = ['fn_gross_profit2assets', 'fn_qfa_ebit', 'fn_qfa_ebit2assets',\n", 70 | " 'fn_qfa_ni_from_operating', 'fn_qfa_ni_from_operating2assets', 'fn_qfa_np',\n", 71 | " 'fn_qfa_profit_before_tax2assets', 'fn_qfa_roa', 'fn_qfa_roa_deducted', 'fn_qfa_roe',\n", 72 | " 'fn_qfa_roe_deducted', 'fn_qfa_total_income2assets', 'fn_qfa_tot_income_indus']\n", 73 | "\n", 74 | "growth_factors_list = ['gw_advantage', 'gw_chg_gpmargin_ttm', 'gw_growth_qfa_yoy_gr',\n", 75 | " 'gw_qfa_np_enhance', 'gw_qfa_yoyop', 'gw_qfa_yoy_gr', 'gw_qfa_yoy_or', 'gw_roe_chg',\n", 76 | " 'gw_roe_deducted_chg', 'gw_roe_deducted_enhance', 'gw_roe_deducted_yoy', 'gw_roe_enhance',\n", 77 | " 'gw_roe_yoy', 'gw_trend', 'gw_yoy_qfa_deductedprofit', 'gw_yoy_qfa_np_belongto_parcomsh',\n", 78 | " 'gw_yoy_qfa_roe_deducted']\n", 79 | "\n", 80 | "valuation_factors_list = [ 'val_ep_de_qfa', 'val_ep_de_sq',\n", 81 | " 'val_ep_de_ttm', 'val_ep_qfa', 'val_ep_sq', 'val_pge_de',\n", 82 | " 'val_equity_mkt']\n", 83 | "\n", 84 | "estimate_factors_list = ['et_eps_ftm_mom3', 'et_ep_ftm', 'et_ep_ftm_mom1', 'et_ep_ftm_mom3', 'et_ep_ftm_mom6',\n", 85 | " 'et_ep_fy1', 'et_ep_fy2', 'et_gr_ftm_mom3', 'et_np_ftm', 'et_np_ftm_mom3', 'et_np_fy1',\n", 86 | " 'et_np_fy2', 'et_peg_ftm', 'et_roe_ftm']\n", 87 | "\n", 88 | "alpha191_factors_list =['alpha101_013_data','alpha101_015_data','alpha101_016_data','alpha101_026_data',\n", 89 | " 'alpha101_040_data','alpha101_044_data','alpha101_050_data','alpha101_055_data',\n", 90 | " 'alpha101_064_data', 'alpha101_074_data' ,'alpha101_075_data','alpha101_099_data',\n", 91 | " 'alpha191_001_data','alpha191_005_data','alpha191_007_data','alpha191_009_data','alpha191_017_data',\n", 92 | " 'alpha191_022_data','alpha191_030_data','alpha191_031_data','alpha191_032_data','alpha191_036_data',\n", 93 | " 'alpha191_042_data','alpha191_046_data','alpha191_074_data','alpha191_090_data','alpha191_092_data',\n", 94 | " 'alpha191_101_data','alpha191_105_data','alpha191_112_data','alpha191_118_data','alpha191_123_data',\n", 95 | " 'alpha191_124_data','alpha191_139_data','alpha191_173_data']" 96 | ] 97 | }, 98 | { 99 | "cell_type": "code", 100 | "execution_count": null, 101 | "metadata": { 102 | "collapsed": true 103 | }, 104 | "outputs": [], 105 | "source": [ 106 | "#十个风险因子\n", 107 | "\n", 108 | "#股票上市状态(只选择为0的值,不为0的值为异常值)\n", 109 | "price_df=dao.get_security_info('stock_price_info')\n", 110 | "trade_status_df=price_df.xs('trade_status',level=1)\n", 111 | "\n", 112 | "def risk_factor(alpha_factor_series):\n", 113 | " alpha_factor_series['beta'] = dao.get_style_risk_factor('risk_beta', 'def')\n", 114 | " alpha_factor_series['mv'] = dao.get_style_risk_factor('risk_mv', 'def')\n", 115 | " alpha_factor_series['vol'] = dao.get_style_risk_factor('risk_vol', 'def')\n", 116 | " alpha_factor_series['liq'] = dao.get_style_risk_factor('risk_liq', 'def')\n", 117 | " alpha_factor_series['ey'] = dao.get_style_risk_factor('risk_ey', 'def')\n", 118 | " alpha_factor_series['bp'] = dao.get_style_risk_factor('risk_bp', 'def')\n", 119 | " alpha_factor_series['mom'] = dao.get_style_risk_factor('risk_mom', 'def')\n", 120 | " alpha_factor_series['lev'] = dao.get_style_risk_factor('risk_lev', 'def')\n", 121 | " alpha_factor_series['nlmv'] = dao.get_style_risk_factor('risk_nlmv', 'def')\n", 122 | " alpha_factor_series['gro'] = dao.get_style_risk_factor('risk_gro', 'def')\n", 123 | " alpha_factor_series['trade_status'] = trade_status_df\n", 124 | " return alpha_factor_series" 125 | ] 126 | }, 127 | { 128 | "cell_type": "code", 129 | "execution_count": null, 130 | "metadata": { 131 | "collapsed": true 132 | }, 133 | "outputs": [], 134 | "source": [ 135 | "def read_factor_data(factors_name_list, trade_date_20d_series):\n", 136 | " compound_factor_dict = {}\n", 137 | " alpha_factor_series = pd.Series()\n", 138 | " for compound_name in factors_name_list[:]:\n", 139 | " pro_factor_path = \"D:\\\\Data\\\\factors\\\\\" + compound_name + '\\\\'\n", 140 | " #alpha_factor_series = pd.Series()\n", 141 | " factor_list = globals().get(compound_name + '_factors_list')\n", 142 | " for factor_name in factor_list:\n", 143 | "# print('读取 ', factor_name)\n", 144 | " data_df = pd.read_pickle(pro_factor_path + factor_name)\n", 145 | " begin_date = max(data_df.columns[0], trade_date_20d_series[0])\n", 146 | " trade_date_series = trade_date_20d_series[trade_date_20d_series >= begin_date]\n", 147 | " alpha_factor_series.loc[factor_name] = data_df.loc[:, trade_date_series]\n", 148 | " #alpha_factor_df = ftool.factor_class_generate(alpha_factor_series)\n", 149 | " #compound_factor_dict[compound_name] = alpha_factor_df\n", 150 | " return alpha_factor_series" 151 | ] 152 | }, 153 | { 154 | "cell_type": "markdown", 155 | "metadata": {}, 156 | "source": [ 157 | "### 获取数据" 158 | ] 159 | }, 160 | { 161 | "cell_type": "code", 162 | "execution_count": null, 163 | "metadata": { 164 | "collapsed": true 165 | }, 166 | "outputs": [], 167 | "source": [ 168 | "start_date = dt.datetime(2007, 1, 1)\n", 169 | "end_date = dt.datetime(2018,9,1)\n", 170 | "factor_name_list = ['emotion', 'pricevol', 'mom', 'finance', 'valuation', 'alpha191'] #growth\n", 171 | "\n", 172 | "#月频数据\n", 173 | "trade_date_m_series = pd.Series( dso.get_trade_date(start_date=start_date, end_date=end_date, period='m') )\n", 174 | "month_list = [date for date in trade_date_m_series if dt.datetime(2009,10,1)rise_quan70_series] = 999\n", 550 | " is_rise_df[is_rise_df= ind_stock_num:\n", 955 | " xx = ind_stock_series.head(ind_stock_num)\n", 956 | " temp_series = xx / xx.sum() * bench_ind_weight_series[industry_name]\n", 957 | " else:\n", 958 | " temp_series = ind_stock_series / ind_stock_series.sum() * bench_ind_weight_series[industry_name]\n", 959 | "\n", 960 | " temp_series = pd.Series(index=ind_stock_series.index[:ind_stock_num], data=1.0 / ind_stock_num) * \\\n", 961 | " bench_ind_weight_series[industry_name]\n", 962 | " port_series = port_series.append(temp_series)\n", 963 | " return port_series" 964 | ] 965 | } 966 | ], 967 | "metadata": { 968 | "kernelspec": { 969 | "display_name": "Python 3", 970 | "language": "python", 971 | "name": "python3" 972 | }, 973 | "language_info": { 974 | "codemirror_mode": { 975 | "name": "ipython", 976 | "version": 3 977 | }, 978 | "file_extension": ".py", 979 | "mimetype": "text/x-python", 980 | "name": "python", 981 | "nbconvert_exporter": "python", 982 | "pygments_lexer": "ipython3", 983 | "version": "3.6.1" 984 | } 985 | }, 986 | "nbformat": 4, 987 | "nbformat_minor": 2 988 | } 989 | -------------------------------------------------------------------------------- /code/116_Factor_Test/README.md: -------------------------------------------------------------------------------- 1 | # 116组合因子测试 2 | 3 | 4 | 5 | 6 | 7 | ## 处理流程 8 | 9 | **此部分的目标是:根据116个已有的特征值进行股价涨跌幅的分类预测,完成概率因子的测试。** 10 | 11 | 12 | 13 | 预测的方案分为分类和回归,分类和回归的标签值如下表,其中分类时采用两种标签进行测试, 14 | 15 | 1. 第一种三分类划分:按照股票涨跌幅排序,收益前30%标记为1, 后30%标记为-1,其余为0 16 | 2. 第二种两分类划分:按照股票涨跌幅排序,收益前30%标记为1, 其余为0 17 | 18 | | 分类标签值: | 1.按照股票涨跌幅排序,收益前30%标记为1, 后30%标记为-1,其余为0 | 19 | | ---------------- | ------------------------------------------------------------ | 20 | | | **2.按照股票涨跌幅排序,收益前30%标记为1,其余为0** | 21 | | **回归标签值:** | **股票涨跌幅的具体数值 ** | 22 | 23 | 24 | 25 | ## **数据构建** 26 | 27 | | **特征值:** | **一共选取六大类因子中的106个特征值+10个风险因子** | 28 | | ---------------- | ------------------------------------------------------------ | 29 | | **分类标签值:** | 1.按照股票涨跌幅排序,收益前30%标记为1, 后30%标记为-1,其余为0 | 30 | | | 2.按照股票涨跌幅排序,收益前30%标记为1,其余为0 | 31 | | **回归标签值:** | 股票涨跌幅的具体数值 | 32 | | **数据时间:** | 2009年10月-2018年8月 | 33 | | **缺失值处理:** | 按照行业均值填充 | 34 | | **数据标准化:** | 基于原始数据的均值(mean)和标准差(standard deviation) | 35 | | **训练集:** | `月频:67180 周频:290294 ` | 36 | | **测试集:** | `月频:118998 周频:500736` | 37 | 38 | 39 | 40 | | 预测滚动周期: | 月频数据:根据前12个月的数据值预测后一个月的值,前24个月预测后一个月 | 41 | | -------------- | :----------------------------------------------------------- | 42 | | | **周频数据:根据前48周的数据值预测后一周的数据** | 43 | 44 | 45 | 46 | ## 预测模型 47 | 48 | 预测分为两种,单个模型预测和集成模型预测,集成模型预测分为两种,一种是简单的平均集成,一种是Meta_Stacking的元模型预测 49 | 50 | | 单个模型预测 | | 51 | | ------------ | ------------- | 52 | | 集成模型预测 | 简单平均集成 | 53 | | | Meta_Stacking | 54 | 55 | 分类模型:xgb,lgb,RF,GBoost 56 | 57 | 回归模型:lasso,ENet,KRR,GBoost,xgb,lgb 58 | 59 | 60 | 61 | ## 因子处理 62 | 63 | 因子测试阶段分为两种。 64 | 65 | 因子中性化处理:为了在用某一因子时能够剔除其他因素的影响,使得选出的股票更加分散,需要进行中性化处理。(即:为了消除因子中的偏差和不必要的影响) 66 | 67 | 对于因子来说,中性化主要考虑市场风险和行业风险。 68 | 69 | 行业中性:多头组合的行业配置与对冲基准的行业配置一致,目的在于剔除行业因子对策略收益的影响,仅考察行业内部个股的超额收益。(行业中性策略的净值曲线往往比较平稳,回测较小) 70 | 71 | 风格因子中性:多头组合的风格因子较之对冲基准的风险暴露为0,目的在于使多头组合的风格特征完全与对冲基准相匹配,使得组合的超额收益不是来自于某类风格 72 | 73 | | 目的: | 为了在用某一因子时能够剔除其他因素的影响,使得选出的股票更加分散,需要进行中性 化处理。(即:为了消除因子中的偏差和不必要的影响) | 74 | | :------------- | :----------------------------------------------------------- | 75 | | **主要考虑:** | **市场风险和行业风险** | 76 | | **处理方式:** | 利用回归,得到一个与风险因子线性无关的因子,即通过线性回归提取残差作为中性化后的因子。(处理完成后的中性化因子与风险因子之间的相关性严格为0) | 77 | 78 | | 因子测试 | 第一种直接选取前100只股票,等权分配 | 79 | | -------- | :----------------------------------------------------------- | 80 | | | 第二种选择前100只股票,根据行业基准权重进行不等权配置(每个行业至少要有1只股票) | 81 | 82 | -------------------------------------------------------------------------------- /code/116_Factor_Test/Regression-回归/116FactorTest_Regressor.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "markdown", 5 | "metadata": {}, 6 | "source": [ 7 | "一共选取六大类因子中的106个特征值+10个风险因子,进行回归预测\n", 8 | "回归目标值为:股票涨跌幅\n", 9 | "滚动预测:前12期预测下一期(月频数据)\n", 10 | " 前48期预测下一期(周频数据)" 11 | ] 12 | }, 13 | { 14 | "cell_type": "code", 15 | "execution_count": null, 16 | "metadata": { 17 | "collapsed": true 18 | }, 19 | "outputs": [], 20 | "source": [ 21 | "import pandas as pd\n", 22 | "import numpy as np\n", 23 | "import datetime as dt\n", 24 | "import daolib.dao as dao\n", 25 | "import daolib.dso as dso\n", 26 | "import util.sectool as sectool\n", 27 | "import util.operatetool as optool\n", 28 | "import matplotlib.pyplot as plt\n", 29 | "import pickle\n", 30 | "import time\n", 31 | "from tqdm import tqdm\n", 32 | "%matplotlib inline" 33 | ] 34 | }, 35 | { 36 | "cell_type": "markdown", 37 | "metadata": {}, 38 | "source": [ 39 | "## 读取数据" 40 | ] 41 | }, 42 | { 43 | "cell_type": "code", 44 | "execution_count": null, 45 | "metadata": { 46 | "collapsed": true 47 | }, 48 | "outputs": [], 49 | "source": [ 50 | "#直接从文件夹读取分类构造好的数据\n", 51 | "week_alpha_factor_series=pickle.load(open(\"./factor_test_data/LightGBM_allfactor/week_alpha_factor_series\",\"rb+\")) #周频数据\n", 52 | "month_alpha_factor_series=pickle.load(open(\"./factor_test_data/LightGBM_allfactor/month_alpha_factor_series\",\"rb+\")) #月频数据" 53 | ] 54 | }, 55 | { 56 | "cell_type": "markdown", 57 | "metadata": {}, 58 | "source": [ 59 | "## 概率预测" 60 | ] 61 | }, 62 | { 63 | "cell_type": "markdown", 64 | "metadata": {}, 65 | "source": [ 66 | "### 单个模型评估" 67 | ] 68 | }, 69 | { 70 | "cell_type": "code", 71 | "execution_count": null, 72 | "metadata": { 73 | "collapsed": true 74 | }, 75 | "outputs": [], 76 | "source": [ 77 | "Wscore_lasso,Wscore_ENet,Wscore_KRR ,Wscore_GBoost,Wscore_xgb,Wscore_lgb = rmse_siglemodel(week_alpha_factor_series,12,week_list) #周频数据" 78 | ] 79 | }, 80 | { 81 | "cell_type": "code", 82 | "execution_count": null, 83 | "metadata": { 84 | "collapsed": true 85 | }, 86 | "outputs": [], 87 | "source": [ 88 | "#RMSE画图分析(看rmse平均值)\n", 89 | "rmse_list=[lasso_rmse,ENet_rmse,xgb_rmse,lgb_rmse,GBoost_rmse]\n", 90 | "label_list=['lasso_rmse','ENet_rmse','xgb_rmse','lgb_rmse','GBoost_rmse']\n", 91 | "rmse_show(rmse_list,label_list)" 92 | ] 93 | }, 94 | { 95 | "cell_type": "code", 96 | "execution_count": null, 97 | "metadata": { 98 | "collapsed": true 99 | }, 100 | "outputs": [], 101 | "source": [ 102 | "# 最终模型的预测结果\n", 103 | "lasso_rmse,lasso_predict_value=rmsle(lasso,month_alpha_factor_series,12,month_list)\n", 104 | "ENet_rmse,ENet_predict_value=rmsle(ENet,month_alpha_factor_series,12,month_list)\n", 105 | "lgb_rmse,lgb_predict_value=rmsle(model_lgb,month_alpha_factor_series,12,month_list)\n", 106 | "xgb_rmse,xgb_predict_value=rmsle(model_xgb,month_alpha_factor_series,12,month_list)\n", 107 | "GBoost_rmse,GBoost_predict_value=rmsle(GBoost,month_alpha_factor_series,12,month_list)" 108 | ] 109 | }, 110 | { 111 | "cell_type": "markdown", 112 | "metadata": {}, 113 | "source": [ 114 | "### 集成模型预测" 115 | ] 116 | }, 117 | { 118 | "cell_type": "markdown", 119 | "metadata": {}, 120 | "source": [ 121 | "#### 简单平均模型融合,(选择最小rmse的三个模型),计算融合模型的rmse" 122 | ] 123 | }, 124 | { 125 | "cell_type": "code", 126 | "execution_count": null, 127 | "metadata": { 128 | "collapsed": true 129 | }, 130 | "outputs": [], 131 | "source": [ 132 | "averaged_models = AveragingModels(models = (ENet,model_lgb,lasso,model_lgb))\n", 133 | "averaged_score1 = rmsle_cv(averaged_models,month_alpha_factor_series,12,month_list)\n", 134 | "averaged_score2,averaged_predict_value=rmsle(averaged_models,month_alpha_factor_series,12,month_list)" 135 | ] 136 | }, 137 | { 138 | "cell_type": "markdown", 139 | "metadata": {}, 140 | "source": [ 141 | "#### Meta-model模型融合" 142 | ] 143 | }, 144 | { 145 | "cell_type": "code", 146 | "execution_count": null, 147 | "metadata": { 148 | "collapsed": true 149 | }, 150 | "outputs": [], 151 | "source": [ 152 | "stacked_averaged_models = StackingAveragedModels(base_models = (ENet,model_lgb, model_xgb),meta_model = lasso)\n", 153 | "stacked_averaged_score1 = rmsle_cv(stacked_averaged_models,month_alpha_factor_series,12,month_list)\n", 154 | "stacked_averaged_score2,stacked_averaged_predict_value=rmsle(stacked_averaged_models,month_alpha_factor_series,12,month_list)" 155 | ] 156 | }, 157 | { 158 | "cell_type": "markdown", 159 | "metadata": {}, 160 | "source": [ 161 | "#### 数据融合" 162 | ] 163 | }, 164 | { 165 | "cell_type": "code", 166 | "execution_count": null, 167 | "metadata": { 168 | "collapsed": true 169 | }, 170 | "outputs": [], 171 | "source": [ 172 | "#最终的数据融合(分配不同权重)\n", 173 | "# ensemble1 = GBoost_predict_value*0.7+ xgb_predict_value*0.15 +lgb_predict_value*0.15\n", 174 | "# ensemble2 = GBoost_predict_value*0.8+ xgb_predict_value*0.1 +lgb_predict_value*0.1\n", 175 | "ensemble3 = GBoost_predict_value*0.6+ xgb_predict_value*0.2 +lgb_predict_value*0.2" 176 | ] 177 | }, 178 | { 179 | "cell_type": "code", 180 | "execution_count": null, 181 | "metadata": { 182 | "collapsed": true 183 | }, 184 | "outputs": [], 185 | "source": [] 186 | }, 187 | { 188 | "cell_type": "markdown", 189 | "metadata": {}, 190 | "source": [ 191 | "### 因子分析" 192 | ] 193 | }, 194 | { 195 | "cell_type": "markdown", 196 | "metadata": {}, 197 | "source": [ 198 | "#### 因子保存" 199 | ] 200 | }, 201 | { 202 | "cell_type": "code", 203 | "execution_count": null, 204 | "metadata": { 205 | "collapsed": true 206 | }, 207 | "outputs": [], 208 | "source": [ 209 | "import pickle\n", 210 | "stacked_averaged_predict_value.to_pickle(\"./factor_test_data/LightGBM_allfactor2/stacked_averaged_predict_value\")" 211 | ] 212 | }, 213 | { 214 | "cell_type": "markdown", 215 | "metadata": {}, 216 | "source": [ 217 | "#### 因子测试" 218 | ] 219 | }, 220 | { 221 | "cell_type": "code", 222 | "execution_count": null, 223 | "metadata": { 224 | "collapsed": true 225 | }, 226 | "outputs": [], 227 | "source": [ 228 | "#因子测试1\n", 229 | "averaged_predict_value_obj=factor_analyse('test1',averaged_predict_value)\n", 230 | "#因子测试2\n", 231 | "average_samew_pre,average_samew_unpre,average_unw_pre,average_unw_unpre=factor_stock_choose(averaged_predict_value,100)" 232 | ] 233 | }, 234 | { 235 | "cell_type": "markdown", 236 | "metadata": {}, 237 | "source": [ 238 | "## 函数部分" 239 | ] 240 | }, 241 | { 242 | "cell_type": "markdown", 243 | "metadata": {}, 244 | "source": [ 245 | "### 回归模型(lasso,ENet,KRR,GBoost,model_xgb,model_lgb)" 246 | ] 247 | }, 248 | { 249 | "cell_type": "code", 250 | "execution_count": null, 251 | "metadata": { 252 | "collapsed": true 253 | }, 254 | "outputs": [], 255 | "source": [ 256 | "from sklearn.linear_model import ElasticNet, Lasso, BayesianRidge, LassoLarsIC\n", 257 | "from sklearn.ensemble import RandomForestRegressor, GradientBoostingRegressor\n", 258 | "from sklearn.kernel_ridge import KernelRidge\n", 259 | "from sklearn.pipeline import make_pipeline\n", 260 | "from sklearn.preprocessing import RobustScaler\n", 261 | "from sklearn.base import BaseEstimator, TransformerMixin, RegressorMixin, clone\n", 262 | "from sklearn.model_selection import KFold, cross_val_score, train_test_split\n", 263 | "from sklearn.metrics import mean_squared_error\n", 264 | "import xgboost as xgb\n", 265 | "import lightgbm as lgb\n", 266 | "\n", 267 | "lasso = make_pipeline(RobustScaler(), Lasso(alpha =0.0005, random_state=1))\n", 268 | "\n", 269 | "ENet = make_pipeline(RobustScaler(), ElasticNet(alpha=0.0005, l1_ratio=.9, random_state=3))\n", 270 | "\n", 271 | "KRR = KernelRidge(alpha=0.6, kernel='polynomial', degree=2, coef0=2.5)\n", 272 | "\n", 273 | "GBoost = GradientBoostingRegressor(n_estimators=3000, learning_rate=0.05,max_depth=4, max_features='sqrt',)\n", 274 | "\n", 275 | "RF=RandomForestRegressor(max_depth=5)\n", 276 | "\n", 277 | "model_xgb = xgb.XGBRegressor(learning_rate=0.05, max_depth=5, )\n", 278 | "\n", 279 | "model_lgb = lgb.LGBMRegressor(objective='regression',num_leaves=50,learning_rate=0.05)" 280 | ] 281 | }, 282 | { 283 | "cell_type": "markdown", 284 | "metadata": {}, 285 | "source": [ 286 | "### 单个模型分数评估" 287 | ] 288 | }, 289 | { 290 | "cell_type": "code", 291 | "execution_count": null, 292 | "metadata": { 293 | "collapsed": true 294 | }, 295 | "outputs": [], 296 | "source": [ 297 | "#模型分数评估(采用交叉验证三折评估,计算RMSE)\n", 298 | "n_folds=3\n", 299 | "def rmsle_cv(model,data,M,date_list):\n", 300 | " RMSE=[]\n", 301 | " train,test=data_input_reg(data,date_list) \n", 302 | " for m in range(len(date_list)-M-4):\n", 303 | " X_train, X_test, Y_train, Y_test,Xx_test= splitdata(data,train,test,m+M-1,m,m+M-1,m+M)\n", 304 | " kf = KFold(n_folds, shuffle=True, random_state=42).get_n_splits(X_train)\n", 305 | " rmse= np.sqrt(-cross_val_score(model, X_train, Y_train, scoring=\"neg_mean_squared_error\", cv = kf))\n", 306 | " RMSE.append(rmse)\n", 307 | " mean_rmse=np.array(RMSE).mean()\n", 308 | " return mean_rmse\n", 309 | "\n", 310 | "def rmse_siglemodel(data,loop,date_list): #单个回归模型评估(三折评估计算rmse)\n", 311 | " regscore_lasso= rmsle_cv(lasso,data,loop,date_list)\n", 312 | " regscore_ENet = rmsle_cv(ENet,data,loop,date_list)\n", 313 | " regscore_KRR = rmsle_cv(KRR,data,loop,date_list)\n", 314 | " regscore_GBoost = rmsle_cv(GBoost,data,loop,date_list)\n", 315 | " regscore_xgb = rmsle_cv(model_xgb,data,loop,date_list)\n", 316 | " regscore_lgb = rmsle_cv(model_lgb,data,loop,date_list)\n", 317 | " return regscore_lasso,regscore_ENet,regscore_KRR ,regscore_GBoost,regscore_xgb,regscore_lgb " 318 | ] 319 | }, 320 | { 321 | "cell_type": "markdown", 322 | "metadata": {}, 323 | "source": [ 324 | "### 最终预测结果" 325 | ] 326 | }, 327 | { 328 | "cell_type": "code", 329 | "execution_count": null, 330 | "metadata": { 331 | "collapsed": true 332 | }, 333 | "outputs": [], 334 | "source": [ 335 | "def rmsle(model,data,loop,date_list):\n", 336 | " RMSE=[]\n", 337 | " predict_value=[]\n", 338 | " train,test=data_input_reg(data,date_list) \n", 339 | " for m in range(len(date_list)-loop-4):\n", 340 | " X_train, X_test, Y_train, Y_test,Xx_test= splitdata(data,train,test,m+loop-1,m,m+loop-1,m+loop)\n", 341 | " model.fit(X_train, Y_train)\n", 342 | " train_pred = model.predict(X_train)\n", 343 | " y_pred =model.predict(X_test)\n", 344 | " y_pred=pd.DataFrame(y_pred)\n", 345 | " y_pred['stock']=Xx_test[:,-2]\n", 346 | " y_pred['date']=Xx_test[:,-1] \n", 347 | " rmse=np.sqrt(mean_squared_error(Y_train, train_pred))\n", 348 | " RMSE.append(rmse)\n", 349 | " predict_value.append(y_pred)\n", 350 | " factor=changeindex1(predict_value,loop,date_list)\n", 351 | " return RMSE,factor" 352 | ] 353 | }, 354 | { 355 | "cell_type": "markdown", 356 | "metadata": {}, 357 | "source": [ 358 | "### 准确率分析" 359 | ] 360 | }, 361 | { 362 | "cell_type": "code", 363 | "execution_count": null, 364 | "metadata": { 365 | "collapsed": true 366 | }, 367 | "outputs": [], 368 | "source": [ 369 | "#RMSE画图分析(看平均值)\n", 370 | "def rmse_show(rmse_list,label_list):\n", 371 | " for i in rmse_list:\n", 372 | " plt.plot(i,\"x-\",label=label_list[rmse_list.index(i)])\n", 373 | " plt.legend() \n", 374 | " for i in rmse_list:\n", 375 | " print(label_list[rmse_list.index(i)],\"平均RMSE为:\",np.array(i).mean())" 376 | ] 377 | }, 378 | { 379 | "cell_type": "markdown", 380 | "metadata": {}, 381 | "source": [ 382 | "### 模型融合" 383 | ] 384 | }, 385 | { 386 | "cell_type": "markdown", 387 | "metadata": {}, 388 | "source": [ 389 | "#### 简单平均模型融合" 390 | ] 391 | }, 392 | { 393 | "cell_type": "code", 394 | "execution_count": null, 395 | "metadata": { 396 | "collapsed": true 397 | }, 398 | "outputs": [], 399 | "source": [ 400 | "class AveragingModels(BaseEstimator, RegressorMixin, TransformerMixin):\n", 401 | " def __init__(self, models):\n", 402 | " self.models = models\n", 403 | " def fit(self, X, y):\n", 404 | " self.models_ = [clone(x) for x in self.models]\n", 405 | " for model in self.models_:\n", 406 | " model.fit(X, y)\n", 407 | " return self\n", 408 | " def predict(self, X):\n", 409 | " predictions = np.column_stack([model.predict(X) for model in self.models_])\n", 410 | " return np.mean(predictions, axis=1) " 411 | ] 412 | }, 413 | { 414 | "cell_type": "markdown", 415 | "metadata": {}, 416 | "source": [ 417 | "#### Meta-model Stacking" 418 | ] 419 | }, 420 | { 421 | "cell_type": "code", 422 | "execution_count": null, 423 | "metadata": { 424 | "collapsed": true 425 | }, 426 | "outputs": [], 427 | "source": [ 428 | "class StackingAveragedModels(BaseEstimator, RegressorMixin, TransformerMixin):\n", 429 | " def __init__(self, base_models, meta_model, n_folds=5):\n", 430 | " self.base_models = base_models\n", 431 | " self.meta_model = meta_model\n", 432 | " self.n_folds = n_folds\n", 433 | "\n", 434 | " def fit(self, X, y):\n", 435 | " self.base_models_ = [list() for x in self.base_models]\n", 436 | " self.meta_model_ = clone(self.meta_model)\n", 437 | " kfold = KFold(n_splits=self.n_folds, shuffle=True, random_state=156)\n", 438 | " out_of_fold_predictions = np.zeros((X.shape[0], len(self.base_models)))\n", 439 | " for i, model in enumerate(self.base_models):\n", 440 | " for train_index, holdout_index in kfold.split(X, y):\n", 441 | " instance = clone(model)\n", 442 | " self.base_models_[i].append(instance)\n", 443 | " instance.fit(X[train_index], y[train_index])\n", 444 | " y_pred = instance.predict(X[holdout_index])\n", 445 | " out_of_fold_predictions[holdout_index, i] = y_pred\n", 446 | " self.meta_model_.fit(out_of_fold_predictions, y)\n", 447 | " return self\n", 448 | " def predict(self, X):\n", 449 | " meta_features = np.column_stack([\n", 450 | " np.column_stack([model.predict(X) for model in base_models]).mean(axis=1)\n", 451 | " for base_models in self.base_models_ ])\n", 452 | " return self.meta_model_.predict(meta_features)" 453 | ] 454 | }, 455 | { 456 | "cell_type": "markdown", 457 | "metadata": {}, 458 | "source": [ 459 | "### 数据构造" 460 | ] 461 | }, 462 | { 463 | "cell_type": "code", 464 | "execution_count": null, 465 | "metadata": { 466 | "collapsed": true 467 | }, 468 | "outputs": [], 469 | "source": [ 470 | "#标签值-回归\n", 471 | "def rise_fall_reg(trade_date_m_series):\n", 472 | " zz_df = dao.get_index_component_data('ZZ')\n", 473 | " stock_price_df = dao.get_security_info('stock_price_info')[trade_date_m_series]\n", 474 | " stock_close_df = stock_price_df.xs('close',level=1)[trade_date_m_series]\n", 475 | " trade_status_df = stock_price_df.xs('trade_status', level=1)[trade_date_m_series]\n", 476 | " pause_df = trade_status_df.copy()\n", 477 | " pause_df[pause_df == 1] = np.nan\n", 478 | " pause_df[pause_df==0] = 1\n", 479 | "\n", 480 | " stock_chg_df = stock_close_df.pct_change(axis=1)\n", 481 | " stock_return_df = stock_chg_df * pause_df * zz_df\n", 482 | " stock_return_df = stock_return_df.shift(-1, axis=1)\n", 483 | " return stock_return_df\n", 484 | "\n", 485 | "#划分测试集和训练集\n", 486 | "def concat_data(data,date_list,is_rise_df):\n", 487 | " factor_class_series = data.map(lambda x: x.loc[:,date_list[0]:date_list[-1]])\n", 488 | " data_df = pd.DataFrame()\n", 489 | " factor_name_list = factor_class_series.index.tolist()\n", 490 | " data_dict = {}\n", 491 | " for trade_date in tqdm(date_list[:]):\n", 492 | " data_section_series = factor_class_series.map(lambda x: x[trade_date] if trade_date in x.columns else None)\n", 493 | " data_section_df = pd.DataFrame(data_section_series.to_dict())\n", 494 | " data_section_df =data_section_df.reindex(columns=factor_name_list)\n", 495 | " data_section_df['rise_fall'] = is_rise_df[trade_date]\n", 496 | " data_dict[trade_date] = data_section_df\n", 497 | " data_section_df['date'] = trade_date\n", 498 | " return data_dict\n", 499 | " \n", 500 | "def data_train_test(data_pct):\n", 501 | " data_pct_test=data_pct #包含0,-1,1的三种分类的全部数据预测集\n", 502 | " data_pct_test=data_pct[data_pct['trade_status']==0] #选择正常股票状态的数据\n", 503 | " data_pct_test=data_pct_test.dropna() #删除空值(回归空值太多)\n", 504 | " data_pct_train=data_pct #不包含0的训练集\n", 505 | " data_pct_train=data_pct_train[data_pct_train['trade_status']==0] #选择正常股票状态的数据\n", 506 | " data_pct_train=data_pct_train.dropna()\n", 507 | " return data_pct_train,data_pct_test\n", 508 | "\n", 509 | "def data_input_reg(data,date_list):\n", 510 | " is_rise_df=rise_fall_reg(date_list) \n", 511 | " data_dict=concat_data(data,date_list,is_rise_df)\n", 512 | " data_df = pd.concat([data_dict[frame] for frame in data_dict.keys()])\n", 513 | " train1,test1=data_train_test(data_df) \n", 514 | " return train1,test1\n", 515 | "\n", 516 | "# 数据标准化,可以处理空值\n", 517 | "def standard(X_train,X_test):\n", 518 | " X_train_scaled =1.0 * (X_train - X_train.mean()) / X_train.std() # 数据标准化\n", 519 | " X_test_scaled =1.0 * (X_test - X_test.mean()) / X_test.std() # 数据标准化\n", 520 | " return X_train_scaled,X_test_scaled \n", 521 | "\n", 522 | "def countsum(data):\n", 523 | " a=data.reset_index()\n", 524 | " a.rename(columns=lambda x:x.replace('index','stock'), inplace=True) \n", 525 | " resultdata=(a['stock'].groupby(a['date'])).describe()\n", 526 | " resultdata['sum']=resultdata['count'].cumsum()\n", 527 | " return resultdata,a\n", 528 | "\n", 529 | "#两分类划分,划分训练集data,测试集alldata(训练集的类别只有(0,1),测试集包含所有类别(0,1,-1))\n", 530 | "def splitdata(data,train,test,i,j,x,y):\n", 531 | " resultdata,a=countsum(train)\n", 532 | " resultalldata,b=countsum(test)\n", 533 | " i=resultdata['sum'][i]\n", 534 | " j=resultdata['sum'][j]\n", 535 | " x=resultalldata['sum'][x]\n", 536 | " y=resultalldata['sum'][y]\n", 537 | "\n", 538 | " newname=data.index.tolist() \n", 539 | " newname.append('stock')\n", 540 | " newname.append('date')\n", 541 | "\n", 542 | " X_train=np.array(a[newname][j:i])\n", 543 | " Y_train=np.array(a['rise_fall'][j:i])\n", 544 | " #第x个月,测试集\n", 545 | " X_test=np.array(b[newname][x:y])\n", 546 | " Y_test=np.array(b['rise_fall'][x:y])\n", 547 | " X_train_scaled,X_test_scaled=X_train[:,:-3],X_test[:,:-3]\n", 548 | " return X_train_scaled,X_test_scaled,Y_train,Y_test,X_test" 549 | ] 550 | }, 551 | { 552 | "cell_type": "markdown", 553 | "metadata": {}, 554 | "source": [ 555 | "### 因子数据合成" 556 | ] 557 | }, 558 | { 559 | "cell_type": "code", 560 | "execution_count": null, 561 | "metadata": { 562 | "collapsed": true 563 | }, 564 | "outputs": [], 565 | "source": [ 566 | "import itertools\n", 567 | "\n", 568 | "def change(data,n,m,M,date_list):\n", 569 | " date=date_list[M:-4]\n", 570 | " factor_df=pd.DataFrame(columns=date)\n", 571 | " factor_df['stock']=list(month_alpha_factor_series[100].index)\n", 572 | "# factor_df['stock']=data['stock']\n", 573 | "\n", 574 | " for i,t in itertools.zip_longest(data,date):\n", 575 | " temp=factor_df[['stock']]\n", 576 | " temp[t]=np.nan\n", 577 | " u=i.iloc[:,[n,m]]\n", 578 | " u.columns=[t,'stock']\n", 579 | " factor_Crash=pd.concat([u,temp],join='inner',ignore_index=True)\n", 580 | " factor_Crash.sort_values(t,inplace=True)\n", 581 | " factor_Crash.drop_duplicates(['stock'],inplace=True)\n", 582 | " factor_Crash.sort_values('stock',inplace=True)\n", 583 | " factor_Crash.reset_index(inplace=True)\n", 584 | " factor_df[t]= factor_Crash[t]\n", 585 | " factorF_df=factor_df.set_index(['stock'])\n", 586 | " return factorF_df\n", 587 | "\n", 588 | "def changeindex1(data,M,date_list):\n", 589 | " factor_df=change(data,0,1,M,date_list)\n", 590 | " return factor_df" 591 | ] 592 | }, 593 | { 594 | "cell_type": "markdown", 595 | "metadata": {}, 596 | "source": [ 597 | "### 因子显著度T检验" 598 | ] 599 | }, 600 | { 601 | "cell_type": "code", 602 | "execution_count": null, 603 | "metadata": { 604 | "collapsed": true 605 | }, 606 | "outputs": [], 607 | "source": [ 608 | "import util.factortool as ftool\n", 609 | "def factor_test_T(factor_list,factor_name): \n", 610 | " risk_test=pd.DataFrame()\n", 611 | " for i ,n in itertools.zip_longest(factor_list,factor_name):\n", 612 | " risk_test[n]=ftool.factor_risk_test_tvalue(i)\n", 613 | " return risk_test" 614 | ] 615 | }, 616 | { 617 | "cell_type": "markdown", 618 | "metadata": {}, 619 | "source": [ 620 | "### 因子测试1" 621 | ] 622 | }, 623 | { 624 | "cell_type": "code", 625 | "execution_count": null, 626 | "metadata": { 627 | "collapsed": true 628 | }, 629 | "outputs": [], 630 | "source": [ 631 | "import alphafactors.factorprepro_class as fp\n", 632 | "import alphafactors.factoranalyse as fa\n", 633 | "\n", 634 | "#因子处理(分成两种方向)\n", 635 | "def factor_analyse(name,factor): # 0-positive , 1-negetive\n", 636 | " factor_prepro_obj = fp.FactorPrePro(factor_name=name, factor_data_df=factor, universe='ZZ', neutral_list=None)\n", 637 | " factor_prepro_obj.run_process(start_date=max(factor.columns[0], dt.datetime(2007,1,5)), end_date=factor.columns[-1])\n", 638 | " df = factor_prepro_obj.factor_pro_df\n", 639 | " factor_test_obj = fa.FactorAnalyse(factor_name=name, factor_data_df=df, factor_dr=0) # 0-positive , 1-negetive\n", 640 | " factor_test_obj.run_analyse_new(start_date=dt.datetime(2009,1,23), universe='ZZ')\n", 641 | " return factor_test_obj\n", 642 | "\n", 643 | "#因子测试画图显示\n", 644 | "def show1(factor_test_obj):\n", 645 | " factor_test_obj.net_value_df.iloc[:,-3:].plot(figsize=(20,10))\n", 646 | "def show2(factor_test_obj):\n", 647 | " factor_test_obj.factor_perform_df\n", 648 | " return factor_test_obj.factor_perform_df\n", 649 | "def show3(factor_test_obj):\n", 650 | " factor_test_obj.factor_para_df\n", 651 | " return factor_test_obj.factor_para_df\n", 652 | "def show4(factor_test_obj):\n", 653 | " factor_test_obj.port_perform_df\n", 654 | " return factor_test_obj.port_perform_df\n", 655 | "def show5(factor_test_obj):\n", 656 | " factor_test_obj.port_perform_df['annual_return'].plot(kind='bar')\n", 657 | " return factor_test_obj.port_perform_df['annual_return'].plot(kind='bar') \n", 658 | "def show6(factor_test_obj):\n", 659 | " factor_test_obj.factor_index_df['IC值'].plot(kind='bar', figsize=(20,10), color='blue')\n", 660 | " return factor_test_obj.factor_index_df['IC值'].plot(kind='bar', figsize=(20,10), color='blue')" 661 | ] 662 | }, 663 | { 664 | "cell_type": "markdown", 665 | "metadata": {}, 666 | "source": [ 667 | "### 因子测试2" 668 | ] 669 | }, 670 | { 671 | "cell_type": "code", 672 | "execution_count": null, 673 | "metadata": { 674 | "collapsed": true 675 | }, 676 | "outputs": [], 677 | "source": [ 678 | "import util.evalstat as evl\n", 679 | " \n", 680 | "def factor_test_pre(factor): #因子中性化预处理\n", 681 | " factor_prepro_obj = fp.FactorPrePro(factor_name='factor_test', factor_data_df=factor, universe='ZZ', neutral_list=None)\n", 682 | " factor_prepro_obj.run_process(start_date=max(factor.columns[0], dt.datetime(2007,1,5)), end_date=factor.columns[-1])\n", 683 | " df = factor_prepro_obj.factor_pro_df\n", 684 | " return df\n", 685 | "\n", 686 | "def factor_test(stock_weighted_series):\n", 687 | " perform_obj=evl.PortPerform(port_series=stock_weighted_series,ret_type='open',fee=0.0035)\n", 688 | " perform_obj.run()\n", 689 | " return perform_obj\n", 690 | "\n", 691 | "def show01(perform_obj):\n", 692 | " perform_obj.net_value_plot() \n", 693 | "def show02(perform_obj):\n", 694 | " perform_obj.get_strategy_perform() \n", 695 | " return perform_obj.get_strategy_perform() \n", 696 | "def show03(perform_obj):\n", 697 | " perform_obj.get_avg_turnover() \n", 698 | " return perform_obj.get_avg_turnover() \n", 699 | "def show04(perform_obj):\n", 700 | " perform_obj.get_annual_perform() \n", 701 | " return perform_obj.get_annual_perform() " 702 | ] 703 | }, 704 | { 705 | "cell_type": "markdown", 706 | "metadata": {}, 707 | "source": [ 708 | "### 投资组合构建(2种:一种等权,一种不等权)" 709 | ] 710 | }, 711 | { 712 | "cell_type": "code", 713 | "execution_count": null, 714 | "metadata": { 715 | "collapsed": true 716 | }, 717 | "outputs": [], 718 | "source": [ 719 | "def stock_choice(data,num): #直接挑选概率值前100支股票,等权\n", 720 | " stock_series= pd.Series()\n", 721 | " for i in data.columns:\n", 722 | " stock_series.loc[i]=pd.Series(index=[data[i].sort_values(ascending=False).head(num).index],data=1/num)\n", 723 | " stock_choice_obj=factor_test(stock_series)\n", 724 | " return stock_choice_obj\n", 725 | "\n", 726 | "def stock_bench_ind(data,num): #行业中性,基准权重后挑选100支股票\n", 727 | " stock_series= pd.Series()\n", 728 | " for i in data.columns:\n", 729 | " set_date=i\n", 730 | " stock_series[i]=get_industry_stock(data[i], set_date, stock_num=num)\n", 731 | " stock_choice_obj =factor_test(stock_series)\n", 732 | " return stock_choice_obj\n", 733 | "\n", 734 | "def factor_stock_choose(factor,num):\n", 735 | " factor_obj=factor_test_pre(factor) #做因子预处理\n", 736 | " #等权选num支\n", 737 | " samew_pre=stock_choice(factor_obj,num)\n", 738 | " samew_unpre=stock_choice(factor,num) #不做因子预处理,等权直接选100支\n", 739 | " #不等权选num支\n", 740 | " unw_pre=stock_bench_ind(factor_obj,num)\n", 741 | " unw_unpre=stock_bench_ind(factor,num)\n", 742 | " return samew_pre,samew_unpre,unw_pre,unw_unpre" 743 | ] 744 | }, 745 | { 746 | "cell_type": "markdown", 747 | "metadata": {}, 748 | "source": [ 749 | "### 基准行业权重" 750 | ] 751 | }, 752 | { 753 | "cell_type": "code", 754 | "execution_count": null, 755 | "metadata": { 756 | "collapsed": true 757 | }, 758 | "outputs": [], 759 | "source": [ 760 | "stock_industry_df = dao.get_security_info('stock_industry_CS')\n", 761 | "stock_industry_list = dso.get_industry_classify('CS')\n", 762 | "stock_pool_df = dao.get_index_component_data('DEF')\n", 763 | "\n", 764 | "def get_bench_ind_weight(set_date, bench_code='ZZ500'):\n", 765 | " industry_series = optool.get_series_from_df(data_df=stock_industry_df, set_date=set_date, axis=1).dropna()\n", 766 | " group_data = industry_series.index.groupby(industry_series)\n", 767 | " # 基准行业权重\n", 768 | " bench_component_df = dao.get_index_component_data(bench_code)\n", 769 | " bench_series = pd.Series(bench_component_df[set_date].set_index('code')['weight'])\n", 770 | " bench_series = bench_series / bench_series.sum()\n", 771 | " bench_ind_weight_series = pd.Series(index=stock_industry_list)\n", 772 | " for industry_name in stock_industry_list:\n", 773 | " ind_stock_list = group_data[industry_name]\n", 774 | " temp_series = bench_series.copy()\n", 775 | " bench_ind_weight_series.loc[industry_name] = temp_series.reindex(ind_stock_list).sum()\n", 776 | " bench_ind_weight_series.fillna(0, inplace=True)\n", 777 | " return bench_ind_weight_series\n", 778 | "\n", 779 | "def get_industry_stock(stock_factor_series, set_date, stock_num=100):\n", 780 | " industry_series = optool.get_series_from_df(data_df=stock_industry_df, set_date=set_date, axis=1).dropna()\n", 781 | " stock_series = stock_pool_df[set_date]\n", 782 | " stock_list = industry_series.index.intersection(stock_series.dropna().index).tolist()\n", 783 | " industry_series = industry_series.loc[stock_list]\n", 784 | "\n", 785 | " group_data = industry_series.index.groupby(industry_series)\n", 786 | " # 基准行业权重\n", 787 | " bench_ind_weight_series = get_bench_ind_weight(set_date=set_date)\n", 788 | " bench_ind_num_series = round(bench_ind_weight_series * stock_num).astype(int)\n", 789 | " port_series = pd.Series()\n", 790 | " # 得到行业中性组合\n", 791 | " for industry_name in stock_industry_list[:]:\n", 792 | " if bench_ind_weight_series[industry_name] <= 0.0:\n", 793 | " continue\n", 794 | " ind_stock_list = group_data[industry_name]\n", 795 | " ind_stock_series = pd.Series(stock_factor_series.loc[ind_stock_list]).reindex(ind_stock_list).sort_values(\n", 796 | " ascending=False)\n", 797 | "\n", 798 | " ind_stock_num = bench_ind_num_series[industry_name]\n", 799 | " if ind_stock_num < 1:\n", 800 | " ind_stock_num += 1\n", 801 | "\n", 802 | " if ind_stock_series.shape[0] >= ind_stock_num:\n", 803 | " xx = ind_stock_series.head(ind_stock_num)\n", 804 | " temp_series = xx / xx.sum() * bench_ind_weight_series[industry_name]\n", 805 | " else:\n", 806 | " temp_series = ind_stock_series / ind_stock_series.sum() * bench_ind_weight_series[industry_name]\n", 807 | "\n", 808 | " temp_series = pd.Series(index=ind_stock_series.index[:ind_stock_num], data=1.0 / ind_stock_num) * \\\n", 809 | " bench_ind_weight_series[industry_name]\n", 810 | " port_series = port_series.append(temp_series)\n", 811 | " return port_series" 812 | ] 813 | } 814 | ], 815 | "metadata": { 816 | "kernelspec": { 817 | "display_name": "Python 3", 818 | "language": "python", 819 | "name": "python3" 820 | }, 821 | "language_info": { 822 | "codemirror_mode": { 823 | "name": "ipython", 824 | "version": 3 825 | }, 826 | "file_extension": ".py", 827 | "mimetype": "text/x-python", 828 | "name": "python", 829 | "nbconvert_exporter": "python", 830 | "pygments_lexer": "ipython3", 831 | "version": "3.6.1" 832 | } 833 | }, 834 | "nbformat": 4, 835 | "nbformat_minor": 2 836 | } 837 | -------------------------------------------------------------------------------- /code/150_Factor_Test/README.md: -------------------------------------------------------------------------------- 1 | # 150组合因子测试 2 | 3 | 4 | 5 | ## 处理流程 6 | 7 | **此部分的目标是:根据150个已有的特征值进行股价涨跌幅的分类预测,完成概率因子的测试。** 8 | 9 | 10 | 11 | 预测的方案为分类 12 | 13 | | | | 14 | | ---------------- | ------------------------------------------------- | 15 | | **分类标签值:** | **按照股票涨跌幅排序,收益前30%标记为1,其余为0** | 16 | 17 | 18 | 19 | ## **数据构建** 20 | 21 | | **特征值:** | **选取150个Alpha因子组合构成特征值** | 22 | | ---------------- | ------------------------------------------------------------ | 23 | | **分类标签值:** | **按照股票涨跌幅排序,收益前T%标记为1,其余为0** | 24 | | **数据时间:** | **2009年10月-2018年8月** | 25 | | **缺失值处理:** | **按照行业均值填充** | 26 | | **数据标准化:** | **基于原始数据的均值(mean)和标准差(standard deviation)** | 27 | | **数据集:** | **周频:1094178 rows × 152 columns** | 28 | 29 | | | | 30 | | ------------------ | ------------------------------------------------ | 31 | | **预测滚动周期:** | **周频数据:根据前48周的数据值预测后一周的数**据 | 32 | 33 | 34 | 35 | ## 预测模型 36 | 37 | | | | 38 | | ---------------- | ---------------------- | 39 | | **单个模型预测** | **分类模型:xgb,lgb** | 40 | 41 | 42 | 43 | ## **因子处理** 44 | 45 | 因子测试阶段分为两种。 46 | 47 | 因子中性化处理:为了在用某一因子时能够剔除其他因素的影响,使得选出的股票更加分散,需要进行中性化处理。(即:为了消除因子中的偏差和不必要的影响) 48 | 49 | 对于因子来说,中性化主要考虑市场风险和行业风险。 50 | 51 | 行业中性:多头组合的行业配置与对冲基准的行业配置一致,目的在于剔除行业因子对策略收益的影响,仅考察行业内部个股的超额收益。(行业中性策略的净值曲线往往比较平稳,回测较小) 52 | 53 | 风格因子中性:多头组合的风格因子较之对冲基准的风险暴露为0,目的在于使多头组合的风格特征完全与对冲基准相匹配,使得组合的超额收益不是来自于某类风格 54 | 55 | | **目的:** | **为了在用某一因子时能够剔除其他因素的影响,使得选出的股票更加分散,需要进行中性 化处理。(即:为了消除因子中的偏差和不必要的影响)** | 56 | | :------------- | :----------------------------------------------------------- | 57 | | **主要考虑:** | **市场风险和行业风险** | 58 | | **处理方式:** | **利用回归,得到一个与风险因子线性无关的因子,即通过线性回归提取残差作为中性化后的因子。(处理完成后的中性化因子与风险因子之间的相关性严格为0)** | 59 | 60 | | **因子测试** | **第一种直接选取前100只股票,等权分配** | 61 | | ------------ | :----------------------------------------------------------- | 62 | | | **第二种选择前100只股票,根据行业基准权重进行不等权配置(每个行业至少要有1只股票)** | 63 | 64 | -------------------------------------------------------------------------------- /code/158_Factor_Test/README.md: -------------------------------------------------------------------------------- 1 | # 158组合因子测试 2 | 3 | 4 | 5 | ## 处理流程 6 | 7 | **此部分的目标是:根据['mom','emotion', 'pricevol', 'minute', 'finance', 'valuation', 'alpha191','growth'] 八大类因子组合测试(共计158个因子)进行股价涨跌幅的2分类预测,完成概率因子的测试。** 8 | 9 | *导入Miya_Test 封装文件进行测试 10 | 11 | 主要测试五天数据(周频数据) 12 | 13 | 14 | 15 | 预测的方案为分类,分类的标签值 16 | 17 | | | | 18 | | ---------------- | ------------------------------------------------- | 19 | | **分类标签值:** | **按照股票涨跌幅排序,收益前30%标记为1,其余为0** | 20 | 21 | 22 | 23 | ## **数据构建** 24 | 25 | | **特征值:** | **选取['mom','emotion', 'pricevol', 'minute', 'finance', 'valuation', 'alpha191','growth'] 八大类因子组合构成特征值** | 26 | | ---------------- | ------------------------------------------------------------ | 27 | | **分类标签值:** | **按照股票涨跌幅排序,收益前T%标记为1,其余为0** | 28 | | **数据时间:** | **2009年10月-2018年8月** | 29 | | **缺失值处理:** | **按照行业均值填充** | 30 | | **数据标准化:** | **基于原始数据的均值(mean)和标准差(standard deviation)** | 31 | | **数据集:** | **周频:1094178 rows × 161 columns** | 32 | 33 | | | | 34 | | ------------------ | ------------------------------------------------ | 35 | | **预测滚动周期:** | **周频数据:根据前48周的数据值预测后一周的数据** | 36 | 37 | 38 | 39 | ## **预测模型** 40 | 41 | | | | 42 | | ---------------- | ---------------------- | 43 | | **单个模型预测** | **分类模型:xgb,lgb** | 44 | 45 | 46 | 47 | ## 因子处理 48 | 49 | 因子测试阶段分为两种。 50 | 51 | 因子中性化处理:为了在用某一因子时能够剔除其他因素的影响,使得选出的股票更加分散,需要进行中性化处理。(即:为了消除因子中的偏差和不必要的影响) 52 | 53 | 对于因子来说,中性化主要考虑市场风险和行业风险。 54 | 55 | 行业中性:多头组合的行业配置与对冲基准的行业配置一致,目的在于剔除行业因子对策略收益的影响,仅考察行业内部个股的超额收益。(行业中性策略的净值曲线往往比较平稳,回测较小) 56 | 57 | 风格因子中性:多头组合的风格因子较之对冲基准的风险暴露为0,目的在于使多头组合的风格特征完全与对冲基准相匹配,使得组合的超额收益不是来自于某类风格 58 | 59 | | **目的:** | **为了在用某一因子时能够剔除其他因素的影响,使得选出的股票更加分散,需要进行中性 化处理。(即:为了消除因子中的偏差和不必要的影响)** | 60 | | :------------- | :----------------------------------------------------------- | 61 | | **主要考虑:** | **市场风险和行业风险** | 62 | | **处理方式:** | **利用回归,得到一个与风险因子线性无关的因子,即通过线性回归提取残差作为中性化后的因子。(处理完成后的中性化因子与风险因子之间的相关性严格为0)** | 63 | 64 | | **因子测试** | **第一种直接选取前100只股票,等权分配** | 65 | | ------------ | :----------------------------------------------------------- | 66 | | | **第二种选择前100只股票,根据行业基准权重进行不等权配置(每个行业至少要有1只股票)** | 67 | 68 | -------------------------------------------------------------------------------- /code/Alpha191_Facor_Test/README.md: -------------------------------------------------------------------------------- 1 | ## 处理流程 2 | 3 | **此部分的目标是:根据192个Alpha因子进行股价涨跌幅的2分类预测,完成概率因子的测试。** 4 | 5 | 主要测试五天数据(周频数据) 6 | 7 | 8 | 9 | 预测的方案为分类,分类的标签值 10 | 11 | | | | 12 | | ---------------- | ------------------------------------------------- | 13 | | **分类标签值:** | **按照股票涨跌幅排序,收益前30%标记为1,其余为0** | 14 | 15 | 16 | 17 | ## **数据构建** 18 | 19 | | **特征值:** | ** 1.选取192个Alpha因子组合构成特征值 2.选取192个Alpha因子+10个风险因子组合构成特征值 ** | 20 | | ---------------- | ------------------------------------------------------------ | 21 | | **分类标签值:** | **按照股票涨跌幅排序,收益前T%标记为1,其余为0** | 22 | | **数据时间:** | **2009年10月-2018年8月** | 23 | | **缺失值处理:** | **按照行业均值填充** | 24 | | **数据标准化:** | **基于原始数据的均值(mean)和标准差(standard deviation)** | 25 | | **数据集:** | **周频:1094178 rows × 195 columns** | 26 | 27 | | | | 28 | | ------------------ | ------------------------------------------------ | 29 | | **预测滚动周期:** | **周频数据:根据前48周的数据值预测后一周的数据** | 30 | 31 | 32 | 33 | ## **预测模型** 34 | 35 | | | | 36 | | ---------------- | ---------------------- | 37 | | **单个模型预测** | **分类模型:xgb,lgb** | 38 | 39 | 40 | 41 | ## 因子处理 42 | 43 | 因子测试阶段分为两种。 44 | 45 | 因子中性化处理:为了在用某一因子时能够剔除其他因素的影响,使得选出的股票更加分散,需要进行中性化处理。(即:为了消除因子中的偏差和不必要的影响) 46 | 47 | 对于因子来说,中性化主要考虑市场风险和行业风险。 48 | 49 | 行业中性:多头组合的行业配置与对冲基准的行业配置一致,目的在于剔除行业因子对策略收益的影响,仅考察行业内部个股的超额收益。(行业中性策略的净值曲线往往比较平稳,回测较小) 50 | 51 | 风格因子中性:多头组合的风格因子较之对冲基准的风险暴露为0,目的在于使多头组合的风格特征完全与对冲基准相匹配,使得组合的超额收益不是来自于某类风格 52 | 53 | | 目的: | 为了在用某一因子时能够剔除其他因素的影响,使得选出的股票更加分散,需要进行中性 化处理。(即:为了消除因子中的偏差和不必要的影响) | 54 | | :------------- | :----------------------------------------------------------- | 55 | | **主要考虑:** | **市场风险和行业风险** | 56 | | **处理方式:** | **利用回归,得到一个与风险因子线性无关的因子,即通过线性回归提取残差作为中性化后的因子。(处理完成后的中性化因子与风险因子之间的相关性严格为0)** | 57 | 58 | | **因子测试** | **第一种直接选取前100只股票,等权分配** | 59 | | ------------ | :----------------------------------------------------------- | 60 | | | **第二种选择前100只股票,根据行业基准权重进行不等权配置(每个行业至少要有1只股票)** | 61 | 62 | -------------------------------------------------------------------------------- /code/基于股价大幅波动的另类选股因子研究/README.md: -------------------------------------------------------------------------------- 1 | # 基于股价大幅波动的另类选股因子研究 2 | 3 | 采用logistic 模型估计股票在未来1个月的大幅下跌概率,并以此作为选股因子;在15%、20%、25%、30%、35%和40%(5%,10%)等阈值计算下跌概率的选股因子。 4 | 5 | 股价未来波动方向大致可以分为三种:大幅上升、震荡、大幅下跌,如果能提前判断股价未来波动方向,可以为投资决策提供重要参考。采用不同方法估计股票未来大涨或大跌的概率,并以此作为因子研究其与股票未来收益率的关系。普遍观点认为,如果股票未来大幅下跌的可能性较大,则其未来的收益率应该越低;如果股票未来大幅上升的可能性较大,则股票未来的收益率应该越高。 6 | 7 | 本实验试图沿着类似的思路,通过计量模型估计股票未来大涨或大跌的概率,然后检验其在A 股市场上的选股能力。 8 | 9 | 估计未来一段时间股票大涨或大跌的概率并以此作为选股因子。考虑到常见的选股因子一般用于月度调仓,因此我们选定的预测期为未来一个月。股票大涨或大跌的阈值分别设为15%、20%、25%、30%、35%至40%。以15%阈值为例,1m 代表1 个月,15 代表阈值,如果未来1 个月股票跌幅超过15%,则类别为-1,相应的概率为Crashp1m15;如果未来1 个月股票收益率在正负15%之间,则类别为0,相应的概率为P1m15;如果未来1 个月股票涨幅超过15%,则类别为1,相应的概率为Jackpotp1m15。 10 | 11 | 12 | 13 | ## 数据构造 14 | 15 | 9个特征值如下: 16 | 17 | | **RM12** | **市场(Wind 全A 指数)过去12 个月的收益率** | 18 | | ----------- | ----------------------------------------------------------- | 19 | | **EXRET12** | **个股过去12 个月的超额收益率** | 20 | | **TVOL** | **近半年的日收益率标准差** | 21 | | **TSKEW** | **近半年的日收益率偏度** | 22 | | **SIZE** | **ln(流通市值)** | 23 | | **DTURN** | **个股近6 个月的月换手率均值- 个股近18 个月的月换手率均值** | 24 | | **AGE** | **股票上市年数** | 25 | | **SALESG** | **销售收入增长率** | 26 | | **EX_PE** | **个股PE_ttm 与行业PE_ttm 的差** | 27 | 28 | 29 | 30 | ## 预测信息 31 | 32 | 33 | 34 | | 数据时间: | 2007年10月-2018年8月 以200701为样本起点(保持不变),从200901开始计算因子值,逐月拓展样本窗口 | 35 | | ---------------- | ------------------------------------------------------------ | 36 | | **缺失值处理:** | **按照行业均值填充** | 37 | | **数据标准化:** | **基于原始数据的均值(mean)和标准差(standard deviation)** | 38 | | **预测模型:** | **LR(逻辑回归)** | 39 | 40 | | 预测滚动周期: | 月频数据:根据前12个月的数据值预测后一个月的值,前24个月预测后一个月 | 41 | | -------------- | :----------------------------------------------------------- | 42 | | | **周频数据:根据前48周的数据值预测后一周的数据** | 43 | 44 | ![数据构造](https://github.com/Miya-Su/Quantitative-Trading/raw/miya/image/基于股价大幅波动的另类选股因子研究01.png) -------------------------------------------------------------------------------- /code/神经网络初步搭建测试/README.md: -------------------------------------------------------------------------------- 1 | # 处理流程 2 | 3 | **目标:使用Tesosrflow搭建神经网络模型进行二分类预测** 4 | 5 | ****此部分主要为测试,存在很多问题,主要集中在神经层的建立,需要进一步学习。 6 | 7 | 初步测试:构建3层神经网络 8 | 9 | 存在问题: 10 | 11 | - 神经层数搭建?搭建多少层? 12 | 13 | - 神经元个数选择? 14 | 15 | - 激活函数选择?隐藏层的激活函数如何选择?输出层的激活函数如何选择? 16 | 17 | - 希望得到二分类的概率值,输出层激活函数选择softmax时存在问题,测试中使用sigmoid函数 18 | 19 | 20 | 21 | 22 | ## 搭建步骤 23 | 24 | 1.训练数据 25 | 2.定义节点准备接收数据 26 | 3.定义神经层:隐藏层和预测层 27 | 4.定义 loss 表达式 28 | 5.选择 optimizer 使 loss 达到最小 29 | 30 | 对所有变量进行初始化,通过 sess.run optimizer,迭代 500 次进行学习 31 | 32 | 33 | 34 | # 神经层搭建 35 | 36 | 1. 初步搭建:三层神经网络测试 37 | 38 | - 输入层 39 | - 3个隐藏层:激活函数:relu 40 | - 输出层:sigmoid函数 41 | 42 | 2. 优化函数:AdamOptimizer算法作为优化函数,来保证预测值与实际值之间交叉熵最小 43 | 44 | 3. 学习速率:0.01 45 | 46 | 4. 神经元个数 47 | 48 | | | 激活函数?? | 神经元个数?? | 49 | | ------ | ------------ | -------------- | 50 | | 第一层 | relu | 30 | 51 | | 第二层 | relu | 20 | 52 | | 第三层 | relu | 20 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | # 数据构建 60 | 61 | 62 | 63 | | **特征值:** | **选取['mom','emotion', 'pricevol', 'minute', 'finance', 'valuation', 'alpha191','growth'] 八大类因子组合构成特征值** | 64 | | ---------------- | ------------------------------------------------------------ | 65 | | **分类标签值:** | **按照股票涨跌幅排序,收益前T%标记为1,其余为0** | 66 | | **数据时间:** | **2009年10月-2018年8月** | 67 | | **缺失值处理:** | **按照行业均值填充** | 68 | | **数据标准化:** | **基于原始数据的均值(mean)和标准差(standard deviation)** | 69 | | **数据集:** | **周频:1094178 rows × 161 columns** | 70 | 71 | | | | 72 | | ------------------ | ------------------------------------------------ | 73 | | **预测滚动周期:** | **周频数据:根据前48周的数据值预测后一周的数据** | 74 | 75 | 76 | 77 | 78 | 79 | -------------------------------------------------------------------------------- /code/神经网络初步搭建测试/Tensorflow_Test.ipynb: -------------------------------------------------------------------------------- 1 | { 2 | "cells": [ 3 | { 4 | "cell_type": "code", 5 | "execution_count": null, 6 | "metadata": { 7 | "collapsed": true 8 | }, 9 | "outputs": [], 10 | "source": [ 11 | "import tensorflow as tf\n", 12 | "import numpy as np\n", 13 | "import matplotlib.pyplot as plt\n", 14 | "import pandas as pd\n", 15 | "\n", 16 | "import datetime as dt\n", 17 | "import daolib.dao as dao\n", 18 | "import daolib.dso as dso\n", 19 | "import util.sectool as sectool\n", 20 | "import util.operatetool as optool\n", 21 | "import matplotlib.pyplot as plt\n", 22 | "import pickle\n", 23 | "import time\n", 24 | "import os\n", 25 | "%matplotlib inline\n", 26 | "from tqdm import tqdm" 27 | ] 28 | }, 29 | { 30 | "cell_type": "markdown", 31 | "metadata": { 32 | "collapsed": true 33 | }, 34 | "source": [ 35 | "简单dnn网络构建测试\n", 36 | "\n", 37 | "数据:['mom','emotion', 'pricevol', 'minute', 'finance', 'valuation', 'alpha191','growth'] 八大类因子组合测试(共计158个因子+1个标签值)" 38 | ] 39 | }, 40 | { 41 | "cell_type": "markdown", 42 | "metadata": {}, 43 | "source": [ 44 | "## 数据读取" 45 | ] 46 | }, 47 | { 48 | "cell_type": "code", 49 | "execution_count": null, 50 | "metadata": { 51 | "collapsed": true 52 | }, 53 | "outputs": [], 54 | "source": [ 55 | "alpha191=readdir('D:\\Data\\\\factor_alpha\\\\alpha191' )\n", 56 | "finance=readdir('D:\\Data\\\\factor_alpha\\\\finance' )\n", 57 | "growth=readdir('D:\\Data\\\\factor_alpha\\\\growth' )\n", 58 | "minute=readdir('D:\\Data\\\\factor_alpha\\\\minute' )\n", 59 | "pricevol=readdir('D:\\Data\\\\factor_alpha\\\\pricevol' )\n", 60 | "valuation=readdir('D:\\Data\\\\factor_alpha\\\\valuation' )\n", 61 | "emotion=readdir('D:\\Data\\\\factor_alpha\\\\emotion' )\n", 62 | "mom=readdir('D:\\Data\\\\factor_alpha\\\\mom' )\n", 63 | "\n", 64 | "stock_price_df = dao.get_security_info('stock_price_info')\n", 65 | "all_stock_list = stock_price_df.index.get_level_values(0).drop_duplicates().tolist()\n", 66 | "\n", 67 | "#股票上市状态(只选择为0的值,不为0的值为异常值)\n", 68 | "price_df=dao.get_security_info('stock_price_info')\n", 69 | "trade_status_df=price_df.xs('trade_status',level=1)\n", 70 | "\n", 71 | "start_date = dt.datetime(2007, 1, 1)\n", 72 | "end_date = dt.datetime(2018,10,1)" 73 | ] 74 | }, 75 | { 76 | "cell_type": "code", 77 | "execution_count": null, 78 | "metadata": { 79 | "collapsed": true 80 | }, 81 | "outputs": [], 82 | "source": [ 83 | "factor_name_list = ['mom','emotion', 'pricevol', 'minute', 'finance', 'valuation', 'alpha191','growth'] \n", 84 | "\n", 85 | "#周频数据\n", 86 | "trade_date_w_series = pd.Series( dso.get_trade_date(start_date=start_date, end_date=end_date, period='w') )\n", 87 | "week_list = [date for date in trade_date_w_series if dt.datetime(2009,10,20)= ind_stock_num:\n", 631 | " xx = ind_stock_series.head(ind_stock_num)\n", 632 | " temp_series = xx / xx.sum() * bench_ind_weight_series[industry_name]\n", 633 | " else:\n", 634 | " temp_series = ind_stock_series / ind_stock_series.sum() * bench_ind_weight_series[industry_name]\n", 635 | "\n", 636 | " temp_series = pd.Series(index=ind_stock_series.index[:ind_stock_num], data=1.0 / ind_stock_num) * \\\n", 637 | " bench_ind_weight_series[industry_name]\n", 638 | " port_series = port_series.append(temp_series)\n", 639 | " return port_series" 640 | ] 641 | } 642 | ], 643 | "metadata": { 644 | "kernelspec": { 645 | "display_name": "Python 3", 646 | "language": "python", 647 | "name": "python3" 648 | }, 649 | "language_info": { 650 | "codemirror_mode": { 651 | "name": "ipython", 652 | "version": 3 653 | }, 654 | "file_extension": ".py", 655 | "mimetype": "text/x-python", 656 | "name": "python", 657 | "nbconvert_exporter": "python", 658 | "pygments_lexer": "ipython3", 659 | "version": "3.6.1" 660 | } 661 | }, 662 | "nbformat": 4, 663 | "nbformat_minor": 2 664 | } 665 | -------------------------------------------------------------------------------- /code/风险因子测试/README.md: -------------------------------------------------------------------------------- 1 | ## 处理流程 2 | 3 | **此部分的目标是:根据10个风险因子进行股价涨跌幅的分类预测,完成概率因子的测试。** 4 | 5 | 10Risk_Factor_Test:10个风险因子的分类概率测试 6 | 7 | 4Risk_Factor_Test:从10个风险因子中选取4个显著风险因子完成概率测试(选取方式为:随机森林特征排序/lightgbm特征排序) 8 | 9 | 10 | 11 | 预测的方案分为分类 12 | 13 | 1. 第一种三分类划分:按照股票涨跌幅排序,收益前30%标记为1, 后30%标记为-1,其余为0 14 | 2. 第二种两分类划分:按照股票涨跌幅排序,收益前30%标记为1, 其余为0 15 | 16 | | 分类标签值: | 1.按照股票涨跌幅排序,收益前30%标记为1, 后30%标记为-1,其余为0 | 17 | | ---------------- | ------------------------------------------------------------ | 18 | | | **2.按照股票涨跌幅排序,收益前30%标记为1,其余为0** | 19 | | **回归标签值:** | **股票涨跌幅的具体数值 ** | 20 | 21 | 22 | 23 | # **数据构建** 24 | 25 | | **特征值:** | 一**共选取10个风险因子** | 26 | | ---------------- | ------------------------------------------------------------ | 27 | | **分类标签值:** | **1.按照股票涨跌幅排序,收益前30%标记为1, 后30%标记为-1,其余为0** | 28 | | | **2.按照股票涨跌幅排序,收益前30%标记为1,其余为0** | 29 | | **回归标签值:** | **股票涨跌幅的具体数值** | 30 | | **数据时间:** | **2009年10月-2018年8月** | 31 | | **缺失值处理:** | **按照行业均值填充** | 32 | | **数据标准化:** | **基于原始数据的均值(mean)和标准差(standard deviation)** | 33 | | **训练集:** | **`月频:67180 周频:290294 `** | 34 | | **测试集:** | **`月频:118998 周频:500736**` | 35 | 36 | | 预测滚动周期: | 月频数据:根据前12个月的数据值预测后一个月的值,前24个月预测后一个月 | 37 | | -------------- | :----------------------------------------------------------- | 38 | | | **周频数据:根据前48周的数据值预测后一周的数据** | 39 | 40 | 41 | 42 | ## 预测模型 43 | 44 | 预测分为两种,单个模型预测和集成模型预测,集成模型预测分为两种,一种是简单的平均集成,一种是Meta_Stacking的元模型预测 45 | 46 | | 单个模型预测 | | 47 | | ---------------- | ----------------- | 48 | | **集成模型预测** | **简单平均集成** | 49 | | | **Meta_Stacking** | 50 | 51 | 分类模型:xgb,lgb,RF,GBoost 52 | 53 | 回归模型:lasso,ENet,KRR,GBoost,xgb,lgb 54 | 55 | 56 | 57 | ## 因子处理 58 | 59 | 因子测试阶段分为两种。 60 | 61 | 因子中性化处理:为了在用某一因子时能够剔除其他因素的影响,使得选出的股票更加分散,需要进行中性化处理。(即:为了消除因子中的偏差和不必要的影响) 62 | 63 | 对于因子来说,中性化主要考虑市场风险和行业风险。 64 | 65 | 行业中性:多头组合的行业配置与对冲基准的行业配置一致,目的在于剔除行业因子对策略收益的影响,仅考察行业内部个股的超额收益。(行业中性策略的净值曲线往往比较平稳,回测较小) 66 | 67 | 风格因子中性:多头组合的风格因子较之对冲基准的风险暴露为0,目的在于使多头组合的风格特征完全与对冲基准相匹配,使得组合的超额收益不是来自于某类风格 68 | 69 | | 目的: | 为了在用某一因子时能够剔除其他因素的影响,使得选出的股票更加分散,需要进行中性 化处理。(即:为了消除因子中的偏差和不必要的影响) | 70 | | :------------- | :----------------------------------------------------------- | 71 | | **主要考虑:** | **市场风险和行业风险** | 72 | | **处理方式:** | **利用回归,得到一个与风险因子线性无关的因子,即通过线性回归提取残差作为中性化后的因子。(处理完成后的中性化因子与风险因子之间的相关性严格为0)** | 73 | 74 | | **因子测试** | **第一种直接选取前100只股票,等权分配** | 75 | | ------------ | :----------------------------------------------------------- | 76 | | | **第二种选择前100只股票,根据行业基准权重进行不等权配置(每个行业至少要有1只股票)** | 77 | 78 | -------------------------------------------------------------------------------- /data/116_Factor_Test/116Mfactor1_lgb3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/data/116_Factor_Test/116Mfactor1_lgb3 -------------------------------------------------------------------------------- /data/116_Factor_Test/116Mfactor1_lgb4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/data/116_Factor_Test/116Mfactor1_lgb4 -------------------------------------------------------------------------------- /data/116_Factor_Test/116Mfactor1_xgb3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/data/116_Factor_Test/116Mfactor1_xgb3 -------------------------------------------------------------------------------- /data/116_Factor_Test/116Mfactor1_xgb4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/data/116_Factor_Test/116Mfactor1_xgb4 -------------------------------------------------------------------------------- /data/116_Factor_Test/116Wfactor1_lgb3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/data/116_Factor_Test/116Wfactor1_lgb3 -------------------------------------------------------------------------------- /data/116_Factor_Test/116Wfactor1_lgb4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/data/116_Factor_Test/116Wfactor1_lgb4 -------------------------------------------------------------------------------- /data/116_Factor_Test/116Wfactor1_xgb3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/data/116_Factor_Test/116Wfactor1_xgb3 -------------------------------------------------------------------------------- /data/116_Factor_Test/116Wfactor1_xgb4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/data/116_Factor_Test/116Wfactor1_xgb4 -------------------------------------------------------------------------------- /data/158_Factor_Test/158Wfactor1_lgb3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/data/158_Factor_Test/158Wfactor1_lgb3 -------------------------------------------------------------------------------- /data/158_Factor_Test/158Wfactor1_lgb4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/data/158_Factor_Test/158Wfactor1_lgb4 -------------------------------------------------------------------------------- /data/191_Factor_Test/191Alpha+10Risk/191Wfactor1_Rlgb3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/data/191_Factor_Test/191Alpha+10Risk/191Wfactor1_Rlgb3 -------------------------------------------------------------------------------- /data/191_Factor_Test/191Alpha+10Risk/191Wfactor1_Rlgb4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/data/191_Factor_Test/191Alpha+10Risk/191Wfactor1_Rlgb4 -------------------------------------------------------------------------------- /data/191_Factor_Test/191Alpha+10Risk/191Wfactor1_Rxgb4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/data/191_Factor_Test/191Alpha+10Risk/191Wfactor1_Rxgb4 -------------------------------------------------------------------------------- /data/191_Factor_Test/191Alpha/191Wfactor1_lgb3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/data/191_Factor_Test/191Alpha/191Wfactor1_lgb3 -------------------------------------------------------------------------------- /data/191_Factor_Test/191Alpha/191Wfactor1_lgb4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/data/191_Factor_Test/191Alpha/191Wfactor1_lgb4 -------------------------------------------------------------------------------- /data/191_Factor_Test/191Alpha/191Wfactor1_xgb3: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/data/191_Factor_Test/191Alpha/191Wfactor1_xgb3 -------------------------------------------------------------------------------- /data/191_Factor_Test/191Alpha/191Wfactor1_xgb4: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/data/191_Factor_Test/191Alpha/191Wfactor1_xgb4 -------------------------------------------------------------------------------- /data/数据说明.md: -------------------------------------------------------------------------------- 1 | # 数据说明 2 | 3 | 数据为测试的分类预测概率因子 4 | 5 | 一共14个因子数据,分别对应三组测试数据:116_Factor_Test 、191_Factor_Test、158_Factor_Test 6 | 7 | (其中191_Factor_Test包含两种测试数据:191Alpha和191Alpha+10Risk,分别对应192个Alpha组合因子测试和192个Alpha加上10个风险因子组成的202因子组合测试) 8 | 9 | 10 | 11 | | 周频数据 | Lable | 116_Factor_Test | 191_Factor_Test | 158_Factor_Test | 12 | | ------------ | :---- | ---------------- | ---------------- | ---------------- | 13 | | LIGHTGBM | 30% | 116Wfactor1_lgb3 | 191Wfactor1_lgb3 | 158Wfactor1_lgb3 | 14 | | | 40% | 116Wfactor1_lgb4 | 191Wfactor1_lgb4 | 158Wfactor1_lgb4 | 15 | | XGBOOST | 30% | 116Wfactor1_xgb3 | 191Wfactor1_xgb3 | | 16 | | | 40% | 116Wfactor1_xgb | 191Wfactor1_xgb4 | | 17 | | **月频数据** | | | | | 18 | | LIGHTGBM | 30% | 116Mfactor1_lgb3 | | | 19 | | | 40% | 116Mfactor1_lgb4 | | | 20 | | XGBOOST | 30% | 116Mfactor1_xgb3 | | | 21 | | | 40% | 116Mfactor1_xgb4 | | | 22 | 23 | 24 | 25 | ## 116_Factor_Test 26 | 27 | 1. 月频因子数据 28 | 29 | - 使用LIGHTGBM预测结果 30 | 31 | 116Mfactor1_lgb3 :按照涨跌幅前30%进行2分类划分 32 | 33 | 116Mfactor1_lgb4 :按照涨跌幅前40%进行2分类划分 34 | 35 | - 使用XGBOOST预测 36 | 37 | 116Mfactor1_xgb3 :按照涨跌幅前30%进行2分类划分 38 | 39 | 116Mfactor1_xgb4:按照涨跌幅前40%进行2分类划分 40 | 41 | 2. 周频因子数据 42 | 43 | - 使用LIGHTGBM预测结果 44 | 45 | 116Wfactor1_lgb3 :按照涨跌幅前30%进行2分类划分 46 | 47 | 116Wfactor1_lgb4:按照涨跌幅前40%进行2分类划分 48 | 49 | - 使用XGBOOST预测结果 50 | 51 | 116Wfactor1_xgb3 :按照涨跌幅前30%进行2分类划分 52 | 53 | 116Wfactor1_xgb4 :按照涨跌幅前40%进行2分类划分 54 | 55 | 56 | 57 | 58 | 59 | ## 191_Factor_Test 60 | 61 | 周频因子数据 62 | 63 | - 使用LIGHTGBM预测结果 64 | 65 | 191Wfactor1_lgb3 :按照涨跌幅前30%进行2分类划分 66 | 67 | 191Wfactor1_lgb4:按照涨跌幅前40%进行2分类划分 68 | 69 | - 使用XGBOOST预测结果 70 | 71 | 191Wfactor1_xgb3 :按照涨跌幅前30%进行2分类划分 72 | 73 | 191Wfactor1_xgb4 :按照涨跌幅前40%进行2分类划分 74 | 75 | -------------------------------------------------------------------------------- /image/代码说明01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/image/代码说明01.png -------------------------------------------------------------------------------- /image/代码说明02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/image/代码说明02.png -------------------------------------------------------------------------------- /image/代码说明03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/image/代码说明03.png -------------------------------------------------------------------------------- /image/代码说明04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/image/代码说明04.png -------------------------------------------------------------------------------- /image/基于股价大幅波动的另类选股因子研究01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/image/基于股价大幅波动的另类选股因子研究01.png -------------------------------------------------------------------------------- /image/多因子模型01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/image/多因子模型01.png -------------------------------------------------------------------------------- /image/多因子模型02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/image/多因子模型02.png -------------------------------------------------------------------------------- /image/多因子模型03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/image/多因子模型03.png -------------------------------------------------------------------------------- /image/多因子模型04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/image/多因子模型04.png -------------------------------------------------------------------------------- /image/实习总结.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/image/实习总结.png -------------------------------------------------------------------------------- /image/量化基础知识01.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/image/量化基础知识01.png -------------------------------------------------------------------------------- /image/量化基础知识02.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/image/量化基础知识02.png -------------------------------------------------------------------------------- /image/量化基础知识03.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/image/量化基础知识03.png -------------------------------------------------------------------------------- /image/量化基础知识04.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/image/量化基础知识04.png -------------------------------------------------------------------------------- /image/量化基础知识05.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/image/量化基础知识05.png -------------------------------------------------------------------------------- /image/量化基础知识06.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/image/量化基础知识06.png -------------------------------------------------------------------------------- /image/量化基础知识07.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/image/量化基础知识07.png -------------------------------------------------------------------------------- /image/量化基础知识08.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/image/量化基础知识08.png -------------------------------------------------------------------------------- /notebook/1.量化基础知识总结.md: -------------------------------------------------------------------------------- 1 | # 学习方法 2 | 3 | 4 | 5 | 1.网上学习平台:聚宽、优矿、米矿 6 | 7 | 8 | 9 | 2.多因子模型阅读资料(参见research文件夹): 10 | 11 | 《20160523-长江证券-多因子模型系列报告之一:模型理论随想和纯因子组合构建》(优先阅读) 12 | 13 | 《20161026-长江证券-多因子模型系列报告之三:利用纯因子组合进行因子投资》 14 | 15 | 《20160219-东方证券-《因子选股系列研究之六》:用组合优化构建更精确多样的投资组合》 16 | 17 | 《20160812-东方证券-《因子选股系列研究之十》:Alpha因子库精简与优化》 18 | 19 | 《20180301-东方证券-因子选股系列研究之三十五:组合优化的若干问题》 20 | 21 | 《20150426-国泰君安-数量化专题之五十七:基于组合权重优化的风格中性多因子选股策略》 22 | 23 | 《17_A股市场风险分析——《因子选股系列研究之十七》》 24 | 25 | 《21_组合优化是与非——因子选股系列研究之二十一》 26 | 27 | 《Barra China Equity Model Descriptor details》 28 | 29 | 《Barra China Equity Model》 30 | 31 | 《fama_common risk factors in the returns on stock and bonds》 32 | 33 | 《Fama-MacBeth-1973-Risk--return--and-equilibrium-empirical-tests》 34 | 35 | 《The Cross-Section of expected stock return》 36 | 37 | 38 | 39 | 40 | 41 | # 基本模型 42 | 43 | 不论Barra还是CAMP 和Fama-French,都只是收益的解释模型,并不包含任何预测信息,要预测未来的股票收益,就需要知道未来的因子收益,从未来到未来,模型本身并不提供预测。 44 | 45 | 46 | 47 | 模型的作用: 48 | 49 | 1. 事后对取得的收益做分解和评价,毕竟如果不知道收益从何处而来,也会不知道 今后收益为何而去; 50 | 51 | 2. 降维的作用,从预测 n 只股票到只需预测m个因子的收益 52 | 53 | 3. 找到合适的因子,考察因子的对应的纯因子组合的收益序列,避免了简单排序导 致对其他因子的暴露,更能反映该因子的历史收益情况。 54 | 55 | 56 | ![量化基础知识01](https://github.com/Miya-Su/Quantitative-Trading/raw/miya/image/量化基础知识01.png) 57 | 58 | 59 | 60 | 根据现代金融理论的定义,投资组合获取的收益均可以分为两个部分,一部分是来自市场的收益也就是𝐵𝑒𝑡𝑎,另一部分则是超出市场的收益也就是我们常说的𝐴𝑙𝑝ℎ𝑎。 61 | 62 | 如何准确的定义和寻找股票市场中的𝐴𝑙𝑝ℎ𝑎一直是学术界和业 界不断探索的问题,已有的模型包括资本资产定价模型 CAPM 和APT、 Fama-French 三因素模型等,而多因子模型正是基于套利定价理论(APT) 而建立的更为完善的定价模型。 63 | 64 | 65 | 66 | ## CAMP 67 | 68 | 资本资产定价模型(CAPM)由威廉·夏普等人于 1964 年提出,CAPM 模 型是在资产组合理论的基础上发展起来的: 69 | $$ 70 | 𝐸(𝑟_𝑝) = 𝑟_𝐹 +𝛽_𝑝 ∗(𝑟_𝑀 −𝑟_𝐹) 71 | $$ 72 | 其中,$𝑟_𝑝$代表资产 p 的收益率,$𝑟_𝐹$代表无风险收益率,$𝑟_𝑀$代表市场基准收益 率。 73 | 74 | 在 CAPM 模型的定义下,资产的收益率只与𝛽𝑝有关,这里的𝛽𝑝则定义为: 75 | $$ 76 | 𝛽_𝑝 = 𝐶𝑜𝑣(𝑟_𝑝,𝑟_𝑀) 𝑉𝑎𝑟(𝑟_𝑀) 77 | $$ 78 | 即资产收益率与市场组合收益率之间的协方差除以市场组合收益率方差,因此我们可以将 CAPM 模型看作以市场组合为因子的单因子 模型。 79 | 80 | 81 | 82 | ## APT 83 | 84 | 套利定价模型,是一种资产价格的估值模型,是[资本资产定价模型](https://baike.baidu.com/item/%E8%B5%84%E6%9C%AC%E8%B5%84%E4%BA%A7%E5%AE%9A%E4%BB%B7%E6%A8%A1%E5%9E%8B/10867338)(CAPM)的替代理论。虽然被称作套利定价模型,但实际与套利交易无关,是适用于所有资产的估值模型,其理论基础是一项资产的价格是由不同因素驱动,将这些因素乘上该因素对资产价格影响的[贝塔](https://baike.baidu.com/item/%E8%B4%9D%E5%A1%94)系数,加总后,再加上[无风险收益率](https://baike.baidu.com/item/%E6%97%A0%E9%A3%8E%E9%99%A9%E6%94%B6%E7%9B%8A%E7%8E%87),就可以得出该项资产的价值。 85 | 86 | ### 套利 87 | 88 | 套利也叫价差交易,套利指的是在买入或卖出某种电子交易合约的同时,卖出或买入相关的另一种合约。 89 | 90 | 套利交易是指利用相关市场或相关电子合同之间的价差变化,在相关市场或相关电子合同上进行交易方向相反的交易,以期望价差发生变化而获利的交易行为。 91 | 92 | 由于套利的存在,即两个约当物品或证券的价格不一致时,必然发生高价卖出,同时低价买入的行为,最终使约当物品或证券的价格相同而达于均衡。罗斯根据这一原理,导出在无套利的价格均衡情况下应有的投资组合。 93 | 94 | | 套利 | 无套利 | 95 | | ------------------------------------------------------------ | ------------------------------------------------------------ | 96 | | 存在一个交易策略,满足以下4个条件: 1)不需要任何投入,自我融资(self-financing) *l**w**A* = 0  2)对所有因素风险完全免疫*B**w**A* = 0 3)对所有非因素风险完全免疫 4)当资产数目足够多时,期末可以获得无风险收益 | 在[市场均衡](https://baike.baidu.com/item/%E5%B8%82%E5%9C%BA%E5%9D%87%E8%A1%A1)时刻,不存在任何套利机会 | 97 | 98 | ### APT原理 99 | 100 | 套利价格理论APT模型是由A·罗斯首创的一种决定资产价格的均衡模型,用来研究证券价格是如何决定的。 101 | 102 | 它假设证券的收益是由一系列产业方面和市场方面的因素确定的。当两种证券的收益受到某种或某些因素的影响时,两种证券收益之间就存在相关性。 103 | 104 | 套利定价理论的基本机制是:在给定资产收益率计算公式的条件下,根据套利原理推导出资产的价格和均衡关系式。 105 | 106 | 该套利价格理论隐含如下几项假设:①影响证券收益率的因素不止一个,而是m个有限因素; ②资本市场是完全竞争市场; ③实行多元化组合投资,可消除只影响单一证券的非系统风险; ④投资者属于风险规避类型。 107 | 108 | 套利定价理论(APT)则为多因子模型提供了理论基础,APT 模型用多个因子来解释资产收益,并且根据无套利原则,得到风险资产均衡收益与多个因 子之间存在近似线性关系,从而将影响资产收益的因子从 CAPM 的单因子或 Fama-French 的三因子拓展到多个因子,也就为多因子模型的发展奠定了基础。 109 | 110 | 111 | 112 | ### APT和CAPM 113 | 114 | 1.套利定价理论APT(Arbitrage Pricing Theory) 是[CAPM](https://baike.baidu.com/item/CAPM)的拓广,由APT给出的定价模型与CAPM一样,都是均衡状态下的模型,不同的是APT的基础是因素模型。 115 | 116 | 2.APT没有给出都是哪些因素驱动资产价格,这些因素可能数量众多,只能凭投资者经验自行判断选择,此外每项因素都要计算相应的[贝塔值](https://baike.baidu.com/item/%E8%B4%9D%E5%A1%94%E5%80%BC),而CAPM模型只需计算一个贝塔值,所以在对资产价格估值的实际应用时,CAPM比APT使用地更广泛。 117 | 118 | 3.APT中,资本资产的收益率(也就是期望风险溢价)是GDP增长、通货膨胀水平等各种因素综合作用的结果,并不仅仅受Rm-Rf的影响,也就是说APT是多因素的。 119 | 120 | 4.APT与CAPM的另一个主要区别就是假设不同:CAPM的假设是马科维茨,主要是最优投资组合和市场均衡,而APT的是因子模型与市场无套利,假设数量相对较少。 121 | 122 | 5.CAPM是从投资者如何构建有效投资组合的分析开始的,但APT却不再分析投资组合是否有效,而是假设每只股票的收益受两种影响:第一种是宏观经济形势的影响,或者说是一些因子(factors),而第二种是与公司相关的独特事件的影响,也就是噪音(noise)。APT则套用风险资产的预期收益率和各宏观经济因素的风险溢价。套利者使用APT模型,利用证券的错误定价从中取利。当证券出现错误定价,其价格将异于从理论模式预测出来的价格。 123 | 124 | 125 | 126 | ## MFM 127 | 128 | 基于 APT 理论的多因子模型(MFM) 。 129 | 股票二级市场的多因子模型也同样可以理解为将N只股票的收益率分解为M 个因子的线性组合与未被因子解释的残差项。影响股票收益率的因素主要来 自某一只股票相对于某一个因子的敏感度或因子暴露(factor loading),这 里的因子暴露即相当于 CAPM 中的𝛽𝑝。 130 | 131 | 相比较 CAPM 和 Fama-French 等模型,多因子模型的优势在于它可以提供 更为完整的风险暴露分析,并且分离出每个因子的影响,从而为投资决策提供 更为局部和细致的分析。 132 | 133 | 多因子定价模型(Multifactor Pricing Model)是CAPM与APT之后的延伸,是指APT后有具体因子出现的定价模型。FF的三因子五因子就是多因子模型中的代表。 134 | 135 | 136 | 137 | ## Fama-French 三因子 138 | 139 | 但随着业界对股票市场研究的深入,CAPM 这样的单一因子模型已经无法很好的解释资产收益的来源。例如,Fama/French1在 1992 年提出 PB 和市值 因子对股票的收益率有十分显著的影响,并且基于这个发现建立了 Fama-French 三因素模型。 140 | 141 | Fama French三因子模型是对CAPM模型的一个扩展。 142 | 143 | CAPM模型认为: 144 | 145 | (1)证券资产的预期收益和它的市场Beta之间存在一个正向的线性关系,Beta越大,资产的预期收益越大;(2)市场Beta足以解释证券资产的预期收益。 146 | 147 | 在CAPM的基础上增加了两个因子:规模因子SMB(size factor,也称市值因子)和账面市值比因子HML(book-to-market factor,也称价值因子)。他们认为,市场因子再加上这两个因子三者可以很好地持续地解释资产的平均收益。 148 | 149 | Fama和French 1993年指出可以建立一个三因子模型来解释股票[回报率](https://baike.baidu.com/item/%E5%9B%9E%E6%8A%A5%E7%8E%87)。模型认为,一个[投资组合](https://baike.baidu.com/item/%E6%8A%95%E8%B5%84%E7%BB%84%E5%90%88)(包括单个股票)的超额回报率可由它对三个因子的暴露来解释,这三个因子是:市场资产组合(*Rm*− *Rf*)、市值因子(SMB)、账面市值比因子(HML)。这个多因子均衡定价模型可以表示为: 150 | $$ 151 | E(Rit) −Rft= βi[E(Rmt−Rft)] +siE(SMBt) +hiE(HMIt) 152 | $$ 153 | 其中*Rft*表示时间t的[无风险收益率](https://baike.baidu.com/item/%E6%97%A0%E9%A3%8E%E9%99%A9%E6%94%B6%E7%9B%8A%E7%8E%87);*Rmt*表示时间t的[市场收益率](https://baike.baidu.com/item/%E5%B8%82%E5%9C%BA%E6%94%B6%E7%9B%8A%E7%8E%87);*Rit*表示资产i在时间t的收益率;*E*(Rmt) − *Rft*是[市场风险](https://baike.baidu.com/item/%E5%B8%82%E5%9C%BA%E9%A3%8E%E9%99%A9)[溢价](https://baike.baidu.com/item/%E6%BA%A2%E4%BB%B7),*SMBt*为时间t的[市值](https://baike.baidu.com/item/%E5%B8%82%E5%80%BC)(Size)因子的模拟组合收益率(Small minus Big),*HMIt*为时间t的账面市值比(book—to—market)因子的模拟组合收益率(High minus Low)。 154 | 155 | β、*si*和*hi*分别是三个因子的系数,回归模型表示如下: 156 | $$ 157 | Rit− Rft= ai+ βi(Rmt− Rft) + siSMBt+ hiHMIt+ εit 158 | $$ 159 | 但是,我们应该看到,三因子模型并不代表资本定价模型的完结,在最近的研究发现,三因子模型中还有很多未被解释的部分,如短期反转、中期动量、波动、偏度、赌博等因素。 160 | 161 | 162 | 163 | ## Fama-French 五因子 164 | 165 | 如果三因子模型中的三个因子可以完全解释各种风险带来的超额收益,那么任何一个股票以及任何一个投资组合的αi的真实值应该为0。在过去20年里面,很多学者对三因子模型进行实证分析,发现有些股票的αi显著不为0,这说明三因子模型中的三个风险(因素)并不能解释所有超额收益。后来,Fama和French发现在上述风险之外,还有盈利水平风险、投资水平风险也能带来个股的超额收益,并于2013年提出了五因子模型。该模型更加充分地解释个股的超额收益,其表达式为: 166 | $$ 167 | 𝑅𝑖=𝑎𝑖+𝑏𝑖𝑅𝑀+𝑠𝑖𝐸(𝑆𝑀𝐵)+ℎ𝑖𝐸(𝐻𝑀𝐼)+𝑟𝑖𝐸(𝑅𝑀𝑊)+𝑐𝑖𝐸(𝐶𝑀𝐴)+𝑒𝑖 168 | $$ 169 | 从表达式看,五因子模型比三因子模型里面多出来了两项:E(RMW)是高/低盈利股票投资组合的回报之差,而E(CMA)则是低/高再投资比例公司股票投资组合的回报之差。这两项分别描述了盈利水平风险、投资水平风险(注意这里的投资水平不是二级市场的投资水平,而可以通俗的解释为企业扩大再生产的能力)。与三因子类似,参数估计的方法仍然是用多元线性回归的方法,这里的αi则是五因子模型里面尚未解释的超额收益。 170 | 171 | ## Barra模型 172 | 173 | ![量化基础知识08](https://github.com/Miya-Su/Quantitative-Trading/raw/miya/image/量化基础知识08.png) 174 | 175 | 这是基于 APT 建立的模型, 176 | 177 | 其中 $I_1,I_2.......I_p$ 为 p个行业因子(Industry), $f_I$$_1$, $f_I$$_2$ ..... $f_I$$_P$ 为对 应的因子收益; 178 | 179 | $S_1,S_2.........S_q$ 为 q个风格因子(Style), $f_s$$_1$, $f_s$$_2$ ..... $f_s$$_P$ 为对应的因子收益 180 | 181 | $X^I$$^P$ 为 行业因子暴露(0 或1), $X^S$$^P$为风格因子暴露。 182 | 183 | Barra一直致力于对结构化风险模型(协方差)的研究。 184 | 185 | Barra的方式不同之处在于,Barra的因 子收益$f_m$ 无法直接观察到,是通过在时间截面上回归得到的(后验) ,因子暴露度则是𝑓 𝑖 由基本面、技术面等因子的值计算截面z-score直接得到的; 而CAMP和Fama-French 中的因子收益不需要截面回归,可以直接观察到(多空组合、后验) ,但因子暴露度需要通过历史时间序列回归来估计。 186 | 187 | 188 | 189 | 190 | # 多因子模型MFM 191 | 192 | 理论上多因子模型应涵盖包含股票、债券、大宗商品、地产等所有资产,但我们的讨论仅局限在股票的二级市场。 193 | 194 | 195 | 196 | 作为量化选股多因子𝐴𝑙𝑝ℎ𝑎模型构建环节中最重要的一部分,如何寻找具有逻辑支撑且能有效区分和预测股票收益的因子是主要内容。 197 | 198 | ![量化基础知识02](https://github.com/Miya-Su/Quantitative-Trading/raw/miya/image/量化基础知识02.png) 199 | 200 | 201 | 202 | 大部分机构投资者主要研究Alpha模型,风险模型和组合优化采用外购商业软件(BARRA,Axioma等) 203 | 204 | 205 | 206 | 风险模型:任意股票同一时刻都暴露于多种不同的风险因素下,它们之间的共同作用形成了股票价格的波动,为了定量研究各种风险因素的作用,量化风险模型应运而生。 207 | 208 | 风险模型的意义在于找到股票价格波动的成因,并将股票收益来源进行剥离,并实行对未来股票波动价格的预测。 209 | 210 | Alpha因子:是对股票收益率具有明显显著且稳定影响的某一变量,同时该影响是剔除其余所有因子对收益的作用而独立存在的。 211 | 212 | “群众型”:更符合分散风险的量化投资基本原理,大型的Alpha因子库在提供多样的Alpha源的而同时,也带来了大量的无效和重复信息,会使得不同的Alpha源被人为的放大或缩小权重,最终影响组合表现。 213 | 214 | 对于一个新的因子,需要思考:是否提供了新的Alpha源?或只是把现有的因子库信息进行了切分重组? 215 | 216 | 217 | 218 | 对于因子相关性检验:IC协方差矩阵的估计(改进:压缩估计量、Boostrap方法) 219 | 220 | 221 | 222 | 223 | 224 | ## 量化投资 225 | 226 | 量化对冲策略目标:追求稳健的绝对收益,最优投资组合的构建是一种完美的平衡状态(充分暴露Alpha因子,同时剔除其余不稳定的风格因素干扰)。 227 | 228 | 市值中性、行业中性、风格中性的约束条件下的最优投资组合的构建。 229 | 230 | | 行业中性: | 多头组合的行业配置与对冲基准的行业配置一致,目的在于剔除行业因子对策略收益的影响,仅考察行业内部个股的超额收益(行业中性策略的净值曲线往往比较平稳,回测较小) | 231 | | ----------------: | ------------------------------------------------------------ | 232 | | **风格因子中性:** | **多头组合的风格因子较之对冲基准的风险暴露为0,目的在于使多头组合的风格特征完全与对冲基准相匹配,使得组合的超额收益不是来自于某类风格** | 233 | 234 | 235 | 236 | 多因子模型:决定策略收益稳健性的关键步骤在于股票组合的权重配置。(组合权重优化) 237 | 238 | 239 | 240 | ## 模型构建 241 | 242 | ![量化基础知识01](https://github.com/Miya-Su/Quantitative-Trading/raw/miya/image/量化基础知识07.png) 243 | 244 | 245 | 246 | ST: 特别处理(Special treatment) 247 | 248 | 交易所[《股票上市规则》规定,当上市公司出现财务状况异常或其他状况异常,投资者难以判断公司前景,自身权益可能受到损害时,交易所将对其股票交易实行特别处理(Special treatment),简称“ST”股票,其股票报价日涨跌幅限制在5%以内。特别处理不属于对上市公司的处罚,上市公司在特别处理期间的权利和义务不变。 249 | 250 | 251 | 252 | PT: 特别转让服务(Particular Transfer) 253 | 254 | 依据《公司法》第157条和《证券法》规定,上市公司发生股本总额,股权分布等变化不再具备上市条件的;不按规定公开其财务状况或对财务会计报告作虚假记载的;有重大违规行为的;连续三年亏损等四种情形之一时,其股票将暂停上市。暂停上市]期间,上市公司仍应依法履行有关义务。 对暂停上市的股票,交易所提供特别转让服务(Particular Transfer),简称PT股票。投资者可在交易所规定的时间(目前是每周五)申报该类股票特别转让委托。申报价格的涨幅不超过5%,不设跌幅限制。 255 | 256 | 257 | 258 | 新股与次新股是根据个股上市时间的早晚不同,将股票划分为新股和次新股,如市场上把2016年上市的股票称为新股,把2015年上市的股票称为次新股。 259 | 260 | 261 | 262 | 新股与次新股 263 | 264 | 依据个股上市时间早晚不同, 将股票区分为新股与次新股。例如, 截止2006年4月份, 市场把2006年上市的股票称为新股; 在2005年上市的股票称为次新股。“次新股”在股市里一般是个相对的说法,比新股(近几个交易周上市的股票)上市的时间要更早一些,但又比老股票(上市有三年以上时间的股票)要晚一些,严格意义上讲,其上市时间一般不会超过一年。 -------------------------------------------------------------------------------- /notebook/2.多因子模型构建.md: -------------------------------------------------------------------------------- 1 | # 基本知识 2 | 3 | 典型的股票多因子模型将 n 只股票的收益率分解为 m 个因子的线性组合和未被因子解释的残留部分,一般形式为 4 | 5 | ![多因子模型01](https://github.com/Miya-Su/Quantitative-Trading/raw/miya/image/多因子模型01.png) 6 | 7 | 8 | 9 | 10 | 11 | 其中,r_{i} 为对无风险收益率的超额部分, x_{ij}为股票i对因子的暴露度,f_{i}为因子收益\\(x_{ij}的名称有许多种,比如因子载荷、因子 beta、斜率、系数、因子敏感度等,此处及后文均采用Barra模型的语境,\\即因子暴露)。x_{ij}是随个股特征不同而变化的部分,而 f_{i}为共同部分(共同因子)。 12 | 13 | 向量形式: 14 | $$𝒓 = 𝒙_𝟏𝑓_1 +𝒙_𝟐𝑓_2 +⋯+𝒙_𝒎𝑓_𝑚 +𝒖$$ 15 | 16 | 17 | 18 | 矩阵形式: 19 | 20 | $$𝒓 = 𝑿_𝒇+𝒖$$ 21 | 22 | 其中: 23 | 24 | ![多因子模型02](https://github.com/Miya-Su/Quantitative-Trading/raw/miya/image/多因子模型02.png) 25 | 26 | 27 | 28 | ## 纯因子组合 29 | 30 | 通过纯因子组合的线性组合可以构造出对每个因子具有指定暴露度的组合。 31 | 32 | 纯因子组合可将各种风险收益精确的切割开来,求解出纯因子组合中的个股的权重,就可以精确控制组合对因子的暴露度,使组合只对希望暴露的风险因子暴露,从而让风险和收益精确匹配起来。 33 | 34 | 假设一个投资组合P中的个股权重为:$$w_P$$ 35 | 36 | 则这个投资组合的收益 $$r_p$$: 37 | 38 | $$𝑟_𝑃 = 𝒘_𝑷^ 𝑻𝒓 = 𝒘_𝑷^ 𝑻𝒙_𝟏𝑓_1 +𝒘_𝑷^ 𝑻𝒙_𝟐𝑓_2 +⋯+𝒘_𝑷^ 𝑻𝒙_𝒎𝑓_𝑚 +𝒘_𝑷^ 𝑻𝒖 = 𝑥_𝑃^ 1𝑓_1 +𝑥_𝑃^ 2𝑓_2 +⋯+𝑥_𝑃^ 𝑚𝑓_𝑚 +𝒘_𝑷^ 𝑻𝒖$$ 39 | 40 | 41 | 其中 $$𝑥_𝑃^ 𝑚𝑓_𝑚 =w_p^Tx_m=\sum w_ix_im$$ 就是组合P对因子m的因子暴露度。 42 | 43 | 44 | 一个投资组合的收益可以分解为 m个因子收益的线性组合: 45 | 46 | ![多因子模型03](https://github.com/Miya-Su/Quantitative-Trading/raw/miya/image/多因子模型03.png) 47 | 48 | 如果一个投资组合,对模型中某因子暴露度为 1,对其他风险因子暴露度为 0,则称该组合为这个因子的纯因子组合。 49 | 50 | 假设因子m对应的纯因子组合$P_M$的权重为 $W_P$$_m$ ,由定义,该组合对各个因子的暴露为 51 | 52 | $X^1_P$$_m$ =0 $X^2_P$$_m$ =0 ........ $X^m_P$$_m$ =0 , 53 | 54 | 因此纯因子组 合的收益为: 55 | 56 | ![多因子模型04](https://github.com/Miya-Su/Quantitative-Trading/raw/miya/image/多因子模型04.png) 57 | 58 | 可见,对于充分分散的组合,因子收益 $f_m$就是因子 对应的纯因子组合 $P_M$的收益。 至此,将 $f_m$ 称作是“收益”才有了很好的解释。通过广义最小二乘法(GLS)就可以 方便的求出 $f_m$的值,同时中间步骤还给出了该纯因子组合中个股的权重$W_P$$_m$ ,即 $f_m$= $W^T_P$$_m$ 59 | 60 | 61 | 62 | 63 | 64 | # 多因子模型构建 65 | 66 | 多因子模型是个较为复杂的体系,模型的构建流程往往包括以下几个方面: 67 | 68 | ![量化基础知识03](https://github.com/Miya-Su/Quantitative-Trading/raw/miya/image/量化基础知识03.png) 69 | 70 | 71 | 72 | ### 样本筛选 73 | 74 | 全体 A 股 ,为了使测试结果更符合投资逻辑,设定了三条样本筛选规则: 75 | 76 | (1) 剔除选股日的 ST/PT 股票; 77 | 78 | (2) 剔除上市不满一年的股票; 79 | 80 | (3) 剔除选股日由于停牌等原因而无法买入的股票。 81 | 82 | 83 | 84 | ### 数据清洗 85 | 86 | 避免可能的数据错误和极端数据对测试结果产生影响,使用标准化后的数据保证最终得到的模型的稳健性。数据清洗的内容主要包括两部分,异常值和缺失值的处理。 87 | 88 | 常见的因子标准化方法包括:Z 值标准化(Z-Score),Rank 标准化,风格 标准化等等。 由于 Rank 标准化后的数据会丢失原始样本的一些重要信息,这里我们仍然 选择 Z 值标准化来处理因子数据。 89 | 90 | 91 | 92 | 93 | 94 | ### 因子测试 95 | 96 | 有效的单因子首先应该具有一定的逻辑支撑,其次则是与股票收益率的相关性较为显著 97 | 98 | #### 单因子测试 99 | 100 | 截面回归(Cross-Section Regression)是目前业界较常用于因子测试的方法,相比全样本面板回归(Panel Data Regression)的方法,截面回归更有利于对因子变化趋势的捕捉。 101 | 102 | 我们选择每期针对全体样本做一次回归,回归时因子暴露为已知变量,回归 得到每期的一个因子收益值𝑓𝑗,在通过多期回归后我们就可以得到因子值𝑓𝑗 的序列,也就是因子收益率序列,同时可以得到 t 值序列,也就是因子值与 股票收益率相关性的t检验得到的t值。 103 | 104 | 针对这两个序列我们将通过以下几个指标来判断 该因子的有效性以及稳定性: 105 | 106 | (1) 因子收益序列𝑓𝑖的假设检验 t 值 107 | 108 | (2) 因子收益序列𝑓𝑖大于 0 的概率 109 | 110 | (3) t 值绝对值的均值 111 | 112 | (4) t 值绝对值大于等于 2 的概率 113 | 114 | IC 值(信息系数)是指个股第 t 期在因子 i 上的因子暴露(剔除行业与市值 后)与 t + 1 期的收益率的相关系数。通过计算 IC 值可以有效的观察到某个因子收益率预测的稳定性和动量特征,以便在优化组合时用作筛选的指标。 常见的计算 IC 值方法有两种:相关系数(Pearson Correlation) 和秩相关系数( Spearman Rank Correlation)。 115 | 116 | 由于 Pearson 相关系数计算时假设变量具有相等间隔以及服从正态分布,而 这一假设往往与因子值和股票收益率的分布情况相左。因此我们将采用 Spearman 的方法计算因子暴露与下期收益率的秩相关性 IC 值。类似回归法 的因子测试流程,我们在计算 IC 时同样考虑剔除了行业因素与市值因素。 117 | 118 | 同样我们会得到一个 IC 值序列,类似的,我们将关注以下几个与 IC 值相关 的指标来判断因子的有效性和预测能力: 119 | 120 | (1) IC 值的均值 121 | 122 | (2) IC 值的标准差 123 | 124 | (3) IC 大于 0 的比例 125 | 126 | (4) IC 绝对值大于 0.02 的比例 127 | 128 | (5) IR (IR = IC 均值/IC 标准差) 129 | 130 | #### 多因子测试 131 | 132 | 在完成单个因子的测试之后,就为多因子模型的构建打下了坚实的基础。我们可以通过下面几个步骤来剔除同类因子之间的多重共线性影响,筛选出同时具有良好的单调性和预测性的有效因子,构造我们的多因子模型: 133 | 134 | 根据上文的截面回归因子测试方法,我们可以轻松的得到每个因子的因子暴 露值序列和因子 IC 值序列。在研究因子间共线性时,就可以通过计算因子 间 IC 值和因子暴露值得相关性来求证因子间的共线性。 135 | 136 | 需要注意的是,经济含义相似度较高的同类型因子往往存在明显的正相关性, 在处理此类因子时,我们可以通过一些方法将因子进行合并;而如果是经济 含义差异较大因子之间存在明显相关性,就需要有所取舍。 137 | 138 | 消除共线性的方法包括以下几种: 139 | 140 | (1) 在同类因子的共线性较大的几个因子中,保留有效性最高的因子, 剔除余下的因子 141 | 142 | (2) 因子组合:方法包括等权加权,以因子收益 f 为权重加权,以及 PCA 主成分分析法等等 143 | 144 | (3) 暴力迭代法,即将因子两两组合暴力迭代得到表现最好的组合方法。 145 | 146 | 在对因子集做残差的异方差分析处理之后,就可以进行多元线性回归,估计每期的因子收益序列。 147 | 148 | ![量化基础知识04](https://github.com/Miya-Su/Quantitative-Trading/raw/miya/image/量化基础知识04.png) 149 | 150 | 151 | 152 | ### 因子的初步筛选 153 | 154 | 对每个因子做详尽的分析,具体测试了包括因子收益,因子收益显著性, 因子 IC、IR,分层回溯收益、多空收益,历史 IC 序列相关性等等指标,一般根据前期的测试结果,筛选出了收益率较显著,高 IC、IR 并且单调性得分较高的因子。 155 | 156 | 157 | 158 | ### 因子权重的优化—基于因子 IC 159 | 160 | 静态因子加权 v.s.动态调整权重 161 | 162 | #### 静态优化IC 163 | 164 | 复合因子是M 个因子的一个线形组合:因子的 IR 值为因子 IC 的均值与因子 IC 的标准差的比值。因子 IR 值越高, 代表因子综合考虑区分度和稳定性后效果越好,优化目标是使复合因子的信息比 IR 取到最大值。 165 | 166 | #### 动态最优化IR 167 | 168 | 虑到市场环境变化和风格转变等原因会使得因子的有效性和 IC 值出现波 动,仅仅使用静态的 IC 优化方法给定复合因子中的因子权重会容易导致组 合受风格变化影响而出现较大的波动和回撤构造了一个动态调整的基于 IC 值的复合因子 IR 最优化模型。 169 | 170 | 动态的最优化权重模型是建立在上面我们提到的静态最优化 IR 模型的基础上的,假设每期优化因子权重时所参考的历史 IC 序列长度为 N 个月。(首先假设组合股票数量为 M=100,手续费单边 0.3%,每月初调仓,则在不 同的参数 N 下) 171 | 172 | 一般动态的最优化 IR 赋权方法要优于静态的因子赋权法 173 | 174 | 175 | 176 | ### 因子赋权组合 177 | 178 | 组合内等权 v.s.复合因子得分加权 179 | 在构建每月调仓组合时,入选标的的赋权方式包括等权和按复合因子的得分加权两种方法。 180 | 181 | (EW 为等权,SW 为复合因子得分加权) 182 | -------------------------------------------------------------------------------- /notebook/3.因子处理.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | # 因子处理 4 | 5 | 6 | 7 | ## 去极值(异常值处理) 8 | 9 | 10 | 11 | 1. 均值方差法3σ:求每个因子的的均值u和方差σ,大于u+3σ和小于u-3σ的值转化为u+3σ和u-3σ 12 | - 先计算因子的平均值u和标准差σ 13 | - 确认参数n(n=3时为3σ法),因子的合理范围为[X_mean-nσ,X_mean+nσ] 14 | 2. 绝对值差中位数法mad:计算所有因子与平均值之间的距离总和来检测离群值 15 | - 先找出所有因子的中位数X_meadian 16 | - 得到每一个因子与中位数的绝对偏差值Xi-X_meadian 17 | - 得到绝对偏差值的中位数mad,最后确定参数n,合理范围为[X_meadian-nmad,X_meadian+nmad] 18 | 3. 分位数法(箱型图) 19 | 20 | 21 | 22 | 23 | 24 | ## 因子中性化 25 | 26 | 原因:A股的行业轮动明显,行业热点之间切换迅速,并且A股小市值个股占比明显,高波动率高收益率 27 | 28 | 目的: 29 | 30 | - 降低投资组合的波动性和回测 31 | - 为了在用某一因子时能够剔除其他因素的影响,使得选出的股票更加分散,需要进行中性化处理 32 | - 为了消除因子中的偏差和不必要的影响 33 | 34 | 对于因子来说,中性化主要考虑市场风险和行业风险。 35 | 36 | 行业中性:多头组合的行业配置与对冲基准的行业配置一致,目的在于剔除行业因子对策略收益的影响,仅考察行业内部个股的超额收益。(行业中性策略的净值曲线往往比较平稳,回测较小) 37 | 38 | 风格因子中性:多头组合的风格因子较之对冲基准的风险暴露为0,目的在于使多头组合的风格特征完全与对冲基准相匹配,使得组合的超额收益不是来自于某类风格 39 | 40 | 1. 行业中性化 41 | 42 | 行业中性化一般采用两种方式处理 43 | 44 | - 简单的标准化法 45 | 46 | 利用申万行业指数,将各个行业的因子进行标准化处理,即减去均值除以标准差 47 | 48 | - 回归取残差法 49 | 50 | 将因子值作为y,行业哑变量作为x,进行线性回归,回归模型的残差即为行业中性化后的因子值 51 | 52 | 2. 市值中性化 53 | 54 | 因为市值因子是连续的,采用回归残差法 -------------------------------------------------------------------------------- /notebook/4.代码说明.md: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | # 代码说明 6 | 7 | 代码一共分为四大部分(参见图1.1,图1.2),详细说明见下,相关图片可以在image文件夹里查阅大图。 8 | 9 | 1. 数据读取 10 | 11 | - 六大类因子读取 12 | 13 | 14 | 15 | 16 | 17 | - 十个风险因子读取 18 | 19 | 2. 空值填充 20 | 21 | 3. 概率预测 22 | 23 | - 24 | 25 | - 26 | 27 | - 28 | 29 | 4. 因子分析 30 | 31 | - 因子T检验 32 | - 因子检测1 33 | - 因子检测2 34 | 35 | ![代码说明01](https://github.com/Miya-Su/Quantitative-Trading/raw/miya/image/代码说明01.png) 36 | 37 | 38 | 39 | ![代码说明02](https://github.com/Miya-Su/Quantitative-Trading/raw/miya/image/代码说明02.png) 40 | 41 | 42 | 43 | ## 详细说明 44 | 45 | *1.数据读取 46 | 47 | 将特征值组合成一个DataFrame,形成输入数据。 48 | 49 | 每个特征值都按照Pandas的pickle形式存储在相应文件夹(数据通过SVN进行本地更新),一共分为六大类(factor_name_list = ['emotion', 'pricevol', 'mom', 'finance', 'valuation', 'alpha191']) 50 | 51 | 使用读取文件列表 52 | 53 | 使用读入每一类的所有特征值数据,合计116个。 54 | 55 | 每个特征数据都是Pandas DataFrame格式,index为股票代码,columns为日期,数据代表当期值,如下所示: 56 | 57 | ![代码说明03](https://github.com/Miya-Su/Quantitative-Trading/raw/miya/image/代码说明03.png) 58 | 59 | 60 | 61 | 使用将116个特征值组合成一个Pandas DataFrame格式,index为3619只股票代码,每一列代表一个特征所对应的数据,即columns为对应的116个特征,最后一列为日期date,倒数第二列为标签值rise_fall,倒数第三列trade_status为股票状态列(只选择为0的正常股票,其余非零状态股票为非正常股票,可能停牌,应该删除),最终 DataFrame构造如下: 62 | 63 | 64 | 65 | ![代码说明04](https://github.com/Miya-Su/Quantitative-Trading/raw/miya/image/代码说明04.png) 66 | 67 | 68 | 69 | *2.数据处理 70 | 71 | 由于很多数据缺失,缺失值处理按照行业均值填充(建议是不处理,为了数据的真实性) 72 | 73 | 74 | 75 | *3.划分测试集和训练集 76 | 77 | 按照滚动周期划分,循环预测得到每一期的数据值,输入的每期数据为numpy.arrary格式,需要将DataFrame进行划分。 78 | 79 | 月频数据:前12个月的值作为训练集,后一个月作为预测集。 80 | 81 | 周频数据:前48周的值作为训练集,后一个周作为预测集。 82 | 83 | 84 | 85 | *4.进行预测 86 | 87 | 由于循环预测,每一期模型的最优参数都不一样,只能进行粗调,尽量保证每一次预测的精度都在50%以上。(为了避免过拟合,需要限制最大深度) 88 | 89 | 90 | 91 | *5.因子数据合成 92 | 93 | 因子数据按照分类和回归分为两种。 94 | 95 | 分类:得到不同分类的两组概率值,选取分类为“1”(即上涨前T%类别)的概率值作为因子数据 96 | 97 | 回归:直接将回归预测得到的涨跌幅数值作为因子数据 98 | 99 | 100 | 101 | *6.因子检验 102 | 103 | 因子检验分为三种 104 | 105 | - 因子T检验 106 | - 因子检测1 107 | - 因子检测2:投资组合构建,直接将概率值排序前100只的股票选出,作为投资组合,分为两种方式:第一种直接等权构建, 即每只股票配置0.01的权重,第二种为按照基准行业权重进行配置 108 | 109 | 110 | 111 | 112 | 113 | # 函数说明 114 | 115 | ### 1.def read_factor_data(factors_name_list, trade_date_20d_series) 116 | 117 | 从文件夹读取数据 118 | 119 | #### `def risk_factor(alpha_factor_series)` 120 | 121 | 读取十个风险因子,加入Pandas Series中,完成数据构建 122 | 123 | 124 | 125 | ### 2.def nonefill(data,date_list) 126 | 127 | 数据缺失值填充(按照行业均值填充) 128 | 129 | #### `def fillna_ind_mean(data,date_list)` 130 | 131 | 对DataFrame格式特征数据按照股票行业均值填充空值 132 | 133 | #### `def data_fillna_mean(data,date_list)` 134 | 135 | 对Series中的每一个DataFrame格式的特征数据进行缺失值填充 136 | 137 | 138 | 139 | ### 3.def predict_probo_class(data,model,loop,date_list,T,x,changeindex_model) 140 | 141 | 分类概率预测 142 | 143 | 输入DataFrame格式数据、分类预测模型、循环预测周期、时间、分类的标签值百分比T(前后T%的数据)、以及标签值分类数据x(x=0为三分类,x=-1为二分类)、因子数据构造模型(两种,二分类和三分类) 144 | 145 | 得到预测的因子概率值、预测准确率 146 | 147 | #### `def data_input_class(data,date_list,T,x)` 148 | 149 | 输入DataFrame格式数据、时间、分类的标签值百分比T(前后T%的数据)、以及标签值分类数据x(x=0为三分类,x=-1为二分类) 150 | 151 | ##### `def concat_data(data,date_list,is_rise_df)` 152 | 153 | 将特征数据和标签值进行合并 154 | 155 | ##### `def rise_fall_class(trade_date_m_series,T)` 156 | 157 | 划分标签值,T为百分数值,T=30表示:将涨跌幅上涨的前30%的股票划分为一类 158 | 159 | ##### `def data_train_test(data_pct,x)` 160 | 161 | 划分测试数据和训练数据 162 | 163 | | x=-1 | 二分类(前T%为1,其余-1) 训练数据为(1、-1),测试数据为(1、-1) | def changeindex2(data,M,date_list) | 164 | | ------- | ------------------------------------------------------------ | -------------------------------------- | 165 | | **x=0** | **三分类(前T%为1,后T%为-1,中间为0)训练数据(1、-1),测试数据(1、-1、0)** | **def changeindex3(data,M,date_list)** | 166 | 167 | #### `def splitdata(train,test,i,j,x,y)` 168 | 169 | 划分每次循环的测试集和训练集,得到的测试集和训练集为numpy.array格式 170 | 171 | ##### `def countsum(data)` 172 | 173 | 根据时间划分数据,同一时间的股票数据划分为一组 174 | 175 | ##### `def standard(X_train,X_test)` 176 | 177 | 数据标准化 178 | 179 | #### `def changeindex2(data,M,date_list)` 180 | 181 | 因子数据构造,二分类,x=-1时,选择此模型,得到两种分类的因子概率值 182 | 183 | ##### `def change(data,n,m,M,date_list)` 184 | 185 | #### `def changeindex3(data,M,date_list)` 186 | 187 | 因子数据构造,三分类,x=0时,选择此模型,会得到三种分类的因子概率值 188 | 189 | #### `def accu_score(score,name)` 190 | 191 | 模型准确率评估(每次循环得到的训练集和预测集上的准确率) 192 | 193 | 194 | 195 | ### 4.def predict_probo_reg(data,model,loop,date_list) 196 | 197 | 回归概率预测 198 | 199 | 输入DataFrame格式数据、回归预测模型、循环预测周期、时间、回归的标签值(涨跌幅数值),因子数据构造模型 200 | 201 | 得到预测的因子值、预测RMSE 202 | 203 | #### `def data_input_reg(data,date_list)` 204 | 205 | 输入DataFrame格式数据、时间 206 | 207 | ##### `def concat_data(data,date_list,is_rise_df)` 208 | 209 | 将特征数据和标签值进行合并 210 | 211 | ##### `def rise_fall_class(trade_date_m_series)` 212 | 213 | 获取标签值:股票涨跌幅的具体数值 214 | 215 | ##### `def data_train_test(data_pct)` 216 | 217 | 划分测试数据和训练数据 218 | 219 | #### `def splitdata(train,test,i,j,x,y)` 220 | 221 | ##### `def countsum(data):` 222 | 223 | ##### `def standard(X_train,X_test)` 224 | 225 | #### `def changeindex1(data,M,date_list)` 226 | 227 | 因子数据构造,将回归模型预测得到的值狗造成因子数据 228 | 229 | #### `def change(data,n,m,M,date_list)` 230 | 231 | 232 | 233 | ### 5.class AveragingModels(BaseEstimator, RegressorMixin, TransformerMixin) 234 | 235 | 简单平均集成学习,通过合成模型进行分类/回归预测 236 | 237 | #### `def rmsle_cv(model,data,loop)` 238 | 239 | 回归预测的交叉验证,通过计算RMSE验证单个模型的准确性,输入模型、数据以及预测周期 240 | 241 | #### `def rmsle(model,data,loop,date_list)` 242 | 243 | 回归预测 244 | 245 | #### `def rmse_show(rmse_list,label_list)` 246 | 247 | RMSE评估,得到每次循环预测的RMSE,画图显示 248 | 249 | 250 | 251 | ### 6.class StackingAveragedModels(BaseEstimator, RegressorMixin, TransformerMixin) 252 | 253 | Meta-model Stacking:使用前面分类器产生的特征输出作为最后总的meta-classifier的输入数据 254 | 255 | #### `def rmsle_cv(model,data,M)` 256 | 257 | #### `def rmsle(model,data,loop,date_list)` 258 | 259 | #### `def rmse_show(rmse_list,label_list)` 260 | 261 | 262 | 263 | ### 7.def factor_test_T(factor_list,factor_name) 264 | 265 | 因子T检验 266 | 267 | 268 | 269 | ### 8.def factor_analyse(name,factor) 270 | 271 | 因子测试 272 | 273 | #### `def show1(factor_test_obj)` 274 | 275 | 净值绩效,对冲表现 276 | 277 | #### `def show2(factor_test_obj)` 278 | 279 | 计算因子年化收益,最大回撤,月胜率 280 | 281 | #### `def show3(factor_test_obj)` 282 | 283 | 计算因子绩效 284 | 285 | #### `def show4(factor_test_obj)` 286 | 287 | 计算分组绩效 288 | 289 | #### `def show5(factor_test_obj)` 290 | 291 | 计算分组年化收益 292 | 293 | #### `def show6(factor_test_obj)` 294 | 295 | 计算因子IC值,看IC衰减 296 | 297 | 298 | 299 | ### 9.def factor_stock_choose(factor,num) 300 | 301 | 投资组合因子检验,直接选取因子值高的前num支股票进行投资组合构建(一般100支或者80支) 302 | 303 | 这里为预测后涨跌幅上涨的TOP num支股票 304 | 305 | #### `def factor_test_pre(factor)` 306 | 307 | 因子中性化处理 308 | 309 | #### `def stock_choice(data,num)` 310 | 311 | 投资组合构建:有两种选择 312 | 313 | 等权选num支股票(每支股票相同权值1/num) 314 | 315 | 按照基准行业选取num支股票(股票按照基准行业进行权重划分) 316 | 317 | ##### `def stock_bench_ind(data,num)` 318 | 319 | 基准行业划分 320 | 321 | ###### `def get_industry_stock(stock_factor_series, set_date, stock_num=100)` 322 | 323 | 获得股票行业 324 | 325 | ###### `def get_bench_ind_weight(set_date, bench_code='ZZ500')` 326 | 327 | 按照基准行业划分股票权重 328 | 329 | #### `def show01(perform_obj)` 330 | 331 | 净值绩效、对冲表现 332 | 333 | #### `def show02(perform_obj)` 334 | 335 | 计算策略收益 336 | 337 | #### `def show03(perform_obj)` 338 | 339 | 计算换手率 340 | 341 | #### `def show04(perform_obj)` 342 | 343 | 计算分组年化收益 -------------------------------------------------------------------------------- /research/17_A股市场风险分析——《因子选股系列研究之十七》.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/research/17_A股市场风险分析——《因子选股系列研究之十七》.pdf -------------------------------------------------------------------------------- /research/20150426-国泰君安-数量化专题之五十七:基于组合权重优化的风格中性多因子选股策略.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/research/20150426-国泰君安-数量化专题之五十七:基于组合权重优化的风格中性多因子选股策略.pdf -------------------------------------------------------------------------------- /research/20160219-东方证券-《因子选股系列研究之六》:用组合优化构建更精确多样的投资组合.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/research/20160219-东方证券-《因子选股系列研究之六》:用组合优化构建更精确多样的投资组合.pdf -------------------------------------------------------------------------------- /research/20160523-长江证券-多因子模型系列报告之一:模型理论随想和纯因子组合构建.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/research/20160523-长江证券-多因子模型系列报告之一:模型理论随想和纯因子组合构建.pdf -------------------------------------------------------------------------------- /research/20160812-东方证券-《因子选股系列研究之十》:Alpha因子库精简与优化.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/research/20160812-东方证券-《因子选股系列研究之十》:Alpha因子库精简与优化.pdf -------------------------------------------------------------------------------- /research/20161023-长江证券-多因子模型系列报告之二:利用纯因子组合检验因子有效性.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/research/20161023-长江证券-多因子模型系列报告之二:利用纯因子组合检验因子有效性.pdf -------------------------------------------------------------------------------- /research/20161026-长江证券-多因子模型系列报告之三:利用纯因子组合进行因子投资.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/research/20161026-长江证券-多因子模型系列报告之三:利用纯因子组合进行因子投资.pdf -------------------------------------------------------------------------------- /research/20180301-东方证券-因子选股系列研究之三十五:组合优化的若干问题.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/research/20180301-东方证券-因子选股系列研究之三十五:组合优化的若干问题.pdf -------------------------------------------------------------------------------- /research/21_组合优化是与非——因子选股系列研究之二十一.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/research/21_组合优化是与非——因子选股系列研究之二十一.pdf -------------------------------------------------------------------------------- /research/Barra China Equity Model Descriptor details.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/research/Barra China Equity Model Descriptor details.pdf -------------------------------------------------------------------------------- /research/Barra China Equity Model.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/research/Barra China Equity Model.pdf -------------------------------------------------------------------------------- /research/Fama-MacBeth-1973-Risk--return--and-equilibrium-empirical-tests.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/research/Fama-MacBeth-1973-Risk--return--and-equilibrium-empirical-tests.pdf -------------------------------------------------------------------------------- /research/The Cross-Section of expected stock return.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/research/The Cross-Section of expected stock return.pdf -------------------------------------------------------------------------------- /research/fama_common risk factors in the returns on stock and bonds.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Miya-Su/Quantitative-Trading/554f55a57756dff85152a30f8e3181cd22817c73/research/fama_common risk factors in the returns on stock and bonds.pdf --------------------------------------------------------------------------------