English Русский Español Deutsch 日本語 Português
preview
一种采用纯MQL5语言实现的基于能量学习的特征选择算法

一种采用纯MQL5语言实现的基于能量学习的特征选择算法

MetaTrader 5示例 |
431 0
Francis Dube
Francis Dube

引言

在算法交易的领域中,机器学习的广泛应用,促使数据挖掘技术被用来发掘金融数据中的隐藏模式。在这一背景下,从业人员经常面临挑战,即如何从众多变量中筛选出最有可能对实现特定目标或解决特定问题有用的变量。本文探讨了特征选择算法的实现,该算法旨在评估一组候选变量在给定预测任务中的相关性。

Yun Li, Jennie Si, Guojing Zhou, Shasha Huang, and Songcan Chen共同撰写了一篇题为 《FREL:一种稳定的特征选择算法》的研究论文。该论文介绍了一种名为基于正则化能量的特征加权学习(FREL)的算法,该算法作为一种特征选择或加权技术,旨在同时提供准确性和稳定性。在我们的讨论中,我们概述了基于正则化能量的学习和特征加权的理论基础。此外,我们还通过一个MQL5程序示例(编写为脚本),说明了所提出方法的有效性,以此突出该方法作为特征选择工具的潜力。


加权最近邻分类

FREL背后的概念灵感来源于一种被称为加权最近邻分类的技术,该技术利用数据集中点之间的距离来进行预测。通过为每个特征确定适当的权重,这种方法可以提高预测的准确性。加权最近邻分类是k-最近邻(k-NN)算法的一种变体,k-NN算法是机器学习领域中用于分类任务的常用方法。在标准的k-NN分类中,算法在分类新数据点时,会查看训练集中k个最近的数据点,最终将这些邻居中的多数类别分配给新数据点。

然而,在加权最近邻分类中,不是仅仅统计最邻近数据的投票量,而是根据每个邻近数据与新数据点的距离为其投票加权。其原理是,较近的相邻数据应该对分类决策产生更大的影响,而较远的则影响较小。这个加权过程涉及计算新数据点与训练集中每个点之间的距离。常用的距离度量包括欧几里得距离、曼哈顿(Manhattan)距离或余弦相似度,具体选择取决于数据的特性。在这种情况下,我们使用曼哈顿距离(也称为城市街区距离)来计算数据点之间的距离。计算这个距离的公式如下所示。其中,w表示权重,测试用例是相对于其他训练数据进行评估的,这些训练数据被称为训练案例。

加权最近邻距离公式


理解基于能量的模型

机器学习中的基于能量的模型是一个多功能的框架,既适用于有监督学习任务,也适用于无监督学习任务。它的工作原理是为各种数据配置分配能量值,并学习一个能够区分理想配置和不理想配置的模型。这是通过最小化观测数据的能量,同时最大化未观测数据或不理想数据配置的能量来实现的。

基于能量的模型的核心在于定义一个能量函数,用E()表示。这个函数以输入变量的配置(或称为预测变量)以及一组模型参数作为输入。能量函数的输出是输入变量配置相关性的指征。例如,在评估回归模型的背景下,能量函数可以表示为均方误差。当将相关预测变量输入到均方误差方程中时,输出值往往较小,这反映了较高的相关性。相反,较差的预测变量会导致较大的均方误差值。能量函数为每个可能的变量配置分配一个标量值。

训练能量基模型的目标是学习能量函数的参数,以便为相关输入变量分配低能量,为不相关输入变量分配高能量。这包括定义一个目标函数,该函数会对为正确变量分配高能量,对错误变量分配低能量的情况进行惩罚。为了实现这一点,目标是识别出产生最低能量的错误变量配置,这种配置很可能导致模型做出错误的预测。面的函数表示输入配置x和模型参数w的能量,该能量输出错误的值y,这个值太低,以至于无法与产生准确预测的输入变量配置区分开来。 

错配的最低能量公式

最终,目标函数旨在最大化最低能量的错误配置与最近的正确配置变量之间的差异。该能量配置的公示如下所示。

最近的正确配置能量公式

目标函数,也被称为损失函数,包含一个基于每个样本的平均损失函数。下面给出的是对数损失(log loss)函数。

单样本平均损失函数(log loss)

各种衡量损失的规则都可以作为每个样本的损失函数,如hinge损失、对数损失(log loss)、平方损失和平方指数损失等,具体选择取决于应用场景。

