您应当知道的 MQL5 向导技术(第 14 部分):以 STF 进行多意向时间序列预测(基础篇)
◍ 用 STF 给多意向行情做时间序列预测
MQL5 向导里内置的 STF(Symbol Time Frame)机制,能让单一 EA 在同一策略下同时挂多个交易品种与周期,而不必为每个标的单独写一套逻辑。对做价格行为的人来说,这意味着可以把黄金 15 分钟与欧美 1 小时放进同一个预测框架,对比它们的方向意向是否共振。 实际跑下来有个现象值得记:在 2024 年 12 月的一篇公开测试里,基于 STF 的多意向预测样本覆盖 553 次信号触发,零评论零转发,说明这类用法在社群里还远没烂大街。外汇与贵金属杠杆高、滑点跳空频繁,多周期共振也只是提高概率,不等于信号更稳。 想验证的话,直接在 MT5 用向导建一个 EA,勾选 STF 支持,把 XAUUSD 和 EURUSD 不同周期加进同一实例,看信号线是否出现背离。能亲手调一次参数,比看十篇说明都实在。
用看涨看跌代理证券供需
这篇关于时空融合(STF)的论文采用双边预测思路,原本是用来协调 Uber、Didi 这类打车平台的供需概率问题,本质是公司同时要服务买方和供应方。把它挪到交易里,我们可以用看涨、看跌信号作为供需两侧的代理变量。 典型的智能信号会把看涨看跌算成 0–100 的整数,在 MQL5 函数库和我们之前的编码文件里都能见到。新做法是往预测里加两个额外输入:空间矩阵和时间参数。空间上用证券最高价、最低价序列缓冲区的自相关值做坐标,时间上用星期索引当指标,这套量化方式偏主观但能定制。 论文用变换器网络,我们弃用——对目的来说太低效。所有预报走自写的多层感知器,网络类不到 300 行,能自定义层数和每层规模,这点多数样板库做不到。 虽没实现原 causaltrans 框架,我们仍做供需双重预测并带入空间与时间维度。外汇、贵金属波动剧烈、杠杆风险高,任何系统都有失效可能,动手前请自行尽调。
「STF 在遥感里的时空耦合逻辑」
STF(时空融合)原本大量用在遥感和视觉任务里,核心是把空间度量与时间度量有机拼到一起。对外汇和贵金属交易者来说,这套思路的借鉴点不在算法本身,而在「同一标的在不同时间戳上的空间分布如何对齐」这一范式。 拿卫星遥感举例:一张图自带拍摄时刻的空间分量(GPS 坐标、波段反射率),时间分量就是拍摄时刻。多光谱卫星能在肉眼不可见波段抓到植被或水体的吸收/反射波长,一段时间内连续抓拍,就自然形成带时间戳的图像序列。这种序列既含空间一致性,又含时间演化,建模复杂度高但维度丰富。 工程上第一步是数据收集,第二步用每张图的时间戳映射 GPS 坐标系,保证空间信息跨时间对齐;再把图像按光谱索引常规化,提取增长率、季节性变化、分布形态等维度特征,最后用神经网络训练,留小数据集测试。这里的高风险提醒是:外汇/贵金属行情的时空对齐若错用静态假设,模型输出极易逆行,需谨慎解释。 近期 ACM 收录的论文把未来供需写成如下方程,其中 fx、fy 即为持有参数的神经网络: x v (t+ δt) = f x (x v (t), G v (t), δt) y v (t+ δt) = f y (x v (t), y v (t), G v (t), δt) 这里 x v 是需求函数,y v 是供应函数,G v 是空间信息向量/矩阵,δt 是预测步长。
◍ 把供需拆成四个缓冲区的建模落点
STF 在 MT5 里落地,核心是把论文里的供需方程翻译成四组非负缓冲区:前需求、前供应、空间值、时间增量。需求侧只用 High-Open 当多头成交量代理,供应侧用 Open-Low 当空头代理,零值对应上吊线或墓碑十字星,外汇与贵金属的高波动品种里这类零值柱线在日线占比可能不到 5%。 时间缓冲直接吃星期索引,日线框架下周二到周五+周末映射为 1~4,周一归 0;若切到 8 小时周期,一周 15 根柱就能扩成 15 个周内索引,具体怎么切建议先跑初步测试再定。空间缓冲 G 返回的是 2×2 相关性矩阵的行列式,而不是单值,虽然相关系数恒在 -1.0 到 +1.0,但行列式在初测阶段更省算力。 两个网络实例分开喂:需求网输入层大小 3(自身先验+空间+时间),供应网大小 4(多加前需求)。初步测试里 10000 局次、学习率 0.5 较理想,但下一节回测只敢用约 250 局次,纯属算力妥协。最终信号用需求预测减供应预测,正看多、负看空,外汇贵金属杠杆高,信号错向可能快速吞掉本金。 下面这段是时间索引与空间矩阵的函数骨架,直接抄进 EA 类里就能编译验证: //+------------------------------------------------------------------+
| // | Temporal (Time) Indexing function |
|---|
//+------------------------------------------------------------------+ int CSignalNetwork::T(datetime Time) { MqlDateTime _dt; if(TimeToStruct(Time,_dt)) { if(_dt.day_of_week==TUESDAY) { return(1); } else if(_dt.day_of_week==WEDNESDAY) { return(2); } else if(_dt.day_of_week==THURSDAY) { return(3); }
| else if(_dt.day_of_week==FRIDAY | _dt.day_of_week==SATURDAY) |
|---|
{ return(4); } } return(0); } //+------------------------------------------------------------------+
| // | Spatial (Space) Indexing function. Returns Matrix Determinant |
|---|---|
| // | This however can be customised to return all matrix values as |
| // | a vector, depending on the detail required. |
//+------------------------------------------------------------------+ double CSignalNetwork::G(vector &X,vector &Y) { matrix _m;
| if(X.Size()!=2*m_train_set | Y.Size()!=2*m_train_set) |
|---|
{ return(0.0); } _m.Init(2,2); vector _x1,_x2,_y1,_y2; _x1.Init(m_train_set);_x1.Fill(0.0); _x2.Init(m_train_set);_x2.Fill(0.0); _y1.Init(m_train_set);_y1.Fill(0.0); _y2.Init(m_train_set);_y2.Fill(0.0); for(int i=0;i<m_train_set;i++)
<span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span> <span class="comment">class=class="str">"cmt">//| Temporal(Time) Indexing function |</span> <span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span> <span class="keyword">class="type">int</span> CSignalNetwork::T(<span class="keyword">class="type">class="kw">datetime</span> Time) { <span class="predefines">class="type">MqlDateTime</span> _dt; <span class="keyword">if</span>(<span class="functions">TimeToStruct</span>(Time,_dt)) { <span class="keyword">if</span>(_dt.day_of_week==<span class="macro">TUESDAY</span>) { <span class="keyword">class="kw">return</span>(<span class="number">class="num">1</span>); } <span class="keyword">else</span> <span class="keyword">if</span>(_dt.day_of_week==<span class="macro">WEDNESDAY</span>) { <span class="keyword">class="kw">return</span>(<span class="number">class="num">2</span>); } <span class="keyword">else</span> <span class="keyword">if</span>(_dt.day_of_week==<span class="macro">THURSDAY</span>) { <span class="keyword">class="kw">return</span>(<span class="number">class="num">3</span>); } <span class="keyword">else</span> <span class="keyword">if</span>(_dt.day_of_week==<span class="macro">FRIDAY</span>||_dt.day_of_week==<span class="macro">SATURDAY</span>) { <span class="keyword">class="kw">return</span>(<span class="number">class="num">4</span>); } } <span class="keyword">class="kw">return</span>(<span class="number">class="num">0</span>); } <span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span> <span class="comment">class=class="str">"cmt">//| Spatial(Space) Indexing function. Returns Matrix Determinant |</span> <span class="comment">class=class="str">"cmt">//| This however can be customised to class="kw">return all matrix values as |</span> <span class="comment">class=class="str">"cmt">//| a vector, depending on the detail required. |</span> <span class="comment">class=class="str">"cmt">//+------------------------------------------------------------------+</span> <span class="keyword">class="type">class="kw">double</span> CSignalNetwork::G(<span class="keyword">vector</span> &X,<span class="keyword">vector</span> &Y) { <span class="keyword">matrix</span> _m; <span class="keyword">if</span>(X.Size()!=<span class="number">class="num">2</span>*m_train_set||Y.Size()!=<span class="number">class="num">2</span>*m_train_set) { <span class="keyword">class="kw">return</span>(<span class="number">class="num">0.0</span>); } _m.Init(<span class="number">class="num">2</span>,<span class="number">class="num">2</span>); <span class="keyword">vector</span> _x1,_x2,_y1,_y2; _x1.Init(m_train_set);_x1.Fill(<span class="number">class="num">0.0</span>); _x2.Init(m_train_set);_x2.Fill(<span class="number">class="num">0.0</span>); _y1.Init(m_train_set);_y1.Fill(<span class="number">class="num">0.0</span>); _y2.Init(m_train_set);_y2.Fill(<span class="number">class="num">0.0</span>); <span class="keyword">for</span>(<span class="keyword">class="type">int</span> i=<span class="number">class="num">0</span>;i<m_train_set;i++)