算法-基于成交量的Adaboost股价涨跌预测模型

     基于上篇文章提到的思路,个人觉得你不能用A来预测A,所以我打算换一种数据。 上篇文章 《算法-基于MACD的Adaboost股价涨跌预测模型》 虽然给出了adaboost算法,但是并没有完全正确的表达,尤其是在权重如何处理上,也就是如何对待那些被误分的样本。 所以打算更严谨的来对待这个算法,本着不要用错误的方法得出正确的结论的原则,我修正了我的adaboost算法,由于需要用大量的数据进行测试,我决定把java代码移植为C/C++版本以期获得更高的训练速度。好吧,下面我介绍一下修正后的算法。我再一次参考李航的《统计学习方法》 和《量价秘密》这两本书,我决定放弃我的阀值分类器转而使用最简单的感知器线性分类器,事实上股价的涨跌和成交量本身就不是一种线性关系,而是一种复杂的非线性关系,而且这种关系由于其他变量的作用变得模糊,我们只能大概判断,却无法精确定性,由此使用弱分类器是合适的。这个版本的预测只是一个阶段性的,后期我还会继续寻找非线性的简单分类器来训练我的数据。在使用adaboost的时候,不得不提到就是error率如何计算,特别是在样本分布不均匀的时候,我们必须分别计算正样本和负样本的分类准确率,这个前提条件下整体的分类准确率才有意义。举个例子,假如正样本个数51个,负样本数据49个,假如分类器毫无理由的完全输出1,即所有的样本都分类为正样本,那么可以获得49%的准确率,完全符合adaboost的算法框架,实际上,这种分类器是毫无意义的,训练出来也毫无决策能力,因为它受样本分布影响,也就是说涨的多你就赚,跌的多你就亏。 如果我们将正负样本分开,51个正样本的错误率是40%, 49个负样本的错误率是42%,那么整体的错误率就会下降:51*40%+49*42%=40.98, 也就是错误分的样本数为40.98个,那么错误率也就是40.98%,这样计算出来错误率才有意义,我不得不百般的强调这个结论,因为在训练的时候我确实因为没有分别对待正样本和负样本而导致了前面提到的垃圾分类器诞生。对于简单的线性感知器,我有一点看法,具体实现请参考李航的《统计学习方法》,训练非常的简单:

for(int epoch = 0; epoch < EPOCH; epoch++){
		//sequence gradient descent. not stochastic.

		for(int i = 0; i < rows; i++){
			double res = predict(trainX[i], colsX);
			if(trainY[i] * res <= 0){
				//update W and b.
				for(int j = 0; j < colsX; j++){
					mWeights[j] += lr * trainY[i] * trainX[i][j];//ok
				}
				mBias += lr * trainY[i];//ok
			}
		}
		
	}

double predict(double* trainX, int colsX){
	double res = 0;
	for(int i = 0; i < colsX; i++){
		res += mWeights[i] * trainX[i];
		
	}
	res += mBias;
	
	return res;
}

对于Adaboost算法错误率的修正


double WeakClassifier::calculateAdaBoostError(double** inputX, double* inputY, double* weights, int* rightOrWrong, const int rows, const int colsX){
    if(inputX == NULL || inputY == NULL || rightOrWrong == NULL || weights == NULL){
        printf("WeakClassifier::calculateAdaBoostError(double**, double*, double*, int*, int, int), param NULL\n");
        int paramNull = 9;
        throw paramNull;
    }
    double err = 0;
    for(int i = 0; i < rows; i++){
        double res = predict(inputX[i], colsX);
        if(inputY[i] * res <= 0){
            rightOrWrong[i] = WRONG;
            err += weights[i];
            //err++;
        }else{
            rightOrWrong[i] = RIGHT;
        }
    }
    //return err / rows;
    return err;
}