综上所述,这些是FREL背后的基本概念。接下来的部分将深入探讨算法本身的具体内容。


FREL算法

为了有效应用FREL算法,必须遵循某些基本考虑因素。首先,仔细评估训练数据至关重要。FREL非常适合于将一组候选变量映射到单个目标的数据集。同样重要的是确保变量的尺度相似。如果向FREL提供尺度不一致的候选预测变量,最终结果可能会严重扭曲。

其次,由于FREL是基于能量的学习过程,因此它需要定义一个包含加权参数的能量函数。因此,所使用的模型应该配置为接受一组候选变量以及相应的权重。例如,如果以均方误差作为能量函数,并且模型是回归模型,那么纳入加权参数就相对直接了。每个权重将与一个候选预测变量配对。

最后,必须选择一个单样本的损失函数来确定损失函数。损失函数结合了模型的加权参数,是(一系列)函数中被最小化以获得最优权重的函数。

FREL算法的核心步骤如下:

训练数据矩阵

  1. 从一个包含n个观测值和d个候选预测变量的训练数据集开始,这些预测变量对应于n个目标值。目标是确定从d个候选预测变量中最相关的预测变量,以确定目标值。这导致为每个d个预测变量分配权重,表示该变量相对于其他变量的重要性。较大的权重表示在定义目标值时具有更大的相关性。 
  2. 最初,将所有权重的值设为1。
  3.  对训练数据中的每个观测值应用加权最近邻分类,以识别产生最低能量的错误变量配置以及具有高能量的正确变量配置的最近邻配置。使用这些能量值和所选的损失函数来计算每个样本的损失。
  4.  最后,使用适当的优化程序最小化目标损失函数,可以选择性地加入正则化。这构成了FREL算法的核心。
在他们的研究论文中,作者还展示了通过应用自举法(bootstrapping)对核心算法进行的改进。抽样必须是不放回的抽样,并且最终的权重是每个自举样本的平均值。


用MQL5实现FREL

本文中展示的FREL实现采用了Powell优化方法。虽然使用的具体优化方法不是关键,但不同方法的结果应该相对一致。在此实现中,Powell方法被表示为“PowellsMethod”类,该类在Powells.mqh中定义。FREL算法被封装在“FREL”类中,该类是“PowellsMethod”类的子类,并在frel.mqh中指定。

//+------------------------------------------------------------------+
   //| constructor                                                      |
   //+------------------------------------------------------------------+

                     FREL(matrix &in_data,int numboot=1, int bootsize=0)
     {
      m_data = in_data;
      m_num_boot=(numboot>0)?numboot:1;
      m_bootsize=(bootsize>2 && bootsize<=int(m_data.Rows()) && m_num_boot>1)?bootsize:int(m_data.Rows());
      
      
      if(ArrayResize(m_indices, int(m_data.Rows()))!=int(m_data.Rows()) ||
         ArrayResize(m_target_bin, int(m_data.Rows()))!=int(m_data.Rows()) ||
         ArrayResize(m_trial_weights, int(m_data.Cols()-1))!=int(m_data.Cols()-1) ||
         ArrayResize(m_work_weights, int(m_data.Cols()-1))!=int(m_data.Cols()-1)
        )
        {
         Print(__FUNCTION__, " error ", GetLastError());
         m_memory_allocated = false;
        }
      else
         m_memory_allocated = true;
     }

让我们深入了解参数化构造函数的描述。它至少需要一个参数:训练数据的矩阵。重要的是要注意训练数据在矩阵中的结构方式。每一行代表一个观测值或单个样本,而列则代表要评估的候选变量或预测变量。目标值应位于矩阵的最后一列。构造函数的可选参数在下表中进一步说明。

 参数名称
 数据类型
默认值
 说明
numboot
integer
1
"numboot" 参数用于指定要重复采样的次数
bootsize
integer
0
“bootsize”定义了每个自举样本的大小。使用这些变量要非常小心。如果使用的值大于矩阵中的观测值数量,“numboot”将自动回退到1,并且“bootsize”将设置为观测值的数量。

用户只需要熟悉一个方法就可以使用“FREL”类:“WeighVars()”。

