深度神经网络 (第 I 部)。准备数据(基础篇)
📘

深度神经网络 (第 I 部)。准备数据(基础篇)

第 1/3 篇

「把 MT5 行情喂进深度网络前先过哪道手」

DNN 在语言与图像识别里已经跑通,挪到算法交易上同样有得折腾,但第一步永远是数据。MetaTrader 5 终端导出的原始报价和指标序列,不能直接丢进多层全连接网络,得先做准备、评估,再叠加多种变换放大特征。 原文作者从 2017 年 9 月发布的系列起手,明确只采用多层全连接网络做实验,不碰卷积或递归结构。整组文章四个落点里,本节只啃第一块:从终端接数据、洗数据、做变换。 实操上,开 MT5 把目标品种的历史报价用 CSV 或标准接口取出,先按窗口切片、去量纲,再试几类变换(差分、标准化、小波之类)观察分布变化——这一步没做扎实,后面 darch 包调参都是空转。外汇与贵金属杠杆高、滑点跳空频繁,变换时务必保留样本外时间段,避免过拟合假象。

◍ 从报价到目标变量搭原始数据集

做行情建模的第一步,是把 MT5 导出的原始报价转成可喂给统计环境的矩阵。以 EURUSD 为例,若取 M1 周期最近 5000 根 K 线,收盘价序列就构成最基础的预测源;用 R 读入后先按时间对齐,避免周末跳空造成行偏移。 预测列通常取未来 N 根的收益率方向,目标变量可设为「收盘价减去当前价再除以当前价」得到的归一化变动。这样原始数据集合至少包含:时间戳、开高低收、预测窗口收益、目标标签三类的字段。 数据清理时优先剔除点差异常放大时段的行——比如重大非农公布后 5 分钟内报价断层,这类样本会污染后续分布。异常值不急着删,先用箱线线看是否在 1.5 倍 IQR 外,偏态明显时再做对数变换。外汇与贵金属杠杆高,样本若混入流动性枯竭段,模型在外盘实盘大概率失效。

DNN 实验前的数据与工具准备

深度神经网络从开发到上线,必须按阶段走:先备好实验用的输入/输出数据,再做网络的创建、训练、测试和调参。前者通常吃掉约 70% 的工期,决定模型上限——数据脏,出来的结果必然没用。 要复现文中的回测实验,环境得是 MRO 3.4.0 加 RStudio,安装步骤网上和随附文件里都有,不在这里展开。 R 这门语言 1996 年由 Ross Ihaka 和 Robert Gentleman 在奥克兰大学搞出来,属 GNU 开源项目,四大自由度(随意用、改、发、再分发)是底色。现在由 R 开发核心团队和 R 联盟维护,联盟里 IBM、Microsoft、Google、Oracle 都在列,背后资源不缺。 对做量化的人而言,R 的硬优势就几条:统计计算的事实标准、全球学界持续供血、数据挖掘的高级包齐全,而且新论文方法落地到 R 包往往不超过两周,最后它还完全免费。外汇和贵金属市场高波动高杠杆,用这类工具做特征工程前先认清样本外失效风险。

「从MT5报价里榨出建模用的原始帧」

价格行为派有个底层假设:已发生、正发生和将发生的走势,全藏在价格本身里。做量化探索前,先要把终端吐出来的裸数据整理成能算的表。财务数据本质是有层级、等间隔、永不结束的时间序列,基准行就是某时间帧下的 OHLCV 报价,其余序列都是它的衍生物。 在 EURJPY 的 M15 周期上,从终端拿到 (o,h,l,cl,v,d) 向量后,写个函数把柱线起始时间转成 POSIXct,再塞进数据帧 pr。实测样本为 8000 根柱线,起算日 2017-01-10,末根 2017-05-05,这段窗口足够跑一轮自适应滤波器的初步观察。 预测侧只用一组精简滤波器:FATL、SATL、RFTL、RSTL 四条自适应趋势线,外加监控其变化率的 FTLM、STLM,以及 RBCI、PCCI 两个振荡器。目标变量用 ZigZag,最小弯曲设 25 点(4 位小数精度),取其一阶差分的符号作为方向信号。所有变量算完丢进子环境 env,不污染全局,方便后续混用多符号多周期而不撞名。 下面这段 R 代码就是接收终端向量并成帧的函数,注意它用 rev() 把终端倒序缓存翻正,时区硬写 CET: 别在全局环境里堆变量 子环境隔离后,换其他品种拉数据也不会把 pr 覆盖掉,回测多标的时这点很关键。

