交易中的神经网络:针对加密货币市场的记忆扩充上下文感知学习(MacroHFT)
概述
金融市场因其广泛的可及性和高利润潜力吸引了大量投资者。在所有可用资产类别中,加密货币以其超常的波动性著称,这为在短时间内创造可观利润创造了独特的机会。另一个优势是其全天候交易周期,允许交易者在不同时间捕捉市场变化。然而,同样的波动性不仅代表机遇,也是重大风险,故需要采用更精准的管理策略。
为了在加密货币市场中最大化利润,交易者常用高频交易(HFT)— 这是一种基于超高速订单执行的算法交易形式。HFT长期主导传统金融市场,近年来在加密货币领域亦眼见广泛扩散。它不仅操作速度卓越,还具备实时处理海量数据的能力,令其在快节奏的加密市场环境中声名显赫。
强化学习(RL)方法在金融领域日益流行,在于它们能够解决复杂的顺序决策制定难题。RL 算法能够处理多维数据,参考多个参数,并适配变化中的环境。然而,尽管低频交易进展显著,针对加密货币市场的高效高频算法仍在开发中。这些市场特征是高波动性、不稳定,需要在长期策略考量、与快速战术反应之间取得平衡。
现有的加密货币 HFT 算法面临诸多挑战,限制了其有效性。首先,市场常被视为统一且固定的系统,许多算法仅依赖趋势分析,而忽视波动性。这种方式令风险管理变得复杂,并降低了预测的准确性。其次,许多策略偏于过度拟合,专注于极狭窄的有限市场特征。这缩减降了它们对新环境的适应能力。最后,个别交易政策往往缺乏足够的灵活性,来应对突发的市场转移 — 这是高频环境中的一个关键缺陷。
针对这些挑战的潜在解决方案已在论文《MacroHFT:高频交易中的记忆扩充上下文感知强化学习》中提出。作者提出了 MacroHFT,这是一个基于上下文感知强化学习的创新框架,专为在分钟时间帧上的加密货币高频交易设计。MacroHFT 协同宏观经济和上下文信息,来强化决策品质。该过程涉及两个关键阶段。第一种是市场分类,基于趋势和波动率指标对市场进行分类。随后针对每个类别训练专门的子智代,令其能够根据当前条件动态调整策略。这些子智代提供了灵活性,并考虑了本地化市场特性。
第二阶段,超智代整合子智代的策略,并基于市场动态优化部署。配备记忆模块,参照近期经验构建稳定、且适应性强的交易策略。这种结构提升了系统对市场突变的韧性,并降低了风险暴露。
MacroHFT 算法
MacroHFT 框架是一个创新的算法交易平台,专为高波动性和快速波动特征的加密货币市场量身定制。它基于强化学习方法,能够创建分析和预测市场行为的自适应算法。其主要思路是整合专门的子智代,每个都已针对特定市场场景优化,且由超智代协调它们,确保一致性和整体效率。
在极端波动和快速变化的条件下,仅依赖单一的强化学习智代是不够的。市场条件会转移过快、且不可预测,单个算法无法及时适应。为此,MacroHFT 框架引入了多个专门的子智代,每个都针对不同的市场环境加以训练。这令构建更灵活、更具适应性的系统成为可能。
基本原则在于按照趋势和波动率两个关键参数对市场数据进行分段和分类。市场数据被划分为固定长度的区块,可用于训练和测试两者。每个区块都被赋予标签,标识其市场条件类型,简化了子智代的训练过程。
标签过程包括两个步骤:
- 趋势标签。每个数据区块都经过低通滤波器处理,去除噪声,并高亮主要价格方向。然后应用线性回归,斜率作为趋势指标。有基于此,趋势分为正(看涨市场)、中性(横盘)、或负面(看跌市场)。
- 波动率标签。计算每个区块内的平均价格变化,估算波动率。这些数值会按数据分布分位数设定类别阈值,并分类为高、中、低类别。
因此,每个数据区块会接收两个标签:一个用于趋势,一个用于波动率。如是结果,我们有六个市场条件类别,结合了趋势类型(看涨、中性、看跌)、和波动率水平(高、中、低)。如此分段产生六个训练子集,每个子集针对特定条件训练并优化一个子智代。同样的标记逻辑也应用于测试数据,阈值衍生自训练集。该方式确保了公平的绩效评估。
每个子智代都是据六个数据子集之一加以训练。然后据对应的类别进行测试。该过程生成针对特定环境的专用模型。例如,一个子智代或许在高波动率的看涨市场表现最佳,而另一个在低波动率的看跌市场表现优异。这种模块化架构令系统能够动态适应演变中的条件,显著提升了性能。
至于子智代训练,该框架采用双架构的双深度 Q-网络(DDQN)方法,即参考市场指标、上下文因素、和交易者持仓。这些数据流经由不同的神经网络层处理,然后被合并为统一的表述。自适应层范数模块进一步细化了这种表述,令模型能够考虑特定市场的细微差别,确保决策制定的灵活性和精准。
MacroHFT 因此创建了六个子智代,每个均专注于不同的市场场景。它们出品的策略由超智代整合,确保系统在加密货币市场动态条件下的效率和适应性。
超智代合并子智代的输出,形成一个灵活高效的政策,具备适应实时市场动态的能力。它调用基于 Softmax 的元政策来整合子智代决策。该方式降低了对单个子智代的过度依赖,同时协同来自所有系统组件的洞查。
超智代的核心优势之一是利用趋势和波动率指标快速制定决策,能针对市场变化快速响应。然而,传统的基于马尔可夫(Markov)决策过程(MDP)的训练方法面临诸多问题,譬如奖励高度变化、及罕见极端市场事件。为迎接这些挑战,超智代协同一个记忆模块。
记忆模块是以固定大小的表格实现,存储关键状态和动作的向量。新增的经验则是计算它们的一步 Q-值 估值。当表格达到容量上限时,旧记录会被丢弃,从而保留最相关的信息。在推理期间,超智代计算当前状态与存储主键之间的 L2 距离,提取最相关的条目。最终数值的计算则为记忆数据加权求和。
这种记忆机制还强化了超智代=的动作评估。通过修改损失函数,包含一个记忆对齐项 — 按当前预测调和存储的记忆值。因此,系统学习更稳定的交易策略,具备有效应对突发市场冲击的能力。
MacroHFT 拥有设计良好的架构,令其成为适用于多元金融市场的多功能交易框架。它最初虽是为加密货币开发的,但其方法论和算法亦能适配其它资产类别,包括股票和大宗商品。
MacroHFT 框架的原始可视化如下所示。