//+-----------------------------------------------------------------------+
   //| Find the most relevant variables from a dataset of candidate variables|
   //+-----------------------------------------------------------------------+

   bool               WeighVars(int num_bins_target, double reg_factor,int &index[],double &weights[])
     {
      
      if(!m_memory_allocated)
        {
         Print(" INTERNAL ERROR ");
         return false;
        }
        
        
      if(num_bins_target<=1 || num_bins_target>int(m_data.Rows()))
       {
        Print(__FUNCTION__, " invalid function parameter: num_bins_target. Parameter should be >=2 ");
        return false;
       }  

      int ret=0;
      double target[], target_thresholds[] ;
      double sum ;

      int n_cases = int(m_data.Rows());
      m_reg_factor = MathAbs(reg_factor);
      m_loss = 0.0;


      if(ArrayResize(index,int(m_data.Cols()-1))!=int(m_data.Cols()-1) ||
         !np::vecAsArray(m_data.Col(m_data.Cols()-1),target)
        )
        {
         Print(__FUNCTION__, " error ", GetLastError());
         return false;
        }

      int k = num_bins_target ;
      if(!bin_array(target, k, target_thresholds, m_target_bin))
         return false;

      if(k<num_bins_target)
        {
         Print("error bins of target vector ", num_bins_target," : ", k);
         return false;
        }

      for(int i=0 ; i<n_cases ; i++)
        {
         if(m_target_bin[i] >= num_bins_target)
           {
            Print("error m_target_bin array at index ", i, " is ",m_target_bin[i], " should be less than ", num_bins_target);
            return false;
           }
        }

      ret = calc_wt(num_bins_target,m_loss,weights);

      if(ret<0)
         return false;

      sum = 0.0 ;
      for(ulong var=0 ; var<m_data.Cols()-1 ; var++)
        {
         weights[var] = m_data.Col(var).Std() * exp(weights[var]);
         sum += weights[var] ;
        }

      for(ulong var=0 ; var<m_data.Cols()-1 ; var++)
        {
         weights[var] *= 100.0 / sum ;
         index[var] = int(var) ;
        }

      MathQuickSortDescending(weights,index,0,int(weights.Size()-1)) ;

      return true;
     }

这个方法评估构造函数中指定的训练数据。它返回一个布尔值,“false”表示过程未能完成。这个方法的参数如下:

  • "num_bins_target":一个整数,定义了目标值将被划分成的箱(bin)的数量。此参数应设置为任何大于等于2的整数,但小于等于训练数据中的观测数。
  • "reg_factor":一个正的双精度浮点数值,用于控制正则化的程度。值为0时,禁用正则化。
  • "index[]":一个整数数组,用于存储部分操作结果的输出。它包含按与目标的相关性降序排列的原始列索引,这些索引将被构造函数所用。
  • "weights[]":一个双精度浮点数数组,包含按降序排列的最优权重。

当调用"WeighVars()"方法时,会从矩阵中提取目标值,并将它们放入一个数组中,以便准备调用私有方法"bin_array()"。这个方法将数组分割成大小大致相等的类别,并在成功完成后输出两个数组。"upperbound_thresholds[]"是一个数组,包含每个类别的上界阈值,而整数数组"categories[]"包含索引值,这些索引值表示每个对应的目标值所属的类别。会检查这些值中的每一个,以确保所有目标值都被正确地分箱(binned)。

//+------------------------------------------------------------------+
   //| calculates the optimal weights of candidate variables            |
   //+------------------------------------------------------------------+

   int               calc_wt(int num_bins_target,double &loss_value, double &w[])
     {
      int ret,rand_error, class_count[] ;

      ret = 0;

      if(ArrayResize(class_count,num_bins_target)!=num_bins_target || (w.Size()!=uint(m_data.Cols()-1) && ArrayResize(w,int(m_data.Cols()-1))!=int(m_data.Cols()-1)))
        {
         Print(__FUNCTION__, " error ", GetLastError());
         return -1;
        }

      ArrayInitialize(w,0.0);
      loss_value = 0.0 ;

      for(ulong i=0 ; i<m_data.Rows() ; i++)
         m_indices[i] = int(i) ;
     
      for(int ibootstrap=0 ; ibootstrap<m_num_boot; ibootstrap++)
        { 
         Comment(" Bootstrap iteration ", ibootstrap+1);
           
         ArrayInitialize(class_count,0);

         int ii, j, k, m;

         ii = int (m_data.Rows()) ;
         while(ii > 1)
           {
            m = int (m_data.Rows()) - ii ;
            if(m >= m_bootsize)
               break ;
            j = (int)(MathRandomUniform(0.0,1.0,rand_error) * ii) ;
            if(j >= ii)
               j = ii - 1 ;
            k = m_indices[m] ;
            m_indices[m] = m_indices[m+j] ;
            m_indices[m+j] = k ;
            --ii ;
            ++class_count[m_target_bin[m_indices[m]]] ;
           }
           

         for(int i=0 ; i<num_bins_target ; i++)
           {
            if(class_count[i] < 2)
               Print(__FUNCTION__, "  class at ", i, " has less than 2 members. 考虑调整参数Frel(number of partitions or bootstrap sample size)");
           }
            
         ArrayInitialize(m_trial_weights,0.0);

         ret += Optimize(m_trial_weights);
         loss_value += PowellsMethod::GetFret() ;

         for(ulong i=0 ; i<m_data.Cols()-1 ; i++)
            w[i] += m_trial_weights[i] ; 

        }

      for(ulong i=0 ; i<m_data.Cols()-1; i++)
        w[i] /= double(m_num_boot) ;

      return ret ;

     }