MQL5 / C++
#---pr.OHLCV-------------------
pr.OHLCV <- function(d, o,  h,  l,  cl, v){
# (d, o,  h,  l,  cl, v)- vector
  require(&class="macro">#x27;magrittr&class="macro">#x27;)
  require(&class="macro">#x27;dplyr&class="macro">#x27;)
  require(&class="macro">#x27;anytime&class="macro">#x27;)
  price <- cbind(Data = rev(d),
                     Open = rev(o), High = rev(h),
                     Low = rev(l), Close = rev(cl),
                     Vol = rev(v)) %>% as.tibble()  
  price$Data %<>% anytime(., tz = "CET")
  class="kw">return(price)
}
evalq({pr <- pr.OHLCV(Data, Open, High, Low, Close, Volume)
        rm(list = c("Data", "Open", "High", "Low", "Close", "Volume"))
       },
env)

◍ 典型价格与差分项的预处理定义

在把行情喂给数字滤波器之前,先把每根 K 线的几个基准价和相对位移算清楚。下面这段 R 风格代码定义了 Med、Typ、Wg 三种均价,以及相对开盘价的 Close/High/Low 偏移量 #CO、#HO、#LO,还有高低价的差分 dH、dL。 Med = (High + Low)/2 是中价,Typ = (High + Low + Close)/3 是经典典型价,Wg = (High + Low + 2*Close)/4 给收盘更高权重。#CO = Close - Open 直接反映实体方向,dH = c(NA, diff(High)) 取最高价一阶差分,首值补 NA。 DigFiltr 函数里写死了两组系数:fatl 长度 40,首项 +0.4360409450、末项 +0.0040364019;rftl 长度 25,首项 -0.0025097319、峰值在中间 +0.2025269304。这两组浮点向量就是后续卷积滤波的核,直接复制到 MT5 自定义指标里做 dot product 即可验证频响。 外汇与贵金属波动无序,这类预处理只是把原始 OHLC 投影到更平滑的空间,不预示任何方向,实盘前请在策略测试器用历史数据跑一遍系数卷积。

MQL5 / C++
Med = (High + Low)/class="num">2,
Typ = (High + Low + Close)/class="num">3,
Wg  = (High + Low + class="num">2 * Close)/class="num">4,
class="macro">#CO  = Close - Open,
class="macro">#HO  = High - Open,
class="macro">#LO  = Low - Open,
dH  = c(NA, diff(High)),
dL  = c(NA, diff(Low))
),
env)
#-----DigFiltr-------------------------
DigFiltr <- function(X, type = class="num">1){
#  X - vector
  require(rowr)
  fatl <- c( +class="num">0.4360409450, +class="num">0.3658689069, +class="num">0.2460452079, +class="num">0.1104506886, -class="num">0.0054034585,
             -class="num">0.0760367731, -class="num">0.0933058722, -class="num">0.0670110374, -class="num">0.0190795053, +class="num">0.0259609206,
             +class="num">0.0502044896, +class="num">0.0477818607, +class="num">0.0249252327, -class="num">0.0047706151, -class="num">0.0272432537,
             -class="num">0.0338917071, -class="num">0.0244141482, -class="num">0.0055774838, +class="num">0.0128149838, +class="num">0.0226522218,
             +class="num">0.0208778257, +class="num">0.0100299086, -class="num">0.0036771622, -class="num">0.0136744850, -class="num">0.0160483392,
             -class="num">0.0108597376, -class="num">0.0016060704, +class="num">0.0069480557, +class="num">0.0110573605, +class="num">0.0095711419,
             +class="num">0.0040444064, -class="num">0.0023824623, -class="num">0.0067093714, -class="num">0.0072003400, -class="num">0.0047717710,
              class="num">0.0005541115,  class="num">0.0007860160,  class="num">0.0130129076,  class="num">0.0040364019 )
  rftl <- c(-class="num">0.0025097319, +class="num">0.0513007762 , +class="num">0.1142800493 , +class="num">0.1699342860 , +class="num">0.2025269304 ,
            +class="num">0.2025269304, +class="num">0.1699342860 , +class="num">0.1142800493 , +class="num">0.0513007762 , -class="num">0.0025097319 ,
            -class="num">0.0353166244, -class="num">0.0433375629 , -class="num">0.0311244617 , -class="num">0.0088618137 , +class="num">0.0120580088 ,
            +class="num">0.0233183633, +class="num">0.0221931304 , +class="num">0.0115769653 , -class="num">0.0022157966 , -class="num">0.0126536111 ,
            -class="num">0.0157416029, -class="num">0.0113395830 , -class="num">0.0025905610 , +class="num">0.0059521459 , +class="num">0.0105212252 ,

把三类残差序列直接喂进 MT5 验证

上面贴出的三组数值,分别是短周期残差 satl、长周期残差 rstl 以及一组未命名偏移量,各含 60 个浮点样本。satl 从 +0.0982862174 单调衰减到末段 +0.0161380976,中间在 -0.0234566315 附近触底,说明该类滤波在中段对趋势的剥离最彻底。 rstl 则全程递增,从 -0.0074151919 走到 +0.0440399188,线性爬升特征明显,和 satl 的凹形轨迹刚好互补。把这两列同时画在 MT5 的自定义指标缓冲区里,能直观看到两者交叉点往往对应盘整突破的临界区。 实操上,复制下面 R 风格向量到脚本里转成 double 数组,用 CopyBuffer 推到图表做叠加。外汇与贵金属波动剧烈,此类残差仅描述历史形态,后续方向仍可能反转,请先用模拟盘核对。

常见问题

先按固定周期切片报价,计算收益率和差分项,再拼成带标签的输入帧,避免直接用原始价格。
原始价格有趋势和量纲问题,差分能去趋势、稳方差,模型更容易学到可复用规律。
可以,小布能按你设的周期和字段自动抽取报价、算差分并生成样本帧,省去手写脚本。
把三类残差直接回看历史区间,确认无显著自相关且波动稳定,再考虑进模型。
常漏掉目标变量对齐:预测窗口和特征帧必须严格错位,否则会带来未来函数泄漏。