实现 MQL5 版本
在分析过 MacroHFT 框架的理论层面后,我们现在转到本文的实施部分,其中我们会实现的所提方法的 MQL5 版本。
在本实现中,我们保留了模型架构的层次化核心概念,但对组件结构和训练过程引入了重大修改。首先,我们剔除了手工按趋势和波动率级别分类标记区块,并将训练和测试数据集分段的操作。其次,我们不会将模型训练过程分为两个不同的阶段。取而代之,我们实现了在统一迭代过程中并发训练超智代和子智代。我们假设在训练期间,超智代能够自主分类环境状态,并相应地为智代分配角色。
我们不会针对超智代使用传统的基于表格的记忆,而是用三层记忆对象来替代,它是作为 FinCon 框架一部分而开发的。此外,我们决定将先前开发的分析智代与更先进的架构整合,以便高效实现子智代的功能。因此,我们在实现 MacroHFT 框架的工作始于超智代的创建。
构建超智代
根据 MacroHFT 框架作者提供的描述,超智代分析当前环境状态,将其与存储的记忆对象比较,并返回表述所分析状态分类的概率分布。该分类或许指的是市场走势的趋势或波动性。出品的概率分布随后用于判定每个子智代对最终交易决策的贡献。最终决策是根据每个子智代的产出,与当前市场条件的契合度加权来产生的。该方式令整体决策制定过程能够动态适应主导市场因素。
换言之,我们必须创建一个状态分类组件,有能力分析当前市场环境、同时参考存储在上下文记忆中之前观察到的状态。这是经由分析市场参数序列、及其与当前形势的相关性来达成的。历史状态有助于揭示长期趋势和隐藏形态,从而在当前市场条件分类时更明智。
我们将要实现的这个超智代,作为名为 CNeuronMacroHFTHyperAgent 的对象,其结构如下所示。
class CNeuronMacroHFTHyperAgent : public CNeuronSoftMaxOCL { protected: CNeuronMemoryDistil cMemory; CNeuronRMAT cStatePrepare; CNeuronTransposeOCL cTranspose; CNeuronConvOCL cScale; CNeuronBaseOCL cMLP[2]; //--- virtual bool feedForward(CNeuronBaseOCL *NeuronOCL) override; virtual bool updateInputWeights(CNeuronBaseOCL *NeuronOCL) override; virtual bool calcInputGradients(CNeuronBaseOCL *NeuronOCL) override; public: CNeuronMacroHFTHyperAgent(void) {}; ~CNeuronMacroHFTHyperAgent(void) {}; //--- virtual bool Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint window, uint window_key, uint units_count, uint heads, uint layers, uint agents, uint stack_size, ENUM_OPTIMIZATION optimization_type, uint batch); //--- virtual int Type(void) override const { return defNeuronMacroHFTHyperAgent; } //--- virtual bool Save(int const file_handle) override; virtual bool Load(int const file_handle) override; //--- virtual bool WeightsUpdate(CNeuronBaseOCL *source, float tau) override; virtual void SetOpenCL(COpenCLMy *obj) override; //--- virtual bool Clear(void) override; };
实现的 Softmax 层被当作父类。该函数由 MacroHFT 框架的作者提出,用于计算概率分布。它在判定每个子智代对最终决策的贡献中扮演关键角色,确保了模型准确性和适应性两者。
超智代结构包括一套标准的虚拟方法、及若干内部对象,这些对象当作分析当前环境状态算法的基础。我们将在超智代类方法的实现期间详尽探讨这些组件的功能。
所有内部对象都声明为静态,允许我们将类构造和析构函数留空。这些声明和继承对象的初始化均在 Init 方法中执行。该方法取多个常量参数,明确定义被创建对象的架构。
bool CNeuronMacroHFTHyperAgent::Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint window, uint window_key, uint units_count, uint heads, uint layers, uint agents, uint stack_size, ENUM_OPTIMIZATION optimization_type, uint batch) { if(!CNeuronSoftMaxOCL::Init(numOutputs, myIndex, open_cl, agents, optimization_type, batch)) return false; SetHeads(1); //--- int index = 0;
在方法主体中,如常,我们首先调用父类的相关方法。在这种情况下,它是 Softmax 函数层。结果向量的期望大小对应于用到的子智代数量,该数值来自调用程序,作为方法参数传递。
接下来,我们转到初始化内部对象。首先,我们初始化记忆模块。
int index = 0; if(!cMemory.Init(0, 0, OpenCL, window, window_key, units_count, heads, stack_size, optimization, iBatch)) return false;
为了检测表述所分析环境状态数据中的依赖性,我们计划使用带有相对位置编码的变换器。
index++; if(!cStatePrepare.Init(0, index, OpenCL, window, window_key, units_count, heads, layers, optimization, iBatch)) return false;
下一步是将所分析环境状态投影到一个维度等于子智代数量的子空间之中。这需要一种高效的投影机制,保留所有关键数据特征。初看,可以使用标准的全连接或卷积层。然而,给定的输入多模态时间序列特性,关键重点是要保持单变量序列的结构,因为这些序列包含了重要信息,或许会因过度聚合而丢失。
早前,我们应用了带有相对编码的变换器来分析时间步骤间的依赖关系。现在,我们必须补充这一过程,维持独立单变量序列的细节。为达成这一点,我们首先转置数据,令后续操作中处理单变量序列更容易。
index++; if(!cTranspose.Init(0, index, OpenCL, units_count, window, optimization, iBatch)) return false;
接下来,我们应用一个卷积层,从这些单变量序列中提取空间和时态特征,强化其可解释性。非线性通过双曲切线(tanh)激活函数引入。
index++; if(!cScale.Init(4 * agents, index, OpenCL, 3, 1, 1, units_count - 2, window, optimization, iBatch)) return false; cScale.SetActivationFunction(TANH);
该阶段之后,我们转到关键数据压缩阶段。为了降维,采用两层 MLP 架构。第一层执行初步数据减少,去除冗余的相关性和噪声。调用泄漏的 ReLU(LReLU)激活函数有助于防止变换中的线性化。第二层最终压缩,优化数据,以便进一步分析。
index++; if(!cMLP[0].Init(agents, index, OpenCL, 4 * agents, optimization, iBatch)) return false; cMLP[0].SetActivationFunction(LReLU); index++; if(!cMLP[1].Init(0, index, OpenCL, agents, optimization, iBatch)) return false; cMLP[0].SetActivationFunction(None); //--- return true; }
该方式确保了信息保存与模型简化之间的平衡,这对于超智代在高频交易环境中的有效性至关重要。
处理过的数据随后通过早前初始化的父类提供的机制传送到概率空间。此刻,方法能够返回一个逻辑成功值至调用程序,结束初始化过程。
一旦初始化完成,我们转到在 feedForward 方法中实现前向通验算法。此处一切都很简单、直截了当。
bool CNeuronMacroHFTHyperAgent::feedForward(CNeuronBaseOCL *NeuronOCL) { if(!cMemory.FeedForward(NeuronOCL)) return false;
该方法在参数里接收指向源数据对象的指针,其中包含描述所分析环境状态的多模态张量。该指针会立即传递至对应的记忆模块方法。该阶段,环境的静态描述会被丰富,包含近期动态信息,从而为后续分析创造更完整、更及时的表述。整合这种时态上下文可以更精确地跟踪系统内的持续变化,从而提升后续处理算法的效率。
前一阶段处理过的数据会被传递到注意力模块,其中识别所分析序列中不同时间点之间的相互依赖关系。这一步揭示了隐藏的关系,并提升了后续价格走势预测的准确性。
if(!cStatePrepare.FeedForward(cMemory.AsObject())) return false;
往后,我们继续数据压缩。我们首先将之前分析所得的结果转置。
if(!cTranspose.FeedForward(cStatePrepare.AsObject())) return false;
接下来,我们用卷积层压缩独立单变量序列,保留其结构信息。
if(!cScale.FeedForward(cTranspose.AsObject())) return false;
然后,我们使用 MLP,将分析后的环境状态投影到预定义维数的子空间之中。
if(!cMLP[0].FeedForward(cScale.AsObject())) return false; if(!cMLP[1].FeedForward(cMLP[0].AsObject())) return false;
现在,我们需要将得到的数值映射到概率空间当中。这是调用来自父类的对应 Softmax 方法完成的,传递处理后的结果。
return CNeuronSoftMaxOCL::feedForward(cMLP[1].AsObject()); }
然后我们将操作的逻辑结果返回给调用者,并结束方法执行。
正如您或许注意到的,超智代的前向通验算法遵循线性且透明的结构。反向传播方法的算法具有类似的线性性质,且相对简单,适合独立研究。
此刻,我们针对超智代工作原理的概览完结。该类的完整源代码,及其所有方法已在附件中提供,供有兴趣进一步学习和实际应用的读者参考。我们转进。我们继续在一个统一框架内整合智代。
构建 MacroHFT 框架
在该阶段,我们已拥有子智代和超智代的各个对象。现在是时候将它们整合为一个统一、连贯的结构,于其中实现模型组件之间的数据交换算法。该任务将在 CNeuronMacroHFT 对象中完成,其将管理和优化数据处理工作流。新对象的结构如下所示。
class CNeuronMacroHFT : public CNeuronBaseOCL { protected: CNeuronTransposeOCL cTranspose; CNeuronFinConAgent caAgetnts[6]; CNeuronMacroHFTHyperAgent cHyperAgent; CNeuronBaseOCL cConcatenated; //--- virtual bool feedForward(CNeuronBaseOCL *NeuronOCL) override; virtual bool updateInputWeights(CNeuronBaseOCL *NeuronOCL) override; virtual bool calcInputGradients(CNeuronBaseOCL *NeuronOCL) override; public: CNeuronMacroHFT(void) {}; ~CNeuronMacroHFT(void) {}; //--- virtual bool Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint window, uint window_key, uint units_count, uint heads, uint layers, uint stack_size, uint nactions, ENUM_OPTIMIZATION optimization_type, uint batch); //--- virtual int Type(void) override const { return defNeuronMacroHFT; } //--- virtual bool Save(int const file_handle) override; virtual bool Load(int const file_handle) override; //--- virtual bool WeightsUpdate(CNeuronBaseOCL *source, float tau) override; virtual void SetOpenCL(COpenCLMy *obj) override; //--- virtual bool Clear(void) override; };
新对象包含了熟悉的可覆盖虚拟方法集合,为实现其功能提供了灵活性。于其内部对象中,超智代居中扮演协调角色,而六个子智代的数组处理输入数据的各个层面。正如我们构建类方法,会用到一份内部对象的功能详述、及其交互逻辑。
所有内部对象均声明为静态。这允许我们将类的构造和析构函数留空。这些声明和继承对象的初始化均在 Init 方法中执行。该方法接收若干常量参数,清晰定义所创建对象的架构。
bool CNeuronMacroHFT::Init(uint numOutputs, uint myIndex, COpenCLMy *open_cl, uint window, uint window_key, uint units_count, uint heads, uint layers, uint stack_size, uint nactions, ENUM_OPTIMIZATION optimization_type, uint batch) { if(!CNeuronBaseOCL::Init(numOutputs, myIndex, open_cl, nactions, optimization_type, batch)) return false;
在方法主体中,如常,我们调用父类的同名方法。该方法已实现了初始化继承对象和接口的过程。在这种情况下,父类是一个全连接层,来自我们仅需的与外部模型组件交互的基本接口。我们新对象的输出应根据所分析市场条件产生模型的最终动作张量。因此,我们指定智代动作空间的维数作为父类初始化方法的参数。
在原版 MacroHFT 框架中,作者提出根据市场趋势和波动率切分子智代。在我们的版本中,虽然我们使用基于市场视野的划分。我们的子智代将接收不同市场分析的数据预测。为了形成这些投影,用到了一个数据置换层。
int index = 0; if(!cTranspose.Init(0, index, OpenCL, units_count, window, optimization, iBatch)) return false;
接下来,我们初始化子智代。前半部分分析原始形式的输入数据,后半部分处理其转置后的表示。为了组织初始化,我们设置了两个连续的环路,每个运行必要的迭代次数。
uint half = (caAgetnts.Size() + 1) / 2; for(uint i = 0; i < half; i++) { index++; if(!caAgetnts[i].Init(0, index, OpenCL, window, window_key, units_count, heads, stack_size, nactions, optimization, iBatch)) return false; } for(uint i = half; i < caAgetnts.Size(); i++) { index++; if(!caAgetnts[i].Init(0, index, OpenCL, units_count, window_key, window, heads, stack_size, nactions, optimization, iBatch)) return false; }
然后我们初始化超智代,它也会分析原始市场数据表述。
index++; if(!cHyperAgent.Init(0, index, OpenCL, window, window_key, units_count, heads, layers, caAgetnts.Size(), stack_size, optimization, iBatch)) return false;
根据 MacroHFT 算法,我们必须现在加权求和子智代的输出。在此情况下权重由超智代生成。该操作通过将子智代结果矩阵乘以超智代提供的权重矢量即可轻松实现。然而,在我们的实现中,子智代的输出被存储在独立对象之中。故此,我们创建一个额外的级联对象,将必要的向量结合至单一矩阵。
index++; if(!cConcatenated.Init(0, index, OpenCL, caAgetnts.Size()*nactions, optimization, iBatch)) return false; //--- return true; }
矩阵相乘本身将在前馈过程中运作。对于目前,我们简单地将初始化的逻辑结果返回至调用程序,并结束 Init 方法。
下一步是在 feedForward 方法中实现前馈算法。如前,方法会接收指向输入数据对象的指针,我们会立即将其转置。
bool CNeuronMacroHFT::feedForward(CNeuronBaseOCL *NeuronOCL) { if(!cTranspose.FeedForward(NeuronOCL)) return false;
接下来,一半的子智代处理所分析环境状态的原始表征,另一半处理其转置后的投影。
uint total = caAgetnts.Size(); uint half = (total + 1) / 2; for(uint i = 0; i < half; i++) if(!caAgetnts[i].FeedForward(NeuronOCL)) return false;
for(uint i = half; i < total; i++) if(!caAgetnts[i].FeedForward(cTranspose.AsObject())) return false;
超智代同时分析原始数据。
if(!cHyperAgent.FeedForward(NeuronOCL)) return false;
然后我们将来自所有子智代的结果收集到一个单一矩阵。
if(!Concat(caAgetnts[0].getOutput(), caAgetnts[1].getOutput(), caAgetnts[2].getOutput(), caAgetnts[3].getOutput(), cConcatenated.getPrevOutput(), Neurons(), Neurons(), Neurons(), Neurons(), 1) || !Concat(cConcatenated.getPrevOutput(), caAgetnts[4].getOutput(), caAgetnts[5].getOutput(), cConcatenated.getOutput(), 4 * Neurons(), Neurons(), Neurons(), 1)) return false;
在成品矩阵中,每一行对应一个子智代的输出。为了正确计算加权合计,我们将权重向量(来自超智代)乘以该结果矩阵。
if(!MatMul(cHyperAgent.getOutput(), cConcatenated.getOutput(), Output, 1, total, Neurons(), 1)) return false; //--- return true; }
该矩阵乘法的结果会写入从父类继承的外部接口缓冲区。然后我们将操作的逻辑结果返回至调用程序,并结束该方法。
值得注意的是,尽管引入了结构修改,前馈算法仍完全保留了 MacroHFT 框架的原始概念逻辑。然而,训练过程并非如此,接下来将详细讨论。
如早前所述,MacroHFT 框架的作者根据市场趋势和波动性将训练数据集合切分成分离的子集。每个子智代都在其相应子集上进行训练。但在我们的实现中,我们提出同时训练所有智代。该过程将在我们类的反向传播方法中实现。
我们首先构建算法,按它们对模型整体输出的影响成比例,在类内部对象和输入数据之间分派误差梯度。该功能在 calcInputGradients 方法中实现。
bool CNeuronMacroHFT::calcInputGradients(CNeuronBaseOCL *NeuronOCL) { if(!NeuronOCL) return false;
该方法接收一个指向前馈阶段中所用的同一输入数据对象的指针。不过这次,必须将相应的误差梯度传递给它。在方法内部,我们立即验证所接收指针的有效性 — 因为如果该对象不存在,就不可能写入数据。在这种情况下,后续所有操作都变得无意义。
正如您所知,误差梯度流与前馈过程的操是镜像,但反方向移动。前向通验以子智代结果和权重向量的矩阵乘法结束,而反向传播始于经由同样操作分派误差梯度。
uint total = caAgetnts.Size(); if(!MatMulGrad(cHyperAgent.getOutput(), cHyperAgent.getGradient(), cConcatenated.getOutput(), cConcatenated.getGradient(), Gradient, 1, total, Neurons(), 1)) return false;
重点要注意,这一步将梯度分成两条信息流。第一个 — 超智代的梯度流。经由该流,我们可以立即将误差传播到输入数据级。
if(!NeuronOCL.calcHiddenGradients(cHyperAgent.AsObject())) return false;
第二个是子智代的梯度流。在矩阵乘法梯度分派期间,我们得到级联对象层级的误差值。自然,对模型输出贡献最大的子智代将获得最大的误差梯度。故此,我们可基于超智代执行的环境状态分类,在训练过程中动态分配子智代的角色。
然后,我们执行数据脱链连,将在相应的子智代之间分派获得的梯度值。
if(!DeConcat(cConcatenated.getPrevOutput(), caAgetnts[4].getGradient(), caAgetnts[5].getGradient(), cConcatenated.getGradient(), 4 * Neurons(), Neurons(), Neurons(), 1) || !DeConcat(caAgetnts[0].getGradient(), caAgetnts[1].getGradient(), caAgetnts[2].getGradient(), caAgetnts[3].getGradient(), cConcatenated.getPrevOutput(), Neurons(), Neurons(), Neurons(), Neurons(), 1)) return false;
之后,我们能够将误差梯度沿每个子智代的计算路径传播到输入数据层。于此,我们应当注意两点。首先,输入数据对象的梯度缓冲区已经包含了从超智代接收到的信息,必须保留这些信息。为此,我们暂时把梯度缓冲区指针替换到另一个可用缓冲区,防止覆盖现有数据。
CBufferFloat *temp = NeuronOCL.getGradient(); if(!temp || !NeuronOCL.SetGradient(cTranspose.getPrevOutput(), false)) return false;
其次,并非所有子智代都直接与输入数据互动。其中一半是处理转置数据。因此,在分派梯度时必须考虑到这一点。与前向通验一样,我们组织两个顺序环路。第一个环路处理与直接输入表述打交道的子智代。我们将梯度传播到输入层级,并与之前存储的梯度一起累积结果。
uint half = (total + 1) / 2; for(uint i = 0; i < half; i++) { if(!NeuronOCL.calcHiddenGradients(caAgetnts[i].AsObject())) return false; if(!SumAndNormilize(temp, NeuronOCL.getGradient(), temp, 1, false, 0, 0, 0, 1)) return false; }
第二个环路与第一个相同,但增加了一步,将梯度传播到数据置换层。该环路处理另一半子智代。
for(uint i = half; i < total; i++) { if(!cTranspose.calcHiddenGradients(caAgetnts[i].AsObject()) || !NeuronOCL.calcHiddenGradients(cTranspose.AsObject())) return false; if(!SumAndNormilize(temp, NeuronOCL.getGradient(), temp, 1, false, 0, 0, 0, 1)) return false; }
当所有环路迭代成功完成后,我们恢复原始数据缓冲指针。之后该方法结束,将逻辑成功结果返回至调用程序。
我们构造新 MacroHFT 框架协调对象方法的算法至此完毕。您可在附件中找到所有提供的类、及其方法的完整源代码。
我们现在已到达了本文篇幅的极限,但我们的工作尚未完成。我们稍事休息,继续下一篇文章。我们终将实现它,并在真实历史市场数据上评估已开发方法的性能。
结束语
本文探讨了 MacroHFT 框架,这是针对加密货币交易的一种有前景的高频解决方案。该框架协同了宏观经济背景和本地市场动态。这令它成为专业交易者在复杂且波动的市场环境中最大化回报的强大工具。
在实践章节,我们遵照框架核心组件的自我诠释实现了 MQL5 版本。在下一期中,我们将完成这项工作,并严格测试所实现方法在真实历史数据上的有效性。
参考
文章中所用程序
| # | 名称 | 类型 | 说明 |
|---|---|---|---|
| 1 | Research.mq5 | 智能系统 | 收集样本的智能系统 |
| 2 | ResearchRealORL.mq5 | 智能系统 | 利用 Real-ORL 方法收集样本的智能系统 |
| 3 | Study.mq5 | 智能系统 | 模型训练智能系统 |
| 4 | Test.mq5 | 智能系统 | 模型测试智能系统 |
| 5 | Trajectory.mqh | 类库 | 系统状态和模型架构描述结构 |
| 6 | NeuroNet.mqh | 类库 | 创建神经网络的类库 |
| 7 | NeuroNet.cl | 函数库 | OpenCL 程序代码 |
本文由MetaQuotes Ltd译自俄文
原文地址: https://www.mql5.com/ru/articles/16975
注意: MetaQuotes Ltd.将保留所有关于这些材料的权利。全部或部分复制或者转载这些材料将被禁止。
本文由网站的一位用户撰写,反映了他们的个人观点。MetaQuotes Ltd 不对所提供信息的准确性负责,也不对因使用所述解决方案、策略或建议而产生的任何后果负责。
交易中的神经网络:针对加密货币市场的记忆扩充上下文感知学习(终篇)
交易中的神经网络:配备概念强化的多智代系统(终篇)
开发多币种 EA 交易(第 22 部分):开始向设置的热插拔过渡
交易中的神经网络:配备概念强化的多智代系统(FinCon)