English Русский Español Deutsch 日本語 Português
preview
交易中的神经网络:面向准确分类的有效特征提取(Mantis)

交易中的神经网络:面向准确分类的有效特征提取(Mantis)

MetaTrader 5交易系统 |
38 0
Dmitriy Gizlyk
Dmitriy Gizlyk

引言

在毫秒级差异、微小价格波动都至关重要的交易领域,交易者所追求的工具,不仅要能够预测未来价格走势,还需要对图表上最复杂的形态完成精准分类。在此背景下,论文《Mantis:便于使用的轻量级校准时间序列分类基础模型》中提出的基础模型Mantis,为时间序列分析开启了全新篇章。凭借轻量化设计、精心设计的架构以及良好的概率校准能力,Mantis可以快速将分类器集成到交易系统中,并输出可靠的置信度估计,服务于风险管理。

作者指出,传统用于预测后续数值的模型往往运行效率低下:每适配一套新策略都需要细致的微调,且剧烈的波动率冲击会严重损害模型效果。尽管近年来时间序列预测基础模型取得了令人瞩目的效果,但这类模型本质上面向回归任务设计,并不适合对市场状态做分类。Mantis框架引入对比预训练,恰好填补了这一技术空白。

其理念简洁巧妙:将时间序列切分为一系列分块(patch),借鉴计算机视觉领域的 视觉Transformer,使用混合注意力机制。然而,经典的全局注意力机制具备二次复杂度,面对高频数据会成为性能瓶颈。为缓解该问题,Mantis同时使用局部token与全局token —— 局部token通过小窗口卷积与池化得到,全局token聚合整个片段的趋势信息。二者结合,模型复杂度相对序列长度近似呈线性扩展,同时既可以捕捉小幅波动,也能够识别长期模式。

Mantis的对比预训练是其核心关键技术:把同一段时序经过不同增强变换后的样本在特征空间拉近,同时把差异巨大的不同时序样本相互推远。最终,同一形态经过不同形变后的嵌入向量会在空间中聚类,而不同市场事件的向量则相互分离。即便行情波峰波谷的幅度、出现时间发生偏移,该策略依然能够让模型学到各类形态的稳定特征。

对于交易者而言,一个关键问题是评估开仓的安全性:仅仅输出“这是趋势反转”远远不够,还需要知道模型给出该结论的置信程度。Mantis通过内置温度缩放模块解决该问题:对输出logits做调整,让后验概率更加贴合样本实际属于某一类的真实发生概率。因此,当信号给出“80%反转概率”时,交易者可以预期该信号大约五分之四的情况是有效的。

作者还重点研究了多变量分析:算法交易中经常同时使用数十项指标(移动平均线、RSI、成交量、货币对相关性等)。如果直接把全部特征通道简单拼接为单一高维表征,会造成参数量爆炸、内存占用飙升;而只分析单变量序列,又会丢失通道之间的关联信息。因此,框架内置轻量化适配器,将跨通道交互信息压缩到紧凑的特征空间,同时保留不同指标之间的关联关系。

为直观展示Mantis的实际价值,我们以加密货币市场的“闪崩”场景举例:一秒之内价格暴跌数个百分点,随后又快速反弹。传统模型可能会把这种异常行情判定为噪声,直接忽略交易信号。Mantis经过数百万条真实与合成样本的预训练,能够识别这类事件属于“假性异动”还是“真正反转”,输出“短期异常”或“真实反转”标签并附带不同置信度,帮助交易者制定合理的资金保护策略。

另一个现实案例是科技股的市场状态分类。上升趋势阶段,受整体消息面影响,各类资产价格走势基本同步;而进入回调阶段,各个资产的走势会出现分化。依托内置适配器,Mantis可以捕捉这类跨通道差异:同类资产之间相关性降低,就会被模型识别为回调周期开启的信号,并同步输出置信度。


Mantis算法

Mantis框架证明,精巧的架构设计与完备的训练流程,可以将一系列算法构想转化为一套可靠工具。该基础模型方案建立在四大核心支柱之上:时间序列Token化、混合注意力、多变量数据适配器,以及自监督对比预训练 + 概率校准流程。

