期货量化交易软件:采用栈式 RBM 的深度神经网络。
本文是有关深度神经网络和预测器选择的前文之续篇。在此我们将涵盖由栈式 RBM 初始化的深度神经网络特性, 以及它在 "darch" 软件包里的实现。还将揭示使用隐藏的马尔科夫模型来改进神经网络预测性能的可能性。总之, 赫兹期货量化将以程序化方式实现一个可操作的智能交易程序。
目录

编辑切换为居中
1. DBN 的结构
2. 数据的准备及选择
2.1. 输入变量
2.2. 输出变量
2.3. 初始化数据帧
2.3.1. 删除高相关性变量
2.4. 最重要变量的选择
3. 实验部分。
3.1. 构建模型
3.1.1. "darch" 软件包的简述
3.1.2. 构建 DBN 模型。参数。
3.2. 训练和测试样品的形成。
3.2.1. 分级平衡和预处理。
3.2.2. 目标变量编码
3.3. 训练模型
3.3.1. 预训练
3.3.2. 微调
3.4. 测试模型。标尺。
3.4.1. 预测解码。
3.4.2. 改善预测结果
校验
使用马尔科夫链模型进行平滑
在理论性平衡曲线上校正预测信号
3.4.3. 标尺
4. 智能交易程序的结构
4.1. 智能交易程序操作的描述
4.2. 自控制。自训练
安装和启动
改进定性指标的方式方法。
结论
概论 在准备进行实验的数据时, 赫兹期货量化将使用来自 前文 中有关评估和选择预测的变量。赫兹期货量化将形成初始样本, 清理它并选择重要的变量。 我们将研究为了训练、测试和验证而划分样本的方法。 我们将使用 "darch" 软件包构建一个 DBN 网络模型, 并用我们的数据对它进行训练。在模型之后测试, 我们将能获得评估模型质量的标尺。我们将研究软件包所提供的神经网络设置的多种配置机会。 另外, 我们会看到隐藏的马尔科夫模型将如何帮助我们改进神经网络预测。 我们将开发一款智能交易系统, 根据持续监测的结果, 在不打断交易的情况下对模型进行定期训练。在 EA 中将使用来自 "darch" 软件包的 DBN 模型。我们还将结合使用来自 前文 的 SAE DBN 构建智能交易系统。 再有, 我们将指点改进模型的定性指标的方式i和方法。1. 由栈式 RBM (DN_SRBM) 初始化的深层神经网络的结构我记得 DN_SRBM 是由 n 个等于神经网络隐藏层数的 RBM 组成, 基本上是神经网络本身。训练包括两个阶段。 第一阶段涉及预训练。每个 RBM 无需监督者即可依据输入集合系统地训练 (无目标)。在隐藏层的权重之后, RBM 被转移到相关的神经网络隐藏层。 第二阶段涉及微调, 在此神经网络由监督者训练。前文中已提供了有关它的详细信息, 所以我们在此不再复述。我将简单叙述, 不像我们前文用过的 "deepnet" 软件包, "darch" 软件包帮助我们实现更广泛的机会来构建并微调模型。更多详细信息将在创建模型时提供。图例. 1 显示 DN_SRBM 的结构和处理过程

