导读:通常情况下,我们使用线性去回归因子数据,用来解释因子对于收益的贡献程度。但事实情况下,此类方法过于简单,且市场收益并不一定与各类因子线性相关,难以达到预期效果。众所周知,树是机器学习中的一类算法,决策树算法则是其中的基础,而随机森林则是利用多棵决策树对样本进行训练并预测的一种算法。它们不同于支持向量机,KNN等需要大量数据前处理,且能处理复杂问题。
一、 决策树概念
分类决策树的核心思想就是在一个数据集中找到一个最优特征,然后从这个特征的选值中找一个最优候选值,根据这个最优候选值将数据集分为两个子数据集,然后递归上述操作,直到满足指定条件为止。

决策树示例图
二、因子选取
我们从趋势类,反趋势类,量价指标,压力支撑型,成交量,超买超卖,摆动型,强弱型,日期类10个维度共选取了39个技术因子作为特征值,并与横截面下的未来收益做合并,以方便数据处理。
趋势类 | bbi | 多空指数 |
ma | 5日移动平均 |
expma | 5日指数移动平均数 |
priceosc | 价格震荡指数 |
ddi | 方向标准差偏离指数 |
反趋势 | bias | 乖离率 |
cci | 顺势指标 |
dbcd | 异同离差乖离率 |
dpo | 区间震荡线 |
kdj_k | 随机指标K值 |
量价指标 | mfi | 资金流向指标 |
obv | 能量潮 |
pvt | 量价趋势指标 |
wvad | 威廉变异离散量 |
压力支撑型 | bbiboll | BBI多空布林线 |
boll | 布林线MID |
cdp | 逆势操作 |
env | ENV指标 |
mike | 麦克指标 |
成交量 | vr | 量比 |
vma | 量简单移动平均 |
vmacd | 量指数平滑异同平均 |
vosc | 成交量震荡 |
vstd | 成交量标准差 |
tapi | 加权指数成交值 |
超买超卖 | adtm | 动态买卖气指标 |
摆动类 | mi | 动量指标 |
micd | 异同离差动力指数 |
rc | 变化率指数 |
rccd | 异同离差变化率指数 |
srmi | SRMIMI修正指标 |
强弱型 | dptb | 大盘同步指标 |
jdqs | 阶段强势指标 |
jdrs | 阶段弱势指标 |
zdzb | 筑底指标 |
atr | 真实波幅 |
mass | 梅丝线 |
日期类 | up_n | 连涨天数 |
down_n | 连跌天数 |
技术因子列表
三、决策树策略
我们选取的时间为2017-01-01到2019-01-21,这段时间基本处于熊市阶段,我们使用train_test_split将样本数据划分为二,我们从中发现整体数据的正向样本(即收益数据大于某特定值)为0.02347312703583062,而在测试集中的正向样本为0.023768322475570033,两者数据相似,与此同时,我们可以开始进行训练数据的步骤。
clf=tree.DecisionTreeClassifier(criterion='gini',max_features='sqrt',max_depth=100,class_weight='balanced')clf.fit(x_train,y_train)
代码展示
我们可以看到在criterion中我们选取了gini,这是基尼不纯度,可以理解为对数据集进行随机分类,分类错误出现的概率的期望。其中数据纯度越高,基尼不纯度越低。

公式展示
其次,在max_features参数,我们选取特征数量的sqrt作为节点分裂时使用的特征数量。在max_depth参数,我们选取120作为基础模型的最大深度,如果不选取,模型会进行到最深部分,容易产生过拟合。在class_weight部分,即类别权重,由于正向样本无论在整体数据还是测试数据都表现特别稀少,如果每个数据等权,则不合适,故我们使用 'balanced',其表示为类别的权重与样本所占比例成反比。
接下来,我们画出特征值在训练时各个因子的重要程度对比图,我们可以看出srmi和mfi指标重要性极大。
因子的重要程度对比图
紧接着我们开始基于训练集训练好的模型,使用决策树对测试集的数据进行验证,我们从沪深300中选取相应股票,并结合对比沪深300本身的指数净值数据,画出相应图像。
data_300 = get_price(['000300.SH'], start_date, end_date, '1d', ['close'], True, None, is_panel=1)['close']data_300.columns=['close300']data_300['return300']=data_300['close300'].pct_change()data_300['net_value']=(1+data_300['return300']).cumprod()df_portfolio['HS300']=data_300.ix[df_portfolio.index,'net_value']df_portfolio[['strategy_return','HS300']].plot(figsize=(20,8))plt.title('Decision Tree Strategy',y=1.05,size=25)
代码展示
我们对股票使用的方式是等权买入,并持有一段固定时间,下图蓝线表示决策树策略净值曲线,绿线表示为沪深300作为基准的净值曲线。
决策树策略净值曲线
四、 随机森林策略
随机森林是指利用多棵决策树对样本进行训练并预测的一种算法,它是一种平均法得到的集成模型。也就是说随机森林算法是一个包含多个决策树的算法,其输出的类别是由个别决策树输出的类别的众树来决定的,也就是说它要求的基础模型,即多个决策树模型,必须是低偏差,高方差的强模型。

随机森林模型示意图
我们依旧选取的时间为2017-01-01到2019-01-21。并开始进行训练数据的步骤。其中,我们选择20作为n_estimators的值,即基础模型(决策树)的数量。
clf_randomforest=RandomForestClassifier(n_estimators=20,criterion='gini',max_features='sqrt',max_depth=100,class_weight='balanced')clf_randomforest.fit(x_train,y_train)
代码展示
我们在训练数据的同时,画出特征值在训练时各个因子的重要程度对比图,我们可以看出srmi、kdj_k、dpo和bias四个技术指标重要性极大。

因子的重要程度对比图
我们将训练好的随机森林模型运用到划分出来的测试数据上进行验证,并相应地画出相关净值曲线图。
predict=clf_randomforest.predict(x_test)data_total.ix[x_test.index,'predict']=predictdata_holding=pd.DataFrame({i:data_total.predict.groupby(level=0).apply(lambda x:x.shift(i)) for i in range(1,6)})data_holding['total']=data_holding.sum(axis=1)data_total['flag_holding']=data_holding.total>0
代码展示
我们对股票使用的方式是等权买入,并持有一段固定时间,下图蓝线表示随机森林模型净值曲线,绿线表示为沪深300作为基准的净值曲线。

随机森林模型净值曲线
结束语:无论在决策树模型,还是在此基础之上的随机森林模型都可以利用多个技术面因子进行有效选股判断,但所选因子应该来自于多个维度,以分散集中风险。我们在实验的过程中循环划分训练和测试数据,发现bias,srmi因子经常表现突出,重要性明显。策略表现也在18年以后有显著超额收益。