Mantis的核心设计思路,摒弃将时间序列切分为固定大小窗口的传统做法。改为将序列切分为固定数量的分块,这样就不再受输入序列长度影响,计算开销也得以稳定。举例来说,长度1024与2048的两条时序,都会被切为32个分块。该方法对于异构时间序列的大规模处理至关重要。

嵌入向量分多步生成。首先使用输出通道数为256的卷积层,将时间序列映射为更加紧凑的隐空间表征。接下来,对32个分块分别进行平均池化,得到维度为(32, 256)的张量。每个分块编码时序的局部特征,包含波峰、波动以及价格运动的微观形态。

与此同时,构建第二条数据流 —— 差分数据流,其基于时序相邻数值的一阶差分构建。该变换可以消除长期趋势,放大短期动态特征的信号。当需要关注偏离稳态水平、支撑阻力位附近的剧烈波动时,该模块尤为有效。

两条数据流执行完全相同的处理流程:卷积、均值池化、归一化。最终得到两组分块,每组包含32个维度256的token。模型同时获取信号形态本身以及信号随时间变化两方面均衡信息。

此外,还会提取其它两类信息:幅值尺度与波动率。方法是将时序均匀切分为32个窗口,计算每个窗口的均值与标准差。通过多尺度标量编码器对这些统计量编码,让模型捕捉信号的背景统计特征。因此,模型一共接收四路数据流:归一化原始数值、差分序列、窗口均值和窗口标准差。

四路数据流先各自经过线性投影层统一维度,再执行拼接融合。拼接后的嵌入经过投影层与层归一化,最终输出由32个256维token构成的时间序列表征。这些token作为通用载体,保存市场的行为特征与统计特征。

架构下一步引入分类token:这是一个可训练向量,用于聚合全部token的信息,使模型综合局部和全局模式,生成整条序列的最终表征。为保留分块之间的顺序信息,加入正弦位置编码,之后送入Transformer模块。

Transformer包含6层网络,每一层包含8头多头注意力机制、归一化层,以及带GELU激活的两层前馈网络。预训练阶段设置10%概率的dropout,用于抑制过拟合。全部层处理完成后,取分类token输出向量,作为整条序列最终嵌入。

Mantis采用自监督范式,并结合对比学习进行训练。模型会对原始时序执行多种数据增强。特别是在RandomCropResize(随机裁剪缩放)方法中,随机裁掉序列 0‑20% 长度,再将剩余片段拉伸恢复原始长度。该操作保留信号整体结构,不改变事件发生顺序。

对批次内每一个样本xi,随机生成两组增强样本,将得到的表征经过投影层,使用余弦相似度做比对。

随后计算交叉熵损失。

在该项研究工作中,作者使用10套数据集的合并样本对模型开展预训练,样本包含超过700万条时间序列。训练共进行100个轮次。批次大小设置为2048,硬件使用4块Tesla V100-32GB GPUs显卡。

微调阶段,在嵌入向量之后接入分类头。输出预测分值经过温度缩放处理,最小化期望校准误差,使模型输出结果可以按概率形式解读。

然而,时间序列的多变量特性依旧是主要难点之一。不同任务的特征通道数量各不相同,这就要求模型具备适配能力。与其他基础模型一样,Mantis最初采用单变量形式训练,对每一个通道使用同一套处理机制。该方式不仅会加大算力开销,还会忽略通道之间的相关性。

为解决上述局限,论文作者提出通道适配器:函数a,将原始d个输入通道转换为dnew个新通道。该方案可以让输入数据适配算力预算,保留时序结构,同时兼容任意模型。

这里,Mantis框架一共给出五种适配器的实现方案。前四种为经典降维算法:

  • PCA主成分分析:寻找正交特征空间,将绝大部分方差集中到数量更少的特征分量;
  • 截断奇异值分解:原理与PCA类似,但直接作用于未去中心化的数据矩阵;
  • 随机投影:通过随机线性映射将数据投影至低维空间;
  • 基于方差的通道筛选器:挑选方差最大的若干通道。

使用上述适配器时,数据会被重塑为(n*t, d)格式, 其中,n代表样本数量。投影矩阵W完成通道维度映射。