编辑切换为居中
图例. 1. DN SRBM 的结构 2. 数据的准备及选择 2.1. 输入变量 (征兆, 预测器) 在前文中, 我们研究过预测器的评估和选择, 所以在此无需提供额外信息。我仅论及我们使用的 11 款指标 (所有的振荡器: ADX, aroon, ATR, CCI, chaikinVolatility, CMO, MACD, RSI, stoch, SMI, volatility)。选择了来自一些指标的若干变量。这样就形成了 17 个变量的输入集。赫兹期货量化从 EURUSD 里取最后 6000 根柱线的报价, 2016 年 02 月 14 日 M30 时间帧, 并使用 In() 函数计算指标值。 #---2--------------------------------------------- In <- function(p = 16){ require(TTR) require(dplyr) require(magrittr) adx <- ADX(price, n = p) %>% as.data.frame %>% mutate(.,oscDX = DIp - DIn) %>% transmute(.,DX, ADX, oscDX) %>% as.matrix() ar <- aroon(price[ ,c('High', 'Low')], n = p) %>% extract(,3) atr <- ATR(price, n = p, maType = "EMA") %>% extract(,1:2) cci <- CCI(price[ ,2:4], n = p) chv <- chaikinVolatility(price[ ,2:4], n = p) cmo <- CMO(price[ ,'Med'], n = p) macd <- MACD(price[ ,'Med'], 12, 26, 9) %>% as.data.frame() %>% mutate(., vsig = signal %>% diff %>% c(NA,.) %>% multiply_by(10)) %>% transmute(., sign = signal, vsig) %>% as.matrix() rsi <- RSI(price[ ,'Med'], n = p) stoh <- stoch(price[ ,2:4], nFastK = p, nFastD =3, nSlowD = 3, maType = "EMA") %>% as.data.frame() %>% mutate(., oscK = fastK - fastD) %>% transmute(.,slowD, oscK) %>% as.matrix() smi <- SMI(price[ ,2:4],n = p, nFast = 2, nSlow = 25, nSig = 9) kst <- KST(price[ ,4])%>% as.data.frame() %>% mutate(., oscKST = kst - signal) %>% select(.,oscKST) %>% as.matrix() In <- cbind(adx, ar, atr, cci, chv, cmo, macd, rsi, stoh, smi, kst) return(In) } 我们将在输出上获得输入数据矩阵。 2.2输出数据 (目标白能量) 我们采用取自 ZZ 的信号作为目标变量。函数计算之字折线信号: #----3------------------------------------------------ ZZ <- function(pr = price, ch = ch , mode="m") { require(TTR) require(magrittr) if (ch > 1) ch <- ch/(10 ^ (Dig - 1)) if (mode == "m") {pr <- pr[ ,'Med']} if (mode == "hl") {pr <- pr[ ,c("High", "Low")]} if (mode == "cl") {pr <- pr[ ,c("Close")]} zz <- ZigZag(pr, change = ch, percent = F, retrace = F, lastExtreme = T) n <- 1:length(zz) dz <- zz %>% diff %>% c(., NA) sig <- sign(dz) for (i in n) { if (is.na(zz[i])) zz[i] = zz[i - 1]} return(cbind(zz, sig)) } 函数参数: pr = 价格 – OHLCMed 报价的矩阵; ch – 之字折线弯曲的最小长度点数 (4 位) 或是实际项 (例如, ch = 0.0035); mode – 应用的价格 ("m" - 中间价, "hl" - 最高价和最低价, "cl" - 收盘价), 省缺使用中间价。 函数返回两个变量的矩阵 — 事实上, 之字折线和信号, 是在之字折线角度范围 [-1;1] 的基础上取得的。我们将信号向左平移一根柱线 (朝向未来)。这个特定的信号将用于训练神经网络。 我们计算信号时 ZZ 弯曲长度至少 37 点 (4 位)。 > out <- ZZ(ch = 37, mode = "m") Loading required package: TTR Loading required package: magrittr > table(out[ ,2]) -1 1 2828 3162 如我们所见, 分级略有失衡。当形成用于训练模型的样本时, 我们将采取必要的措施来令它们平衡。 2.3. 初始化数据帧 我们来编写创建初始数据帧的函数, 清理不确定的数据 (空) 并转换目标变量至两个分级的因子 "-1" 和 "+1"。函数组合之前编写的函数 In() 和 ZZ()。我们将立即裁剪最后 500 根柱线, 用于评估模型预测质量。 #-----4--------------------------------- form.data <- function(n = 16, z = 37, len = 500){ require(magrittr) x <- In(p = n) out <- ZZ(ch = z, mode = "m") data <- cbind(x, y = out[ ,2]) %>% as.data.frame %>% head(., (nrow(x)-len))%>% na.omit data$y <- as.factor(data$y) return(data) } 2.3.1. 删除高相关性变量 我们将从初始集合里面删除相关性系数高于 0.9 的变量。我们将编写形成初始数据帧的函数, 删除高相关性变量并返回清理后数据。 我们可以预先检查哪一个变量的相关性系数高于 0.9。 > data <- form.data(n = 16, z = 37) # 准备数据帧 > descCor <- cor(data[ ,-ncol(data)])# 删除目标变量 > summary(descCor[upper.tri(descCor)]) Min. 1st Qu. Median Mean 3rd Qu. Max. -0.1887 0.0532 0.2077 0.3040 0.5716 0.9588 > highCor <- caret::findCorrelation(descCor, cutoff = 0.9) > highCor [1] 12 9 15 > colnames(data[ ,highCor]) [1] "rsi" "cmo" "SMI" 因此, 以上列出的变量可以删除。我们将从数据帧里删除它们。 > data.f <- data[ ,-highCor] > colnames(data.f) [1] "DX" "ADX" "oscDX" "ar" "tr" [6] "atr" "cci" "chv" "sign" "vsig" [11] "slowD" "oscK" "signal" "vol" "Class" 我们可在一个函数里紧凑地编写它: #---5----------------------------------------------- cleaning <- function(n = 16, z = 37, cut = 0.9){ data <- form.data(n, z) descCor <- cor(data[ ,-ncol(data)]) highCor <- caret::findCorrelation(descCor, cutoff = cut) data.f <- data[ ,-highCor] return(data.f) } > data.f <- cleaning() 并非所有软件包的作者和研究人员都同意将高相关性的数据从集合中删除。不过, 两种使用结果会在此进行比较。在我们的情况中, 我们选择的选项是删除。 2.4. 最重要变量的选择 重要变量的选择基于三个指标: 按照分级的全局重要性, 局部重要性 (结合) 和部分重要性。我们要把握前文详述的 "randomUniformForest" 软件包的机会。为了紧凑性, 所有之前和之后的动作均在一个函数收集。一旦执行, 赫兹期货量化将获取三个集合作为结果:
具有最佳贡献和交互的变量;
对于分级 "-1" 的最佳变量;
对于分级 "+1" 的最佳变量。
#-----6------------------------------------------------ prepareBest <- function(n, z, cut, method){ require(randomUniformForest) require(magrittr) data.f <<- cleaning(n = n, z = z, cut = cut) idx <- rminer::holdout(y = data.f$Class) prep <- caret::preProcess(x = data.f[idx$tr, -ncol(data.f)], method = method) x.train <- predict(prep, data.f[idx$tr, -ncol(data.f)]) x.test <- predict(prep, data.f[idx$ts, -ncol(data.f)]) y.train <- data.f[idx$tr, ncol(data.f)] y.test <- data.f[idx$ts, ncol(data.f)] #--------- ruf <- randomUniformForest( X = x.train, Y = y.train, xtest = x.test, ytest = y.test, mtry = 1, ntree = 300, threads = 2, nodesize = 1 ) imp.ruf <- importance(ruf, Xtest = x.test) best <- imp.ruf$localVariableImportance$classVariableImportance %>% head(., 10) %>% rownames() #-----部分重要 best.sell <- partialImportance(X = x.test, imp.ruf, whichClass = "-1", nLocalFeatures = 7) %>% row.names() %>% as.numeric() %>% colnames(x.test)[.] best.buy <- partialImportance(X = x.test, imp.ruf, whichClass = "1", nLocalFeatures = 7) %>% row.names() %>% as.numeric() %>% colnames(x.test)[.] dt <- list(best = best, buy = best.buy, sell = best.sell) return(dt) }