我为什么在参考了《量价秘密》后决定用成交量来预测股价呢,而且使用线性模型,这里解释一下。量价秘密那本书里通过比较成交量的大小来决定买入和卖出信号的触发,比较本身就是一种线性关系,所以我使用WX+B的方式来进行判断,通过对成交量进行线性组合,调节W和B就可以组合出成交量的比较,也就有了通过量的比较的弱分类器。


关于数据,我依然使用均成交量,并且使用了多日的均成交量,由于股价的短期的不可预测性,我将预测周期延长至3天。

通过训练:

 ./test.exe -e 3000 -c 600704
train epoch is 3000  code is -c
startrow=0  endrow=51000  startcol=1  endcol=16
startrow=0  endrow=4623  startcol=1  endcol=16
start training......
Epoch [   ]       0      ECR=100.0000    EP=0.3169       EN=0.6166       SUME=0.4651     E=0.4651        IR0=1173.1940   IR1=-4018.6180  SUMIR=-2845.4240
Epoch [GOT]       1      ECR=100.0000    EP=0.4761       EN=0.4381       SUME=0.4569     E=0.4569        IR0=12071.1190  IR1=-14916.5430         SUMIR=-2845.4240
Epoch [GOT]       6      ECR=100.0000    EP=0.4868       EN=0.4209       SUME=0.4567     E=0.4678        IR0=11375.0000  IR1=-14220.4240         SUMIR=-2845.4240
Epoch [GOT]       9      ECR=100.0000    EP=0.4350       EN=0.4300       SUME=0.4524     E=0.4466        IR0=4615.1350   IR1=-7460.5590  SUMIR=-2845.4240
Epoch [GOT]      10      ECR=100.0000    EP=0.3227       EN=0.4616       SUME=0.4465     E=0.4280        IR0=14724.8560  IR1=-17570.2800         SUMIR=-2845.4240
Epoch [   ]     100      ECR=2.3039      EP=0.5383       EN=0.5726       SUME=0.5553     E=0.5302        IR0=-1646.3840  IR1=-1199.0400  SUMIR=-2845.4240
Epoch [   ]     200      ECR=2.3039      EP=0.7418       EN=0.2352       SUME=0.4913     E=0.4943        IR0=1293.3930   IR1=-4138.8170  SUMIR=-2845.4240
Epoch [   ]     300      ECR=2.3039      EP=0.5250       EN=0.5844       SUME=0.5544     E=0.5334        IR0=-23511.8240         IR1=20666.4000  SUMIR=-2845.4240
Epoch [   ]     400      ECR=2.3039      EP=0.4121       EN=0.7739       SUME=0.5910     E=0.5561        IR0=-20503.8920         IR1=17658.4680  SUMIR=-2845.4240
Epoch [   ]     500      ECR=2.3039      EP=0.6112       EN=0.4390       SUME=0.5261     E=0.5163        IR0=2418.4420   IR1=-5263.8660  SUMIR=-2845.4240
Epoch [   ]     700      ECR=2.3039      EP=0.4904       EN=0.6286       SUME=0.5587     E=0.5341        IR0=-11965.5530         IR1=9120.1290   SUMIR=-2845.4240
Epoch [   ]     800      ECR=2.3039      EP=0.4483       EN=0.6330       SUME=0.5396     E=0.5236        IR0=-7478.3960  IR1=4632.9720   SUMIR=-2845.4240
Epoch [   ]     900      ECR=2.3039      EP=0.5614       EN=0.4788       SUME=0.5205     E=0.5111        IR0=5078.3710   IR1=-7923.7950  SUMIR=-2845.4240
Epoch [   ]    1000      ECR=2.3039      EP=0.4377       EN=0.7497       SUME=0.5920     E=0.5560        IR0=-30847.1960         IR1=28001.7720  SUMIR=-2845.4240
Epoch [   ]    1100      ECR=2.3039      EP=0.4969       EN=0.5871       SUME=0.5415     E=0.5227        IR0=-18519.4230         IR1=15673.9990  SUMIR=-2845.4240
Epoch [   ]    1200      ECR=2.3039      EP=0.4789       EN=0.7170       SUME=0.5966     E=0.5544        IR0=-21886.6390         IR1=19041.2150  SUMIR=-2845.4240
Epoch [   ]    1300      ECR=2.3039      EP=0.4268       EN=0.6292       SUME=0.5269     E=0.5148        IR0=-10134.1010         IR1=7288.6770   SUMIR=-2845.4240
Epoch [   ]    1400      ECR=2.3039      EP=0.4437       EN=0.6296       SUME=0.5356     E=0.5187        IR0=-16387.0800         IR1=13541.6560  SUMIR=-2845.4240
Epoch [   ]    1500      ECR=2.3039      EP=0.4849       EN=0.6207       SUME=0.5521     E=0.5264        IR0=-10468.6150         IR1=7623.1910   SUMIR=-2845.4240
Epoch [   ]    1700      ECR=2.3039      EP=0.4401       EN=0.7248       SUME=0.5809     E=0.5496        IR0=-17702.6790         IR1=14857.2550  SUMIR=-2845.4240
Epoch [   ]    2000      ECR=2.3039      EP=0.4878       EN=0.6360       SUME=0.5611     E=0.5330        IR0=-11540.4570         IR1=8695.0330   SUMIR=-2845.4240
Epoch [   ]    2100      ECR=2.3039      EP=0.6207       EN=0.4958       SUME=0.5589     E=0.5316        IR0=-17458.0150         IR1=14612.5910  SUMIR=-2845.4240
Epoch [   ]    2200      ECR=2.3039      EP=0.4197       EN=0.7084       SUME=0.5625     E=0.5350        IR0=-15700.9920         IR1=12855.5680  SUMIR=-2845.4240
Epoch [   ]    2300      ECR=2.3039      EP=0.3692       EN=0.7865       SUME=0.5756     E=0.5458        IR0=-16695.8020         IR1=13850.3780  SUMIR=-2845.4240
Epoch [   ]    2400      ECR=2.3039      EP=0.4680       EN=0.7610       SUME=0.6129     E=0.5676        IR0=-25387.5070         IR1=22542.0830  SUMIR=-2845.4240
Epoch [   ]    2500      ECR=2.3039      EP=0.5393       EN=0.6183       SUME=0.5784     E=0.5439        IR0=-22889.1490         IR1=20043.7250  SUMIR=-2845.4240
Epoch [   ]    2600      ECR=2.3039      EP=0.6507       EN=0.3491       SUME=0.5016     E=0.4994        IR0=5327.8050   IR1=-8173.2290  SUMIR=-2845.4240
Epoch [   ]    2700      ECR=2.3039      EP=0.4453       EN=0.6017       SUME=0.5226     E=0.5135        IR0=-7558.7720  IR1=4713.3480   SUMIR=-2845.4240
Epoch [   ]    2800      ECR=2.3039      EP=0.4725       EN=0.7312       SUME=0.6005     E=0.5599        IR0=-22751.3970         IR1=19905.9730  SUMIR=-2845.4240