第五种适配器为可微分线性组合器LComb),与主模型一同训练,在反向传播过程中更新自身参数。该适配器可以结合具体任务上下文,实现更高的精度。

综上所述,Mantis可适配大量任务场景,既保留数据时序结构,也保留通道间的关联关系。即便面对真实场景的多变量数据,模型依旧兼具通用性与运算效率。

论文作者给出的Mantis框架可视化示意图如下。


MQL5的实现

完成Mantis框架理论部分的详细分析后,接下来进入最关键的环节 —— 实际实现。接下来进入框架的实际编码实现阶段,将上述理念落实到代码中。我们的目标是使用MQL5语言实现框架核心架构模块。尽管算法概念复杂度很高,但我们面临清晰且具备挑战性的目标:构建一套能够高效处理真实市场数据、适配波动率变化,同时尽可能节约资源开销的模型。

实现方案探讨


在正式编写代码之前,遵循工程开发惯例,需要先制定实现策略。缺少清晰规划的架构,无法应对真实市场的复杂需求。首先开展系统性分析:明确需要实现哪些模块、各个组件承担什么作用、潜在性能瓶颈可能出现在哪里。不能单纯照搬原论文思路,还要适配我们自身业务目标与MQL5环境,由于MQL5有自身的限制条件与独有特性。

实现工作的核心是生成Token。Token的构建决定模型后续效果,因为Transformer无法直接高效处理原始行情数据。输入必须转为Token序列,每个Token对一段时序做压缩且具备表达能力的表征。

原版Mantis架构采用多通道方案,包含偏差序列、片段均值、片段标准差。然而,我们的模型大多使用归一化输入,均值和标准差两路数据流的信息增益会下降。因此我们刻意舍弃这两路通道,只保留两路核心数据流:原始时间序列、时序一阶差分。两路结合,既可以捕捉价格绝对水平,又可以捕捉局部变化,在模型稳定性与灵敏度之间取得折中。

数据流预处理第一步是对原始时间序列做归一化。该步骤十分关键,可以平滑大幅度波动,提升模型对异常值的鲁棒性。接下来执行差分运算,计算相邻样本之间的差值。差分后的序列对行情突变十分敏感,对于捕捉市场脉冲行情与趋势反转非常有价值。之后,将两组时序合并为双通道张量,每个通道对应一路独立信息。

然而,仅仅是简单拼接还远远不够。多通道时序虽然包含丰富信息,但模型依旧缺失时序上下文的关键信息。众所周知,Transformer本身不具备感知序列元素先后顺序的能力,因此需要额外信息描述各个样本之间的位置关系。

Mantis的原始实现中,该问题通过加入正弦位置编码得到解决,该编码方案与《注意力就是一切》论文提出的方案类似。该方法的优势在于通用性与可移植性:无需训练,并且能够很好地适配各类任务。与此同时,仅在通道合并和分块之后才添加编码。

然而,本文提出了另一种实现思路。在将序列切分为片段之前,引入时序编码,实现方式参考Mamba4Cast框架。该编码不仅标记数据点在时间网格上的位置,还传递时间序列的时序结构信息 —— 让模型能够挖掘市场数据中隐藏的季节性、重复模式、非对称特征与周期节律。与正弦位置编码不同,该时序编码对市场微观结构更加敏感,可以捕捉超出当前分析窗口范围的模式。

只有完成该编码的添加之后,才进入下一逻辑步骤 —— 通道分割。这一步相当于一类过滤器,将经过时序增强的数据转换为模型可接受的格式。换言之,此时的数据不仅包含原始数值与差分信息,还额外携带一层上下文,体现数据随时间演变的行为动力学特征。这极大地降低了模型挖掘复杂关联的难度,同时提升模型对市场噪声的抗干扰能力。

关于分割算法的改动,我们留到后续实际实现环节再展开讨论。现阶段我们暂不介绍其余模块,聚焦底层基础 —— 把时间序列转换为富含信息、标准化且结构化的序列。整个模型的效果根基就建立在这一步之上。高质量预处理的数据,能够帮助模型高效识别模式、正确理解事件先后顺序,区分市场行为里的关键特征。