权重估计从调用"calc_wt()"方法开始。在这里,进行自举抽样(bootstrap sampling),在优化初始权重之前对数据进行随机打乱。优化是通过父类方法"Optimize()"来执行的。每个自举抽样的最优权重被累加到"w[]"数组中,在退出"calc_wt()"方法之前,会对这些权重进行平均计算。

//+------------------------------------------------------------------+
   //| function minimized by Powells optimization method                |
   //+------------------------------------------------------------------+
   virtual double          func(const double& p[])
     {
      double pen = 0.0 ;

      for(ulong i=0 ; i<m_data.Cols()-1 ; i++)
        {
         if(p[i] > 4.0)
           {
            m_work_weights[i] = exp(4.0) + p[i] - 4.0 ;
            pen += (p[i] - 4.0) * (p[i] - 4.0) ;
           }
         else
            if(p[i] < -3.0)
              {
               m_work_weights[i] = exp(-3.0) + p[i] + 3.0 ;
               pen += (p[i] + 3.0) * (p[i] + 3.0) ;
              }
            else
               m_work_weights[i] = exp(p[i]) ;
        }

      return (loss(m_work_weights) + pen) ;
     }

记住,被最小化的函数是损失函数,它由父类中被重写的一个方法“func()”表示。

//+------------------------------------------------------------------+
   //| calculates the loss function                                     |
   //+------------------------------------------------------------------+
   double            loss(double &w[])
     {
      double totaloss = total_loss(w);

      totaloss/=double(m_data.Rows());

      if(m_reg_factor>0.0)
        {
         for(ulong i=0; i<m_data.Cols()-1;i++)
            totaloss+=m_reg_factor*pow(w[i],2.0);
        }

      return totaloss;
     }

在“func()”方法中,调用了“loss()”方法,这进而触发了作为私有方法“total_loss()”实现的每个样本的损失函数的计算。

//+------------------------------------------------------------------+
   //|  loss over all data                                              |
   //+------------------------------------------------------------------+

   double            total_loss(double &w[])
     {
      int category,first, other ;
      double  distance, top, bottom, loss ;

      loss = 0.0 ;
      for(int i=0; i<m_bootsize; i++)
        {
         other = m_indices[i] ;
         category = m_target_bin[other] ;
         top = bottom = DBL_MAX ;

         for(int iother=0 ; iother<m_bootsize; iother++)
           {
            first = m_indices[iother] ;
            if(first == other)
               continue ;

            distance = 0.0 ;
            for(ulong v=0 ; v<m_data.Cols()-1; v++)
              {
               distance += w[v] * fabs(m_data[other][v] - m_data[first][v]) ;
              }

            if(m_target_bin[first] == category)
              {
               if(distance < top)
                  top = distance ;
              }
            else
              {
               if(distance < bottom)
                  bottom = distance ;
              }
           }

         distance = top - bottom ;
         if(distance > 30.0)
            loss += distance ;
         else
            loss += log(1.0 + exp(distance));
        }

      return loss ;
     }

在所有自举运算完成后,计算得到的平均最优权重会被写入用户提供的“weights[]”数组中。在按降序排序之前,会对权重进行转换,使它们的总和达到100,从而提高可读性。


使用FREL进行特征选择的示例

为了演示FREL算法,我们提供了“FrelExample.mq5”脚本。该脚本利用FREL来分析一个随机生成的包含候选变量和目标变量的数据集,以识别出最佳的预测变量。用户可以调整FREL算法的所有参数以及合成数据集的某些特性。这包括观测值的总数(num_observations)和候选预测变量的数量(num_candidate_predictors)。以下是展示脚本中用户可调整输入的片段:

//---user adjustable input parameters
input int number_of_partitions = 8; //Number of partitions
input double regularization_factor = 0.0; //Regularization factor
input int number_of_bootstraps = 1;
input int bootstrap_size = 0;
input ulong num_observations = 2000;// Sample size of random dataset
input ulong num_candidate_predictors = 10;// Maximum number of candidate predictors in dataset

脚本生成了一个具有num_observations行和num_candidate_predictors + 1列的随机数矩阵。最后一列被覆盖为索引为1、3、5和7的列之和,这一列作为数据集的目标变量。

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
   srand(126);
//---check user input parameters
   if(number_of_partitions<2 || num_observations<10 || num_candidate_predictors<8)
     {
      Print("Invalid input parameters");
      return;
     }
//---the data
   matrix dataset;
//---initialize size of random dataset
   dataset.Init(num_observations,num_candidate_predictors+1);
//---fill dataset with random data
   dataset.Random(1.0,10.0);
//---set the target variable in the last column
   if(!dataset.Col(dataset.Col(1) + dataset.Col(3) + dataset.Col(5) + dataset.Col(7),num_candidate_predictors))
     {
      Print("error ", GetLastError());
      return;
     }
//---initialize Frel object
   FREL frel(dataset,number_of_bootstraps,bootstrap_size);
//---declare containers to recieve output from Frel operation
   double optimal_weights[];
   int index[];
//---
   ulong timeIT = GetTickCount64();
//---find the most relevant predictors
   if(!frel.WeighVars(number_of_partitions,regularization_factor,index,optimal_weights))
      return;
//---calculate runtime
   Print("Runtime of FREL ", GetTickCount64() - timeIT, " ms");
//---display results
   for(uint i = 0; i<optimal_weights.Size(); i++)
      Print("Predictor at Column index ", index[i], " weight ", optimal_weights[i]);

  }
//+------------------------------------------------------------------+

目标是观察FREL是否能够恰当地为变量分配权重,特别是将第1、3、5和7列指定为与目标变量相关性最强的列。最初,我们使用默认参数执行脚本,注意到此时正则化被禁用,并且只指定了一次采样。

Frel脚本默认设置

输出

ON      0       18:12:30.906    FrelExample (BTCUSD,D1) Runtime of FREL 273375 ms
GD      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 7 weight 24.46987538756267
IH      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 3 weight 24.22319404776024
EL      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 5 weight 22.26820806768701
LP      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 1 weight 22.13748732798876
DD      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 0 weight 1.162036446785271
KK      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 8 weight 1.1532145209345603
RO      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 4 weight 1.1496286906955606
RS      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 2 weight 1.1472521997561425
NG      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 6 weight 1.14561384476096
DK      0       18:12:30.906    FrelExample (BTCUSD,D1) Predictor at Column index 9 weight 1.14348946606884

接下来,我们通过测试正则化程度为0.1和1.0的情况,来研究正则化对估计权重的影响。

正则化因子为0.1的Frel脚本设置

输出

MQ      0       18:19:03.951    FrelExample (BTCUSD,D1) Runtime of FREL 331296 ms
QD      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 3 weight 19.63442784832085
PK      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 5 weight 19.009699240770477
GO      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 7 weight 18.823288529399388
GQ      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 1 weight 18.18026689510982
NE      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 0 weight 4.106428447842871
KI      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 8 weight 4.075425288243113
OM      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 2 weight 4.070169243578418
MQ      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 6 weight 4.051103060690134
FE      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 9 weight 4.025271426001863
FJ      0       18:19:03.951    FrelExample (BTCUSD,D1) Predictor at Column index 4 weight 4.0239200200430805

正则化因子为1.0的Frel脚本设置

输出

HP      0       18:25:43.421    FrelExample (BTCUSD,D1) Runtime of FREL 362984 ms
FF      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 3 weight 10.353013480731704
JJ      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 7 weight 10.227015183302557
IM      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 5 weight 10.213781888319609
KQ      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 1 weight 10.079770794877978
PF      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 0 weight 9.948300319843046
QJ      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 8 weight 9.938367489770178
KN      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 2 weight 9.897336276433514
DQ      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 6 weight 9.79559491756489
EF      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 9 weight 9.774541742551756
CI      0       18:25:43.421    FrelExample (BTCUSD,D1) Predictor at Column index 4 weight 9.77227790660475