calculate trained model:E0=0.3227  E1=0.4616

Use model 0

这里解释下各个参数,epoch[  ]代表例行检查输出,表明我的程序在跑epoch[ GOT ]代表找到了一个弱分类器。

ECR为错误分类样本的权重小于平均值的比例,EP代表正样本的错误率, EN代表负样本的错误率, SUME代表整体错误率,E是adaboost模型的错误率,IR0代表系统发出买入信号的利润率, IR1代表系统发出卖出信号时,如果你买入后将获得的利润率,好的模型应该是IR0大于0 IR1小于0,所以我过滤掉了那些不符合这个条件,但是准确率符合条件的若分类器。


train over!!  4 weak classifier(s) was trained !!!

MODEL0: [20150616] [ERROR]  BLF:   0.26    POINT=  -5.55    IR0=  -5.55
MODEL0: [20150618] [ERROR]  BLF:   0.04    POINT=  -3.66    IR0=  -9.21
MODEL0: [20150624] [ERROR]  BLF:   0.73    POINT= -15.23    IR0= -24.44
MODEL0: [20150625] [ERROR]  BLF:   0.20    POINT= -15.03    IR0= -39.46
MODEL0: [20150626] [ERROR]  BLF:   0.90    POINT= -19.59    IR0= -59.05
MODEL0: [20150630] [ERROR]  BLF:   0.24    POINT= -19.42    IR0= -78.48
MODEL0: [20150701] [ERROR]  BLF:   1.86    POINT= -19.44    IR0= -97.92