现在,概念框架已经搭建完毕,技术路线也已明确,接下来要从理论走向实践。正式进入模型的实际实现阶段,将理论转化为代码。让我们从最基础却至关重要的环节开始:时间序列预处理,生成多通道数据表示。初始特征提取就在这一步完成,直接决定Transformer能够读取什么以及如何解读数据。任务目标是提取两路数据流:原始序列与其一阶差分,再合并为一个张量。全部逻辑基于OpenCL实现。

OpenCL程序的修改


采用OpenCL的目的是加速计算,尤其适用于处理大批量时间序列场景。GPU可以对多变量做并行运算,加速数据预处理,不给主处理器增加过重负载。因此,首先实现专用的ConcatDiff内核函数。其作用是计算一阶差分,同时将差分结果与原始数据拼接,为每个时间步生成双通道张量。

该内核仅传入两个数据缓冲区指针,是经过实践检验的极简设计。第一个为输入数组data,存放待分析的时间序列;第二个为输出缓冲区output,保存计算结果。这种设计令内核接口简洁直观,消除多余开销。

额外传入常量参数step,即差分计算步长。该参数大幅提升算法的灵活性。现在,我们既可以计算标准一阶差分(相邻数据点之间),也可以计算例如“当前值“与“五步之后值”的差值。后者在金融场景中非常实用:借助该参数,可以构造反映不同时间维度变化的特征。

__kernel void ConcatDiff(__global const float* data,
                         __global float* output,
                         const int step)
  {
   const size_t i = get_global_id(0);
   const size_t v = get_local_id(1);
   const size_t inputs = get_local_size(0);
   const size_t variables = get_local_size(1);

每个工作项被分配一组唯一索引:时间索引i与变量索引v。因此,每个工作项负责处理源数据矩阵中的某一个特定数值。

源数据数组data是经过归一化的时间序列,采用线性展平存储,时间维度与通道维度被展开为一维。

接下来,我们在内核内部计算shift ,即当前时间‑通道位置在data数组中的内存偏移量。

const int shift = i * variables;
const float d = data[shift + v];

获取原始数值d之后,沿着时间轴计算其一阶差分。其计算方式为:当前数值与向后偏移step步的数值做差。该方式用于构建刻画局部动力学的特征:上涨或下跌、变化的加速与减速。同时需要校验索引合法性,防止访问越界。

float diff = 0;
if(step > 0 && (i + step) < inputs)
   diff = IsNaNOrInf(d - data[shift + step * variables + v], 0);

差分计算末尾调用保护函数IsNaNOrInf,当出现NaN或无穷大时,将结果置为0。在存在缺失值、数据异常的场景下,该保护逻辑尤为关键。

接下来进入核心环节 —— 构造输出数组output。此处执行一项关键操作:数据成对写入。先写入原始数值,紧随其后写入对应的一阶差分值。由于变量步长扩大一倍(通道数量翻倍),最终张量的每个时间步下,每个变量都保存两个数值。因此,output数组的尺寸为T*2*V,其中, T为时间步总数,V为变量数量。

 output[2 * shift + v] = d;
 output[2 * shift + v + variables] = diff;
}

该方法仅需一次运算即可完成模型输入数据的预处理:输出张量已经同时包含市场的静态特征与动态变化特征。

本场景下使用OpenCL具备双重收益:一方面借助并行处理节省运算时间;另一方面简化代码逻辑,所有索引、数组相关运算全部在内核内部完成。不再需要在CPU端编写繁杂循环,取而代之的是一套精简高效的计算单元,可轻松扩展,适配任意长度、任意维度的数据。

该模块是整套模型的基础构建单元。它实现了一项核心设计:将时间序列初步拆解为两路互补数据流。原始数值可以反映价格水平与趋势,一阶差分则对变化敏感,相当于导数,用于捕捉拐点信号。二者结合形成均衡的数据表征,抗噪声能力强,同时可以适配行情的快速突变。

需要重点说明该模块的架构特性:ConcatDiff内核不包含任何可训练参数。它只承担功能性任务:执行简单线性运算(读取数值和计算差分),并把结果合并输出到数组。这一特性非常适合用OpenCL实现;大规模并行运算、无复杂状态逻辑的场景下,其执行效率极高。

