量化软件——赫兹MT5多层感知器函子

概述
到目前为止,该系列已经展示了如何在 MQL5 代码中表示和使用范畴论中的一些基本概念,从而帮助交易者开发更强壮的交易系统。范畴论的主题有很多层面,但按理说两个关键方面可能是函子和性质变换。故此,通过再次讨论函子(就像我们之前的两篇文章一样),我们强调了该主题的顶端思路之一。

来自财经日历数据的范畴论函子
通过运用图论达成财经日历数据重新格式化,并作为一个范畴,适合得出日历数据复杂的相互关联性。从 MetaTrader 5 终端的日历选项卡中可以看出,有大量不同类型的财经数据。这个问题在之前的文章中已经强调过,需要将这些数据配对,鉴于货币对的特殊性,针对货币对制定交易决策会很困难。对于预期的证券,尽管在上一篇文章和本文中,没有必要将数据配对,但仍然应当考虑其中一些数据依赖于其它财经数据的概念,特别是考虑到我们的证券普适性,标普 500 指数。故此,为了定位这个问题,我们在上一篇文章中提出了一个简单的假设,即 CPI 数据依赖于 PMI 数据,PMI 又依赖于最新的 10 年期竞卖收益率,竞卖收益率又受到零售销售的影响。因此,时间序列并非只有其中一个经济数据点,而是针对标准普尔 500 指数波动,我们得到由多个点形成的系列基础。

不过,在这篇文章中,我们对标普 500 指数更感兴趣,不仅仅是因为它的波动性,就像上一篇文章的情况,还有它的趋势。我们希望对其短期(月度)趋势进行预测,并在我们的智能系统中使用这些预测开仓。这意味着我们与智能信号类打交道,而不是智能尾随类,就像该系列到目前为止的情况一样。那么,依据财经日历数据图形实现基于函子的变换将导致标普 500 指数的预测变化。这种实现将在多层感知器的帮助下达成。


标准普尔 500 指数值的范畴论函子
在信号文件内,将标普 500 指数值表述为图形相当于一个范畴,因为正如上一篇文章所分享的,每个图形顶点(数据点)等价于一个对象,因此顶点之间的箭头可以被视为态射。一个对象可以有一个元素,但在这种情况下,数据点不仅包含我们感兴趣的数值,还有我们的范畴未考虑的额外数据包括:财经数据发布日期、该数据发布前的预测共识、以及 MetaTrader 终端的日历选项卡中列出的其它数据。此链接指向一个包含日历事件类型的页面,列举的每个属性都适用于我们的对象。然后,所有这些数据将在财经日历范畴中形成一个对象,或我们所说的集合。

若要利用函子来分析和预处理历史财经日历数据,不幸的是,这在策略测试器中只能通过第三方完成,而不能直接从 MetaQuotes 的服务器完成。这当然是一个瓶颈问题,我们已经通过脚本将数据导出到 csv,然后像上一篇文章一样在策略测试器中读取该 csv。于此的区别在于,我们在执行此操作时,针对的是智能信号类实例,而非尾随类。由于我们正在与两个函子打交道,因此所用脚本在两个文件写入,其一前缀为 “true”,意即函子交叉对象,另一个前缀为 “false”,意即交叉态射。写入文件附在文章末尾。

上面的示意图中共享了转换后的标普 500 指数值的基于图形的表示。

基于函子的神经网络架构
在本文中,函子作为多层感知器(神经网络)比我们之前跨范畴、甚至范畴内对象(因为两个元素之间的态射关系可以用相同的方式定义)映射时所用的线性或二次关系更进一步。如前强调的,函子的使用不仅意味着两个范畴中的对象交叉映射,还意味着它们各自交叉态射。因此,彼此能够互查,即如果您知道协域范畴中的对象,则隐含态射,反之亦然。这意味着我们将与范畴之间的两个感知器打交道。

本文也不会提供关于感知器的入门知识,因为已有太多文章,不仅有发表在本网站上的文章,也有普遍的在线文章,故邀请好奇的读者自行去背景研究,这将有助于澄清这里讲述的内容。此处实现的网络架构很大程度上要归功于 Alglib,它可从 MetaTrader 的 IDE 中的 “Include\Math” 文件夹下访问。这是如何使用函数库执行感知器初始化:

//+------------------------------------------------------------------+
//|   Function to train Perceptron.                                  |
//+------------------------------------------------------------------+
bool CSignalCT::Train(CMultilayerPerceptron &MLP)
   {
      CMLPBase _base;
      CMLPTrain _train;
      
      if(!ReadPerceptron(m_training_profit))
      {
         _base.MLPCreate1(__INPUTS,m_hidden,__OUTPUTS,MLP);
         m_training_profit=0.0;
      }
      else
      {
         printf(__FUNCSIG__+" read perceptron, with profit: "+DoubleToString(m_training_profit));
      }
      
      ...
      
      return(false);
   }


该函数库中所用的感知器非常基本,它们由三层组成。输入层、隐藏层和输出层。我们的财经数据范畴一次有四个数据点(基于我们的假设),故隐藏层中的输入数量将为四个。隐藏层上的数据点数量是为数不多的可优化参数之一,但我们的默认值是 7。最后,输出层中有一个输出,即标普 500 指数的预测变化。权重、背离和激活函数的知识是理解感知器前馈工作的关键。再次邀请读者在必要时自行研究这些知识点。

训练基于函子的神经网络
历史财经日历数据的训练过程将采用 Levenberg-Marquardt 算法完成。与前馈和反向验算一样,该编码由 AlgLib 函数处理。我们将据函数库实现以下训练:

      int _info=0;
      CMatrixDouble _xy;
      CMLPReport _report;
      TrainingLoad(m_training_stop,_xy,m_training_points,m_testing_points);
      //
      if(m_training_points>0)
      {
         _train.MLPTrainLM(MLP,_xy,m_training_points,m_decay,m_restarts,_info,_report);
         
         if(_info>0){ return(true); }
      } 


此处的关键部分是从共用目录中 csv 文件中读取输入数据,并填充 XY 矩阵。每当生成新柱线(或计时器)时,矩阵都会获取每个数据行上定义的四个数据点作为历史数据,并用它来训练网络,从而生成其权重和背离。由 “TrainingLoad” 函数处理 XY 输入矩阵的填充,如下所示:

//+------------------------------------------------------------------+
//|   Function Get Training Points and Initialize Training Matrix.   |
//+------------------------------------------------------------------+
void CSignalCT::TrainingLoad(datetime Date,CMatrixDouble &XY,int &TrainingPoints,int &TestingPoints)
   {
      TrainingPoints=0;
      TestingPoints=0;
      
      ResetLastError();
      string _file="_s_"+m_currency+"_"+m_symbol.Name()+"_"+EnumToString(m_period)+"_"+string(m_objects)+".csv";
      int _handle=FileOpen(_file,FILE_SHARE_READ|FILE_ANSI|FILE_COMMON,"\n",CP_ACP);
      
      if(_handle!=INVALID_HANDLE)
      {
         string _line="";
         int _line_length=0;
         
         while(!FileIsLineEnding(_handle))
         {
            //--- find out how many characters are used for writing the line
            _line_length=FileReadInteger(_handle,INT_VALUE);
            //--- read the line
            _line=FileReadString(_handle,_line_length);
            
            string _values[];
            ushort _separator=StringGetCharacter(",",0);
            if(StringSplit(_line,_separator,_values)==6)
            {
               datetime _date=StringToTime(_values[0]);
               
               _d_economic.Let(); _d_economic.Cardinality(4);
               
               //printf(__FUNCSIG__+" initializing for: "+TimeToString(Date)+" at: "+TimeToString(_date));
               
               if(_date<Date)
               {
                  TrainingPoints++;
                  //
                  XY.Resize(TrainingPoints,__INPUTS+__OUTPUTS);
                  
                  for(int i=0;i<__INPUTS;i++)
                  {
                     XY[TrainingPoints-1].Set(i,StringToDouble(_values[i+1]));
                  }
                  //
                  XY[TrainingPoints-1].Set(__INPUTS,StringToDouble(_values[__INPUTS+1]));
               }
               else
               {
                  TestingPoints++;
               }
            }
         }
         
         FileClose(_handle);
      }
      else
      {
         printf(__FUNCSIG__+" failed to load file. Err: "+IntegerToString(GetLastError()));
      }
   }

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值