...........................................

..............................................

.................................................

MODEL0: [20160314] [ OK  ]  BLF:   0.20    POINT=   6.51    IR0= 745.22
MODEL0: [20160315] [ OK  ]  BLF:   0.21    POINT=   5.79    IR0= 751.01
MODEL0: [20160321] [ OK  ]  BLF:   0.10    POINT=   6.70    IR0= 757.71
MODEL0: [20160322] [ OK  ]  BLF:   0.02    POINT=   2.11    IR0= 759.82
MODEL0: [20160329] [ OK  ]  BLF:   0.46    POINT=   1.94    IR0= 761.76
MODEL0: [20160330] [ OK  ]  BLF:   0.03    POINT=   3.77    IR0= 765.54
MODEL0: [20160406] [ OK  ]  BLF:   0.96    POINT=  10.83    IR0= 776.37
MODEL0: [20160407] [ OK  ]  BLF:   0.03    POINT=   7.66    IR0= 784.03
MODEL0: [20160413] [ OK  ]  BLF:   0.30    POINT=   4.35    IR0= 788.38
MODEL0: [20160421] [ERROR]  BLF:   0.11    POINT=  -6.98    IR0= 781.40
MODEL0: [20160428] [ OK  ]  BLF:   0.30    POINT=   2.95    IR0= 784.35
MODEL0: [20160509] [ERROR]  BLF:   0.09    POINT= -12.38    IR0= 771.97
MODEL0: [20160607] [ OK  ]  BLF:   0.42    POINT=   8.74    IR0= 780.71
MODEL0: [20160608] [ OK  ]  BLF:   0.17    POINT=   7.49    IR0= 788.20
MODEL0: [20160620] [ OK  ]  BLF:   0.20    POINT=   5.13    IR0= 793.33
MODEL0: [20160621] [ OK  ]  BLF:   0.11    POINT=   2.15    IR0= 795.48
MODEL0: [20160628] [ OK  ]  BLF:   0.32    POINT=   4.38    IR0= 799.87
MODEL0: [20160629] [ OK  ]  BLF:   0.04    POINT=   5.75    IR0= 805.62
MODEL0: [20160708] [ OK  ]  BLF:   0.05    POINT=   0.41    IR0= 806.03
MODEL0: [20160721] [ OK  ]  BLF:   0.33    POINT=   4.61    IR0= 810.63
MODEL0: [20160722] [ OK  ]  BLF:   0.23    POINT=   6.15    IR0= 816.78


MODEL0: IR0=816.780000 ACCURACY=0.620314 SUMIRP=11880.370000

MODEL1: IR1=-5329.251000 ACCURACY=0.546312 SUMIRN=-16392.841000

SUMIR:-4512.471000





最后的结果还是挺好的,8倍的收益,4000条测试数据,从2015年6月15日后一直到今天

训练数据有10多只股票的,是我随机挑选的,大概有51000条训练样本,训练时间大概有10分钟左右。召回率62%

前景展望:这个模型目前还需要大量测试,尤其是同一板块的数据集合起来进行训练,应该会有几十万个训练样本,线性分类器能否经得住考验还需要检验,此外还需要测试一下这个模型在牛市的表现。由于股价与成交量的非线性关系,探索非线性的若分类器应该理论上会提高分类精度,尤其是BP神经网络。

你可能感兴趣的:(算法)