另外,针对金融时间序列的特点,在单次预处理迭代中,输入数据本身被视作常量。正因如此,我们无需为该内核实现误差梯度反向传播与参数更新逻辑。这类逻辑只属于模型内部可训练层。而当前属于预处理阶段,该阶段更看重运算速度、可靠性与完全确定性计算。

OpenCL程序的完整代码见附件。

差分计算对象


下一步需要将ConcatDiff内核集成到主程序架构中。为此,我们专门实现CNeuronConcatDiff类对象。该对象作为高层神经网络模型逻辑与底层OpenCL代码之间的接口,负责完成参数准备、内核调度启动、接收运算结果。

class CNeuronConcatDiff:  public CNeuronBaseOCL
  {
protected:
   uint              iUnits;
   uint              iVariables;
   uint              iStep;
   //---
   virtual bool      feedForward(CNeuronBaseOCL *NeuronOCL) override;
   virtual bool      updateInputWeights(CNeuronBaseOCL *NeuronOCL) override   { return true; }
   virtual bool      calcInputGradients(CNeuronBaseOCL *NeuronOCL) override;

public:
                     CNeuronConcatDiff(void) :  iUnits(0), iVariables(1), iStep(1) {  activation = None; }
                    ~CNeuronConcatDiff(void) {};
   virtual bool      Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl,
                          uint units_count, uint step, uint variables,
                          ENUM_OPTIMIZATION optimization_type, uint batch);
   //---
   virtual int       Type(void) override  const   {  return defNeuronConcatDiff;   }
   //--- methods for working with files
   virtual bool      Save(int const file_handle) override;
   virtual bool      Load(int const file_handle) override;
  };

该类内部包含若干关键成员变量:

  • iUnits —— 时间步数量;
  • iVariables —— 源数据的通道数或变量数;
  • iStep —— 偏移参数,指定差分计算的步长,该值赋予组件良好通用性,可适配任意时间窗口宽度与采样频率。

类的构造函数使用默认值初始化核心参数:单通道(iVariables = 1)、差分步长为 1(iStep = 1),并且关闭激活函数(activation = None)。该设置合乎逻辑,毕竟本组件工作在预处理阶段,不应引入非线性变换。

该类还实现了对象初始化方法Init,传入的常量参数能够对所创建对象的架构进行完整且明确的配置。

bool CNeuronConcatDiff::Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl,
                             uint units_count, uint step, uint variables,
                             ENUM_OPTIMIZATION optimization_type, uint batch)
  {
   if(!CNeuronBaseOCL::Init(numOutputs, myIndex, open_cl, 2 * units_count * variables, optimization_type, batch))
      return false;
   if(step<=0 || step >= units_count)
      return false;
//---
   iUnits = units_count;
   iVariables = variables;
   iStep = step;
//---
   return true;
  }

Init方法的内部逻辑尽可能简洁明了。函数体内调用父类同名方法,同时兼顾数据结构的自身特性。由于我们会将原始输入数据与一阶差分结果合并写入输出数组,输出缓冲区的尺寸必须扩大一倍。

完成父类初始化后,将传入的全部入参保存到类的内部成员变量,后续在构造OpenCL内核参数时便可读取使用。

该设计让对象具备灵活性、独立性,并且可复用。

需要重点关注虚feedForward方法,该方法负责前向传播,进而完成 OpenCL内核的调用。

方法入参接收源数据对象的指针,并且会立刻校验该指针的有效性。

