R语言的股市人生
1.1问题描述和目标
对数据挖掘而言股票市场交易是个具有巨大潜力的应用领域;我们目标是尽可能的获取利润;应用数据挖掘技术得到结果给出信号,然后据此作为决策的基础来制定交易策略;
1.2数据说明
我还是使用上篇博客的数据集作为我们这此研究的重点,我们一样使用西班牙著名企业迪亚天天的股市价格数据作为我们的模型数据;我们还是使用包quantmod的函数getSymbols获取我们需要的数据;我们获取的数据中包含了下面几个属性;这里就不贴字段了;
~交易日期
~当天开盘价
~当日最高价
~当日最低价
~当日收盘价
~当日成交量
~当日调整后的收盘价;
1.3将数据加载到R中
我们还是使用quantmod包中的getSymbols函数获取数据并加载到R中,出现了下面的结果说明数据已经成功加载到R中;
library(quantmod)
getSymbols("DIA")
head(DIA)
1.4定义预测任务
一般我们都是要预测股票价格的,但是这里我们能否预测未来几天的市场变化趋势,如果这个预测是正确的该预测下达的交易指令将是获利的;我们认为价格变动超过P%,时值得交易,所以我们需要预测的是在未来几天价格总的变化,并不是预测某个特定时间的一个特定价格;例如,在t+k的收盘价的变化可能比P%低得多,但是在它前面日期t,..,t+k的价格变化可能远远大于P%。因此我们要预测的是K天的总体价格趋势
这么多个价格到底选用那个作为每天的价格呢,我们这时候取
avg_price=(high+close+low)/3
其中C,H,L分别为第i天的收盘价,最高价和最低价;
设V代表未来K天的平均价格相对今天收盘价的百分比变化,其中P是代表未来K天的平均价格,C是收盘价;
然后我们把动态变化绝对值超过目标收益的P%的变化进行累加作为一个指标变量;
指标变量T用来找出日平均价格明显高于目标变化的那些的那些日期的变化之和,越大的T值怎么说明了未来的几天平均报价会高于收盘价的P%,这种情况下我们可以有很多的选择入市的机会,因为预期是看涨;相反,越大的负值T说明平均价格可能下降,我们可以进行卖出止损;如果T值一直是在0附近进行波动,则可能是价格正负的波动持平出现;
下面一段代码实现这个指标的只算,
t_ridao <- function(price,t.margin=0.02,time=9){
v <- apply(HLC(price), 1, mean)
r <- matrix(NA,ncol=time,nrow=NROW(price))
for (x in 1:time) r[,x] <- Next(Delt(v,k=x),x)
x <- apply(r,1,function(x) sum(x[x>t.margin|x< -t.margin]))
if (is.xts(price))
xts(x,time(price)) else x
}
这个函数首先是先计算平均价格,然后使用quantmod包中的HLC()从价格中提取价格的最高价,最低价和收盘价,然后根据未来TIME天相对当前收盘价的收益,而函数Next()按时间平移一个时间序列,Delt()函数可用于计算价格序列的百分比收益;最后t_radio函数将绝对值较大的收益相加,我们默认设置为2%
我们画出了关于价格的波动和平均价格的走势,价格波动处于一个平稳的波动中,不过为了大家能够更好的了解这个指标的性质
candleChart(last(DIA,"4 months"),theme="white",TA=NULL)
avgprice <- function(x)apply(HLC(x), 1,mean)
addavgprice <- newTA(FUN=avgprice,col=1,legend="Avgprice")
addT_radio <- newTA(FUN=t_radio,col="red",legend="tgtRat")
addavgprice(on=1)
addT_radio()
这里获取了最后四个月的故事K线图,这里橘色代表这一天中价格是下降(也就是开盘价低于收盘价),绿色代表价格上涨,使用candleChart()得到K线图;从上结果上看,当一段时间价格的上下波动,价格波动指标T_RADIO会呈现较为平稳,当价格上涨的时候,t_radio值达到了最大,因为计算未来的时间,所以这里我们选用9天的价格,这里只是将未来观测到的价格变化概括;
1.5预测变量选择
前面已经确定选用指标t_radio来总结未来时间的价格变化,这时候我们不选择常规的纯时间序列模型去预测价格行为,而是构建多个属性指标当作描述指标近期动态,这时候我们就要借助包TTR包来帮我们构建有关于反映价格时间序列特征的指标;
我们从R添加包中选取具有代表性的技术指标集合:
平均真实范围(ATR) 这个指标是衡量价格波动的指标;
随机动量指数(SMI) 该指标是一个动量指标;
威尔斯-维尔德定向运动指数(ADX) 定向运动指数
Aroon指标 该指标是找出开始的趋势
布林带指标 它比较一段时间内价格的波动
蔡金波动(CV)指标 计算最高价和最低价之间的价差。以在最大和最小之间的振幅为基础蔡金波动指标来断定波动价值;
收盘价位置价值(CLV) 该指标把收盘价和其交易范围相联系
简易波动指标(EMV)测度股价的变化和成交量的变化引发的数值变动
MACD指标 市场大趋势的一个测度指标
顺势指标(CCI) 这个是判断股价偏离股市的衡量指标
资金流向指数(MFI)这个指标是测度市场需求关系和买卖力道
抛物线止损反转(SAR) 这个也是用来分析市场趋势变化的一个指标
波动性指标(VOLAT)顾名思义这个就是衡量波动的一个指标
在这实现这写指标前我们先给数据列的命名,因为要和变量书写一直
names(DIA) <-c("Open","High","Low","Close","Volume","Adjusted")
head(DIA)
列的名称修改完毕这时候我们实现指标,指标实现代码如下;
T_ATR <- function(x) ATR(HLC(x))[,"atr"]
T_SMI <- function(x) SMI(HLC(x))[,"SMI"]
T_ADX <- function(x) ADX(HLC(x))[,"ADX"]
T_Aroon <- function(x) aroon(x[,c("High","Low")])$oscillator
T_BB <- function(x) BBands(HLC(x))[,"pctB"]
T_CV <- function(x) Delt(chaikinVolatility(x[,c("High","Low")]))[,1]
T_CLV <- function(x) EMA(CLV(HLC(x)))[,1]
T_EMV <- function(x) EMV(x[,c("High","Low")],x[,"Volume"])[,2]
T_MACD <- function(x) MACD(Cl(x))[,2]
T_MFI <- function(x) MFI(x[,c("High",'Low',"Close")],x[,"Volume"])
T_SAR <- function(x) SAR(x[,c("High","Close")])[,1]
T_Volat <- function(x) volatility(OHLC(x),salc="garman")[,1]
由于自变量过多,我们需要精简,接下来我们确定了预测变量是什么,接下俩的任务就是应用统计方法将变量确定,下面我们利用随机森林的输出变量的重要性来选择变量;它是通过计算每个变量移除后的随机森林误差的增加来估计变量的重要性,我们将使用包randomForest
library(randomForest)
data_model <- specifyModel(t_radio(DIA)~Delt(Cl(DIA),k=1:10)+T_ATR(DIA)+T_SMI(DIA)+T_ADX(DIA)+T_Aroon(DIA)+T_BB(DIA)+T_CV(DIA)+T_CLV(DIA)+CMO(Cl(DIA))+EMA(Delt(Cl(DIA)))+T_EMV(DIA)+T_Volat(DIA)+T_MACD(DIA)+T_MFI(DIA)+RSI(Cl(DIA))+T_SAR(DIA)+runMean(Cl(DIA))+runSD(Cl(DIA)))
现在我们已经构造好了模型需要的公式,我们接下来就可以构造随机森林了,通过随机森林输出模型的重要性进行选择自变量;这里我们选取截止到2009年末的数据够造随机森林模型,子树我们选择初始值500进行建模,然后在通过画图找出通过函数varImPlot()绘制各个变量的得分;然后通过设定得分的界限值;超过界限值的我就给予选取
rf <- buildModel(data_model,method = "randomForest",training.per = c(start(DIA),index(DIA["2009-12-31"])),ntree=500,importance=T)
plot(rf)
通过以上图可以得知,模型在子树约在120后误差趋于稳定,所以我们就选取ntree=120进行建模
rf <- buildModel(data_model,method = "randomForest",training.per = c(start(DIA),index(DIA["2009-12-31"])),ntree=120,importance=T)
rf
从结果上看,能解释数据55%的方差;感觉还可以吧,不过我们并不是用这模型进行预测,知识用来进行变量的选择
能解释55%,接下来我们输出各个变量的得分分布图
varImpPlot(rf@fitted.model,type = 1)
从上图看我们的变量的重要性最高的是runMean,这里我们随意设一个限制值过滤些我们认为不重要的变量,所以我这里设置为10;
rf_imp <- importance(rf@fitted.model,type = 1)
rownames(rf_imp)[which(rf_imp>10)]
所以我们这里得到了5个,所以我们得到结果;
data_model <- specifyModel(t_radio(DIA)~T_ATR(DIA)+T_SMI(DIA)+T_ADX(DIA)+T_SAR(DIA)+runMean(Cl(DIA)))
data_model
得到结果如下
这时候数据集已经构造好了,我们这时候只需要将数据分为一个是训练集,一个是测试集,
Tdata_train <- as.data.frame(modelData(data.model,data.window = c("1960-01-01","1999-12-31")))#训练数据集
Tdata_eval <- na.omit(as.data.frame(modelData(data.model,data.window = c("2000-01-01","2016-08-15"))))#测试数据集
Tform <- as.formula('t_radio.DIA~.')
head(Tdata_eval)
从上结果看,我们的数据集已经成功分为两部分了,as.formula这个函数是让我们定义个公式给我们后面调用;
1.6预测任务
数据集我们已经构造好了,这里我们尝试将预测值转换成交易的信号,这里我们认为
当T_RADIO>0.1的时候我们可以认为是卖出
当-0.1<=T_RADIO<=0.1的时候我们认为是可以持有的
当T_RADIO>0.1的时候我们可以认为是买入的
因为我们认为至少高出一周5*0.02=0.1,当然我们也可以选择别的限定值,如果太小的界限可能导致太小的市场变化时交易,这里我们使用DMwR包中的函数trading.signals()进行转换
1.7信号模型评价规则
一般来说正确率确实是一个很好很直观的评价指标,但是有时候正确率高并不能代表一个模型就好。这里我们就只介绍三个评价信号的指标。
现实
YES NO
预测 YES TP TN
NO FN FN
精度(准确精度)
精度是精确性的度量,表示被分为正例的示例中实际为正例的比例,precision=TP/(TP+FP);
召回率(回溯精度)
召回率是覆盖面的度量,度量有多个正例被分为正例recall=TP/(TP+FN)
还有将这两个指标合成一个指标的F指标,我们称之为F度量Fb=[(1+b2)*P*R]/(b2*P+R),其中P代表精度,R代表召回率
1.8预测模型的选择
1.8.1神经网络
首先神经网络对预测问题中的变量的尺度敏感,在这种情况下,我们要考虑对数据进行标准化是很有意义的,
set.seed(1234)
library(nnet)
norm_data <- scale(Tdata_train) #数据进行标准化
nn <- nnet(Tform,norm_data[1:400, ],size=10,decay=0.01,maxit=1000,linout=T,trace=F)
norm_preds <- predict(nn,norm_data[401:800,])
preds <- unscale(norm_preds,norm_data)
sigs_nn <- trading.signals(preds,0.1,-0.1)
true_sign <- trading.signals(Tdata_train[401:800,'t_radio.DIA'],0.1,0.1)
sigs.PR(sigs_nn,true_sign)
得到结果
这个结果上看对买入精确度和回溯精度有较好的预测,但是对卖出有较差的预测,这说明神经网络对我们来说预测性能不是特别好,所以我们多多尝试其他的模型
1.8.2支持向量机
支持向量机一般也是用来处理预测和分类问题,也是我们较为常用的模型之一
set.seed(1234)
library(e1071)
install.packages("e1071")
sv <- svm(Tform,Tdata_train[1:400,],gama=0.001,cost=100)
s_preds <-predict(sv,Tdata_train[401:800,])
sigs_svm <- trading.signals(s_preds,0.1,-0.1)
true_sign <- trading.signals(Tdata_train[401:800,'t_radio.DIA'],0.1,-0.1)
sigs.PR(sigs_svm,true_sign)
从上看这个结果也不是特别好,虽然卖出的回溯和精确度提高了,但买入的相应下降了
1.8.3随机森林
set.seed(1234)
rf <- randomForest(Tform,Tdata_train[1:404,],ntree=500)
rf_spreds <- predict(rf,Tdata_train[401:800,])
sigs_rf <- trading.signals(rf_spreds,0.1,-0.1)
true_sign <- trading.signals(Tdata_train[401:800,'t_radio.DIA'],0.1,-0.1)
sigs.PR(sigs_rf,true_sign)
从结果上看,模型的精确度大幅的提高,回溯精确度还是和其他模型没什么区别;这里就说到这里了
1.9总结
文章的代码可以直接COPY在R上运行,所以大家可以一起敲下看看自己的结果如何;这个文章各个模型就没怎么说明了,都在我的博客有介绍,本来想详细的说一下关于评价指标的知识的,不过感觉和本文主要用的不太搭,所以就没怎么写,望见谅;本人菜鸟,有错误还请大牛指教,谢谢!