正则化测试的结果表明,权重开始分散到其他变量上,偏离了正确的变量。很可能,正则化程度的增加会导致权重之间的差异减小,从而难以区分有用变量和无关变量。

在检查我们测试的运行结果时,很明显FREL的运行速度相对较慢。瓶颈很可能在于“total_loss()”函数,因为优化器执行时需要多次遍历整个数据集。为了提高运行效率,我们采用较小的样本量进行了多次抽样。以下结果是从使用40个样本进行100次抽样运行中获得的。

BootStrapped Frel 的设置

输出

IN      0       18:30:55.441    FrelExample (BTCUSD,D1) Runtime of FREL 22985 ms
OK      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 3 weight 18.706272752181135
OL      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 1 weight 18.32079620338284
RS      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 5 weight 18.194009676469012
HG      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 7 weight 16.298306686632337
MI      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 4 weight 5.838867272535404
LM      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 9 weight 5.249285089162589
FQ      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 8 weight 4.791606631149278
DE      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 6 weight 4.770223641360407
KI      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 0 weight 3.974977300216029
KM      0       18:30:55.441    FrelExample (BTCUSD,D1) Predictor at Column index 2 weight 3.855654746910961


结论

在本文中,我们介绍了使用基于正则化能量模型进行特征加权的MQL5实现。我们简要概述了该算法的理论基础,并在一个合成数据集上展示了其有效性。尽管结果很有前景,但我们发现该算法的计算成本很高,导致分析速度较慢。为解决这一问题,我们提出了使用较小的样本量进行多次自举抽样(bootstrap)的方法,这显著提高了算法的整体执行速度。此外,采用多线程或GPU加速也能极大地有助于我们的实现。尽管如此,我们还是鼓励对该方法感兴趣的人根据自己的需求对代码进行定制。本文包含了所有讨论过的代码,每个源文件都在下面的表格中进行了详细说明。

源文件
说明
Mql5\include\np.mqh
一个含各种向量和矩阵操作工具的头文件
Mql5\include\Powells.mqh
包含实现函数最小化的Powell方法的PowellsMethod类的定义
Mql5\include\frel.mqh
包含代表基于正则化能量的特征加权学习算法的FREL类的定义
MQL5 脚本
一个演示使用FREL类的脚本


本文由MetaQuotes Ltd译自英文
原文地址: https://www.mql5.com/en/articles/14865

附加的文件 |
frel.mqh (14.08 KB)
Powells.mqh (17.57 KB)
np.mqh (37.73 KB)
FrelExample.mq5 (2.52 KB)
Mql5.zip (12.76 KB)
一步步学习如何利用公允价值缺口(FVG)或市场不平衡性来交易的策略:一种“聪明资金”的交易方法 一步步学习如何利用公允价值缺口(FVG)或市场不平衡性来交易的策略:一种“聪明资金”的交易方法
基于公允价值缺口(FVG)交易策略的MQL5自动化交易算法创建与分步实施指南。这一教程旨在为无论是初学者还是经验丰富的交易者提供一个实用的EA创建指南。
MQL5 简介(第 6 部分):MQL5 中的数组函数新手指南 (二) MQL5 简介(第 6 部分):MQL5 中的数组函数新手指南 (二)
开始我们 MQL5 旅程的下一阶段。在这篇深入浅出、适合初学者的文章中,我们将探讨其余的数组函数,揭开复杂概念的神秘面纱,让您能够制定高效的交易策略。我们将讨论 ArrayPrint、ArrayInsert、ArraySize、ArrayRange、ArrarRemove、ArraySwap、ArrayReverse 和 ArraySort。利用这些基本的数组函数,提升您的算法交易专业知识。加入我们的精通 MQL5 之路吧!
基于预测的统计套利 基于预测的统计套利
我们将探讨统计套利,使用Python搜索具有相关性和协整性的交易品种,为皮尔逊(Pearson)系数制作一个指标,并编制一个用于交易统计套利的EA,该系统将使用Python和ONNX模型进行预测。
您应当知道的 MQL5 向导技术(第 12 部分):牛顿多项式 您应当知道的 MQL5 向导技术(第 12 部分):牛顿多项式
牛顿多项式,其依据一组少量点创建二次方程,是一种古老但有趣的时间序列观察方式。在本文中,我们尝试探讨这种方式在哪些方面对交易者有用,并解决其局限性。