bool CNeuronConcatDiff::feedForward(CNeuronBaseOCL *NeuronOCL)
  {
   if(!OpenCL || !NeuronOCL || !Output)
      return false;
   if(getOutputIndex() < 0)
      return false;

完成全部校验且校验通过后,将ConcatDiff内核加入执行队列。此处采用的是前文已经介绍过的算法流程。借助预先保存在类内部变量中的数值,来设定任务空间的维度参数。

{
 uint global_work_offset[2] = {0};
 uint global_work_size[2] = {iUnits, iVariables};
 const int kernel = def_k_ConcatDiff;
 if(!OpenCL.SetArgumentBuffer(kernel, def_k_concdiff_data, NeuronOCL.getOutputIndex()))
   {
    printf("Error of set parameter kernel %s: %d; line %d", OpenCL.GetKernelName(kernel),
                                                               GetLastError(), __LINE__);
    return false;
   }
 if(!OpenCL.SetArgumentBuffer(kernel, def_k_concdiff_output, getOutputIndex()))
   {
    printf("Error of set parameter kernel %s: %d; line %d", OpenCL.GetKernelName(kernel), 
                                                               GetLastError(), __LINE__);
    return false;
   }
 if(!OpenCL.SetArgument(kernel, def_k_concdiff_step, iStep))
   {
    printf("Error of set parameter kernel %s: %d; line %d", OpenCL.GetKernelName(kernel), 
                                                               GetLastError(), __LINE__);
    return false;
   }
 //---
 if(!OpenCL.Execute(kernel, global_work_size.Size(), global_work_offset, global_work_size))
   {
    printf("Error of set parameter kernel %s: %d; line %d", OpenCL.GetKernelName(kernel), 
                                                               GetLastError(), __LINE__);
    return false;
   }
}

然而,feedForward方法的逻辑并未到此结束。下一步对输出张量做归一化处理,本质是将数据映射到统一量纲尺度,这对于神经网络训练至关重要。另外,本实现对两类特征分别执行归一化:变量原始数值做一路归一化,一阶差分值单独做另一路归一化。该处理方式能够让模型既对时间序列的剧烈变化保持敏感度,又在面对大幅行情波动时维持稳定性。

     {
      uint global_work_offset[1] = {0};
      uint global_work_size[1] = {2 * iUnits};
      const int kernel = def_k_Normilize;
      if(!OpenCL.SetArgumentBuffer(kernel, def_k_norm_buffer, getOutputIndex()))
        {
         printf("Error of set parameter kernel %s: %d; line %d", OpenCL.GetKernelName(kernel),
                                                                    GetLastError(), __LINE__);
         return false;
        }
      if(!OpenCL.SetArgument(kernel, def_k_norm_dimension, iVariables))
        {
         printf("Error of set parameter kernel %s: %d; line %d", OpenCL.GetKernelName(kernel), 
                                                                    GetLastError(), __LINE__);
         return false;
        }
      if(!OpenCL.Execute(kernel, global_work_size.Size(), global_work_offset, global_work_size))
        {
         string error;
         CLGetInfoString(OpenCL.GetContext(), CL_ERROR_DESCRIPTION, error);
         printf("Error of execution kernel %s: %d -> %s", OpenCL.GetKernelName(kernel), 
                                                                GetLastError(), error);
         return false;
        }
     }
//---
   return true;
  }

该后处理通过标准化输入数值的取值范围,显著提升训练稳定性,加快模型收敛速度。

另外再介绍误差梯度传播方法 —— calcInputGradients。虽然我们没有为该层编写反向传播内核,但依旧实现了对应的方法。

为什么要这样做?答案很简单。这样可以把该对象嵌入模型的任意层级,而不用担心破坏误差反向传播链路。即便该层不需要计算自身梯度,也必须把误差信号正确传递给前序模块。否则,整个模型的训练可能在该层失效,造成梯度流停滞,最终底层网络参数将无法完成优化。

该方法内部算法简洁可靠。首先获取源数据对象(NeuronOCL)的指针,并立刻校验指针有效性。

bool CNeuronConcatDiff::calcInputGradients(CNeuronBaseOCL *NeuronOCL)
  {
   if(!NeuronOCL)
      return false;

我们将当前对象中累积的误差梯度,沿着源数据的前向信息流进行转发,把它作为上一层的输入信号。该过程仅做解拼接操作,不包含任何复杂计算逻辑。

if(!DeConcat(NeuronOCL.getGradient(), getPrevOutput(), getGradient(), iVariables, iVariables, iUnits))
   return false;

根据架构需要,还可以借助激活函数的导数对误差梯度做相应修正。

   if(NeuronOCL.Activation() != None)
      if(!DeActivation(NeuronOCL.getOutput(), NeuronOCL.getGradient(), NeuronOCL.getGradient(),
                                                                       NeuronOCL.Activation()))
         return false;
//---
   return true;
  }

该设计保障了整体架构的兼容性与灵活性。CNeuronConcatDiff对象不会干扰梯度传播,可应用于复杂模型当中,既可以放在低层(靠近输入侧),也能够部署在计算图的深层位置。

至此,关于CNeuronConcatDiff类各方法的实现算法介绍完毕。该类及其全部方法的完整代码参见附件。

本文篇幅已经接近合理的上限。即便如此,大部分开发工作仍有待完成。我们仅仅打下了基础。然而,讨论并未到此结束。为避免内容过于冗长,保证文章可读性,我们暂且告一段落,具体实现将在本系列的下一篇文章继续展开。后续还有同样精彩、技术信息量十足的环节等待我们研究。


结论

在本文中,我们探究了Mantis框架,该框架兼具轻量化设计与高预测精度。框架的原作者提出了一套基于卷积与平均池化(mean‑pooling)的创新token化方案,可以将时间序列高效编码为32个维度为256的token,相比传统方法降低计算开销。基于多源数据集样本开展对比预训练,得到鲁棒、具备迁移能力的特征表达;该模型在零样本(zero‑shot)与微调(fine‑tuning)场景下性能优于其他方案,并且取得了极低的校准误差记录。

实践部分展示了基于OpenCLMQL5实现的核心数据预处理层,实现输入张量的并行化和确定性预处理。在下一篇文章中,我们将继续按照我们自身的理解,实现Mantis框架原论文提出的各项算法。


链接


本文使用的软件

# 名称 类型 描述
1 Research.mq5 EA 用于收集示例的EA
2 ResearchRealORL.mq5
EA
通过Real-ORL方法收集示例的EA
3 StudyContrast.mq5 EA 用于编码器对比学习的EA
4 Study.mq5 EA 用于离线模型训练的EA
5 StudyOnline.mq5
EA
用于在线模型训练的EA
6 Test.mq5 EA 用于模型测试的EA
7 Trajectory.mqh 类库 用于描述系统状态与模型架构的结构
8 NeuroNet.mqh 类库 用于构建神经网络的类库
9 NeuroNet.cl OpenCL程序代码库


本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/18246

附加的文件 |
MQL5.zip (2794.71 KB)
交易中的神经网络:用于精确分类的高效特征提取(构建对象) 交易中的神经网络:用于精确分类的高效特征提取(构建对象)
Mantis 是一款用于深度时序分析的多功能工具,可灵活扩展,适配任意金融场景。了解分块处理、局部卷积与交叉注意力相结合,如何实现对市场形态的高精度解读。
市场模拟(第 23 部分):仓位视图(一) 市场模拟(第 23 部分):仓位视图(一)
接下来我们将要介绍的内容,在理论和概念方面要复杂得多。我会让这些材料尽可能简单易懂。编程部分本身相当简单明了。但是,如果你不了解背后的理论,那么在将回放模拟系统改进或调整以适应不同于我将要展示的任务时,你就几乎没有任何可用于进一步改进或适配系统的实际依据。我不希望你只是编译和使用我提供的代码。我希望你能学习、理解,并且如果可能的话,能够创造出更好的东西。
新手在交易中的10个基本错误 新手在交易中的10个基本错误
新手在交易中会犯的10个基本错误: 在市场刚开始时交易, 获利时不适当地仓促, 在损失的时候追加投资, 从最好的仓位开始平仓, 翻本心理, 最优越的仓位, 用永远买进的规则进行交易, 在第一天就平掉获利的仓位,当发出建一个相反的仓位警示时平仓, 犹豫。
交易中的神经网络:不依赖特定数据的时间序列泛化(核心模型模块) 交易中的神经网络:不依赖特定数据的时间序列泛化(核心模型模块)
我们继续介绍Mamba4Cast框架。今天,我们将深入探讨该方案的实现。Mamba4Cast的设计目标并非对每一条全新时间序列都进行冗长的预热,而是支持直接部署上线。依托零样本预测理念,该模型无需额外训练、也无需调优超参数,就可以在真实业务数据上输出高质量预测结果。