English Deutsch
preview
知っておくべきMQL5ウィザードのテクニック(第14回):STFによる多目的時系列予測

知っておくべきMQL5ウィザードのテクニック(第14回):STFによる多目的時系列予測

MetaTrader 5テスター | 27 5月 2024, 10:45
114 0
Stephen Njuki
Stephen Njuki

はじめに

SpatiaTemporal Fusion(STF)に関するこの論文で、予測に対する両面からのアプローチのテーマに対する興味をそそられました。おさらいしておくと、本稿は、UberやDidiのような双方向ライドヘイリングプラットフォームにおける需要と供給の両方について協調する確率ベースの予測問題を解くことに着想を得ています。協調的な需要と供給の関係は、Amazon、Airbnb、eBayなどのさまざまな両面市場で一般的です。本質的に、企業は従来の「顧客」または購入者にサービスを提供するだけでなく、顧客のサプライヤーにも対応します。

そのため、供給が一部需要に依存しているケースでの両面予測は、こうした企業にとって頻繁に重要な意味を持つことになります。しかし、この需要と供給の二重の予測は、時系列やデータセットに特定の値を予測するという従来のアプローチとは一線を画すものでした。また、この論文では、需要と供給の因果的な「協調」関係を行列Gで捉え、すべての予測を変圧器ネットワークを介しておこなうという、causaltransのフレームワークと呼ばれるものを導入し、その結果は注目に値するものでした。

そこからヒントを得て、私たちは、弱気と強気をこの2つの指標の代用として使用することで、取引される証券の需給を予測しようと考えています。しかし厳密に言えば、典型的なExpertSignalクラスは、MQL5ライブラリファイルやこれまでこの連載でコーディングしたファイルを見ればわかるように、これらの値を0~100の範囲の整数として計算しています。しかし新しいのは、予測をおこなう際に空間行列と時間パラメータを追加することでしょう(論文から引用した2つの追加入力)。

取引証券の空間的量子化は主観的なものであり、時間メトリックの選択も主観的なものです。需要と供給のアンカーとしてセキュリティの高価格と低価格のシリーズを使用し、これらのバッファ間の自己相関値を空間行列の座標として使用し、曜日インデックスを時間指標として使用します。この初歩的なアプローチは、カスタマイズや改良が可能であり、この記事の目的には適しています。

この論文ではtransformerネットワークを使用していますが、私たちの目的には非効率的なので使用しません。すべての予測はカスタムメイドのハンドコーディング多層パーセプトロンを使用します。多層パーセプトロンに関するライブラリやコードサンプルはたくさんあるので、自分でコーディングしようとするのは時間の無駄に思えるでしょう。しかし、使用されているネットワーククラスは300行にも満たない長さで、層の数や各層のサイズをカスタマイズする限りでは、それなりにスケーラブルです。これは、利用可能なほとんどの定型ライブラリにはまだ欠けています。

そのため、transformerではなく、特異なニューラルネットワークを使用することで、この論文のcausaltransフレームワークの実装はここでは実現されない。とはいえ、需要と供給の二重予測をおこなうことに変わりはなく、その過程で空間行列や時間も使用することになるので、何を使用するかで手一杯です。また、どのような取引システムにもリスクが内在しているのはいつものことなので、ここで共有されている資料をさらに利用する前に、読者各自が十分な注意を払うことを歓迎します。



STFイラストレーション

STFは、リモートセンシングで使用され、空間と時間のメトリックスを結びつけることができるビジュアル中心の活動で主に使用されます。

取引以外でSTFの可能性を探ることにあまり興味がないのであれば、このセクションは飛ばしてMQL5の実装に進むことができます。

リモートセンシングを見ると、例えば、衛星によってキャプチャされた画像はデータの空間成分と検査対象の領域をキャプチャしますが、時間は画像が撮影された時間を指します。このような情報は、時系列を形成するだけでなく、STFのおかげで、調査対象地域の天候、植物、あるいは動物の生息環境の変化を予測する上で重要なものとなります。

STFが森林伐採や植生に関連する問題にどのように貢献できるのか、順を追って考えてみましょう。機械学習の問題でよくあるように、この最初のステップはデータの収集です。リモートセンシング衛星は、調査地域のマルチスペクトル画像を一定期間にわたって撮影します。人工衛星がマルチスペクトルであることを考えると、肉眼では見えないが、植生や水域などに関連する波長帯の反射吸収波長情報を捉えることができます。これらの画像は、ある程度の時間をかけて撮影されたものであるため、シリーズにモデリングできるデータの種類に豊かさ(と複雑さ)が加わります。

各画像にはすでにタイムスタンプが付けられているため、適切なGPS座標系を使用して各画像をマッピングすることができ、キャプチャされたすべての時点のすべての画像にわたる空間情報の一貫性が保証されます。

続くのは、「データ」を正規化して、植生と森林伐採に適した形式にすることでしょう。これを実現する方法の1つが、NDVI(Normalized Difference Vegetation Index)によって、異なる時点の各画像のスペクトルシグネチャを記録することです。そうすることで、データをモデルの訓練で扱いやすくするだけでなく、目の前の対象に集中させることができます。

この正規化には、植生にとって重要な特徴を抽出または定義できるように、撮影画像の経時変化を検出することも含まれます。これらの特徴には、成長率、季節変動、分布パターンなどが含まれます。これらの特徴はそれぞれ、データの次元を形成する可能性があります。

モデルの選択はさまざまですが、ニューラルネットワークが最有力候補でしょう。現在、画像のかなりの部分が正規化されたデータとなっており、このために使用され、一般的にそうであるように、確保されるテスト用のデータセットはより少なくなっています。

そのため、モデルによる予測は、訓練とテストが成功した結果に基づいておこなわれることになりますが、留意すべき重要な点は、すでに多くの正規化がおこなわれているため、モデルの出力についてはその逆を注意深くおこなわなければならないという解釈です。

最近、ACMによって受理された私たちの論文の引用では、将来の需要と供給の方程式は以下のように表されています。

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:予測をおこなう時間増分
  • t:時間

つまり、この場合、関数f xとf yは、それぞれの入力層に供給されるデータを保持するパラメータベクトルまたは行列を持つニューラルネットワークとなります。


MQL5によるSTFの実装

MQL5でSTFを実装するには、上記の共有方程式に従って、モデルへの入力データをどのように構成するかを設定します。この2つの方程式から、それぞれの入力データは通常ベクトルか行列形式をとることは明らかであり、これはもちろん無数の可能性と課題を提示します。2つの方程式における各f関数の潜在的な入力は同様のバッファであり、2つの方程式の唯一の違いは、供給方程式が以前の値だけでなく、需要の値にも依存していることです。これは、供給は需要に左右され、その逆はないという論文の著者のテーゼに従っています。

つまり、両方の方程式の重なりを考慮すると、バッファの総数は4となります。これらはすべて供給方程式の中に存在し、それらを列挙すると、以前の需要、以前の供給、空間的価値、そして時間の増分です。

需要バッファは、この記事では「強気」価格点の時系列バッファと解釈されます。おそらく、より簡潔なバッファは、長い契約の実際のボリュームでしょうが、そのような情報はめったに証券会社によって共有されませんし、外国為替市場におけるボリューム情報の分裂の性質を考えると、共有されたとしてもボリュームの正確な表現ではないでしょう。そのため、始値を下回る高値が、実質的なロングボリューム契約の代替バッファとして選択されます。この役割を果たす他の緩衝材としては、金利、インフレ率、あるいは中央銀行のマネーサプライ指数など、通貨固有の指標が考えられます。高値から始値を差し引いた値をバッファとして選択したのは、上方へのボラティリティを測定するためです。これは長い出来高の契約と正の相関があると理解できるため、次善のプロキシとして使用しました。これらの値は正か0でしかなく、0の場合は首吊り線(ハンギングマン)かフラットプライスバーを示します。

供給バッファも、その前段と同様、始値から安値を引いた値で近似されます。これは、弱気の出来高契約と正の相関がある下方ボラティリティの読みとも受け取れます。また、上記と同様に、このバッファの値は正の値のみとなり、0の値は墓石童子スターまたはフラットバーを示します。供給方程式は需要とは異なり、より多くの入力を必要とするため、そのモデルも需要と似ているが異なることを意味します。そのため、予測モデルには需要用と供給用の2つのインスタンスが存在することになります。最終的な結果は単一のシグナルを得ることなので、これは需要予測から供給予測を差し引くことで決定されます。需要と供給モデルへのすべての入力は正またはゼロであるため、おそらく出力も同様であるはずです。したがって、需要出力から供給モデルの出力を引くと、正の値が強気を示し、負の値が弱気を意味する2つの数値が得られます。

時間バッファの選択は単純で、曜日のインデックスです。次のセクションで取り上げるテストは日足でおこなわれるため、曜日のインデックスは簡単にそれに結びつきます。ただし、代替の時間枠、つまり日足よりも小さい時間枠を考慮する場合は、1日または1週間以内のインデックスを考慮することもできます。例えば、8時間足では、1週間に15本の8時間足があり、週内に15種類の時間指標が存在します。その日の時間帯や取引セッションを選ぶなど、選択肢は豊富であり、事前にテストして自分の取引システムに最適なものを選ぶのが良い方法かもしれません。曜日指数を返す簡単な関数は以下の通りです。

//+------------------------------------------------------------------+
//| 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);
}

G行列は、このモデルの空間データをキャプチャします。証券取引環境における空間はどのように定義するのでしょうか。例えば、私たちの参考論文を考えてみると、需要と供給の間のメタデータのクロステーブルは、この論文でGraph Attention Transformers (GAT)と呼ばれているものに通すことによって「正規化」されます。これらは2つの層で動作します。最初の層は複雑なノード関係を取得し、2番目の層は最終的なノード予測のために近隣情報を集約します。GATの測定値は、需要や供給を予測するためにそれぞれのニューラルネットワークに送られるデータの一部となります。私たちの場合、強気価格バッファと弱気価格バッファのメタデータは、これらのバッファが共有する相関値から取得されます。これらの相関関係は、以下のコードに示すようにキャプチャされます。

//+------------------------------------------------------------------+
//| 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++)
   {  _x1[i] = X[i];
      _x2[i] = X[i+m_train_set];
      _y1[i] = Y[i];
      _y2[i] = Y[i+m_train_set];
   }
   _m[0][0] = _x1.CorrCoef(_x2);
   _m[0][1] = _x1.CorrCoef(_y2);
   _m[1][0] = _y1.CorrCoef(_x2);
   _m[1][1] = _y1.CorrCoef(_y2);
   return(_m.Det());
}


行列式を使用するため、行列の個々の読み取り値ではなく、行列を表す単一の値を返すことに注意してください。相関値は常に-1.0から+1.0まで正規化されるため、個々の測定値を代わりに使用することも可能であり、この方がモデル全体としてより正確な結果が得られる可能性があります。私たちの目的では、とにかく予備テストでは効率の方が重要なので、決定力にこだわりました。

4つのデータバッファをすべて説明したところで、ライブラリを使わずにコーディングされた単純なニューラルネットワークである、私たちの非常に初歩的なモデルについても話しておくと役に立つかもしれません。ネットワークを、入力、重み、バイアス、隠れ出力、出力、目標という非常に基本的な構成要素に分解し、フォワードフィードとバックプロパゲーションをおこなう際にこれらのみを使用します。ネットワークインターフェイスは以下の通りです。

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class Cnetwork
{
protected:
   matrix            weights[];
   vector            biases[];

   vector            inputs;
   vector            hidden_outputs[];
   vector            target;

   int               hidden_layers;
   double            Softplus(double X);
   double            SoftplusDerivative(double X);

public:
   vector            output;

   void              Get(vector &Target)
   {                 target.Copy(Target);
   }

   void              Set(vector &Inputs)
   {                 inputs.Copy(Inputs);
   }
   
   bool              Get(string File, double &Criteria, datetime &Version);
   bool              Set(string File, double Criteria);

   void              Forward();
   void              Backward(double LearningRate);

   void              Cnetwork(int &Settings[],double InitialWeight,double InitialBias)
   {                 
                        
                        ...
                        ...

   };
   void              ~Cnetwork(void) { };
};

入力と目標の設定と取得のための一般的な関数に加えて、訓練後の重みとバイアスのエクスポート関数も含まれています。フィードフォワードアルゴリズムは、各層の活性化にソフトプラスを使用した普通のもので、バックプロパゲーション機能も、ネットワークの重みとバイアスを調整する際にチェーンルールと勾配降下法に頼った旧式のものです。しかし、ネットワークを初期化するにはいくつかの入力が必要で、クラスのインスタンスを安全に使用する前に、これらの入力は「検証」を通過しなければなりません。ネットワークを作成するための入力は、設定配列、(ネットワーク全体の)初期重みの値、および初期バイアス値です。設定配列は、それ自身のサイズによってネットワークが持つ隠れ層の数を決定し、そのインデックスの各整数はそれぞれの層のサイズを設定します。

   void              Cnetwork(int &Settings[],double InitialWeight,double InitialBias)
   {                 int _size =    ArraySize(Settings);
                     if(_size >= 2 && _size <= USHORT_MAX && Settings[ArrayMinimum(Settings)] > 0 && Settings[ArrayMaximum(Settings)] < USHORT_MAX)
                     {  ArrayResize(weights, _size - 1);
                        ArrayResize(biases, _size - 1);
                        ArrayResize(hidden_outputs, _size - 2);
                        hidden_layers = _size - 2;
                        for(int i = 0; i < _size - 1; i++)
                        {  weights[i].Init(Settings[i + 1], Settings[i]);
                           weights[i].Fill(InitialWeight);
                           biases[i].Init(Settings[i + 1]);
                           biases[i].Fill(InitialBias);
                           if(i < _size - 2)
                           {  hidden_outputs[i].Init(Settings[i + 1]);
                              hidden_outputs[i].Fill(0.0);
                           }
                        }
                        output.Init(Settings[_size - 1]);
                        target.Init(Settings[_size - 1]);
                     }
                     else
                     {  printf(__FUNCSIG__ + " invalid network settings. ");
                        //~Cnetwork(void);
                     }
   };


需要と供給の両方を予測するので、それぞれのタスクを処理するために、ネットワークのインスタンスが2つ必要になります。CheckOpenLong 関数とCheckOpenShort関数のフィードとして機能するGetOutput関数は、各ネットワークのそれぞれの入力層を前述のデータバッファで満たします。需要については、需要はその事前値に加え、空間と時間のパラメータにのみ依存するため、その入力層のサイズは3です。しかし、供給については、その事前値に依存することに加え、以前の需要の影響を受ける可能性があるため、同様の空間と時間の入力を考慮すると、その入力層のサイズは4です。これらの層の充填は、それぞれの新しいバーの出力取得関数内で次のように処理されます。

//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double CSignalNetwork::GetOutput()
{  

        ...
        ...

   for(int i = 0; i < m_train_set; i++)
   {  for(int ii = 0; ii < __LONGS_INPUTS; ii++)
      {  if(ii==0)//time
         {  m_model_longs.x[i][ii] = T(m_time.GetData(i));
         }
         else if(ii==1)//spatial matrix
         {  vector _x,_y;
            _x.CopyRates(m_symbol.Name(),m_period,2,StartIndex() + ii + i,2*m_train_set);
            _y.CopyRates(m_symbol.Name(),m_period,4,StartIndex() + ii + i,2*m_train_set);
            m_model_longs.x[i][ii] = G(_x,_y);
         }
         else if(ii==2)//demand
         {  m_model_longs.x[i][ii] = (m_high.GetData(StartIndex() + ii + i) - m_open.GetData(StartIndex() + ii + i));
         }
      }
      if(i > 0) //assign classifier 
      {  m_model_longs.y[i - 1] = (m_high.GetData(StartIndex() + i - 1) - m_open.GetData(StartIndex() + i - 1));
      }
   }
   for(int i = 0; i < m_train_set; i++)
   {  for(int ii = 0; ii < __SHORTS_INPUTS; ii++)
      {  if(ii==0)//time
         {  m_model_shorts.x[i][ii] = T(m_time.GetData(i));
         }
         else if(ii==1)//spatial matrix
         {  vector _x,_y;
            _x.CopyRates(m_symbol.Name(),m_period,4,StartIndex() + ii + i,2*m_train_set);
            _y.CopyRates(m_symbol.Name(),m_period,2,StartIndex() + ii + i,2*m_train_set);
            m_model_shorts.x[i][ii] = G(_x,_y);
         }  
         else if(ii==2)//demand
         {  m_model_shorts.x[i][ii] = (m_high.GetData(StartIndex() + ii + i) - m_open.GetData(StartIndex() + ii + i));
         }  
         else if(ii==3)//supply
         {  m_model_shorts.x[i][ii] = (m_open.GetData(StartIndex() + ii + i) - m_low.GetData(StartIndex() + ii + i));
         }
      }
      if(i > 0) //assign classifier
      {  m_model_shorts.y[i - 1] = (m_open.GetData(StartIndex() + i - 1) - m_low.GetData(StartIndex() + i - 1));
      }
   }

        ...
        ...

}

この後、各ループが設定されたエポック数のネットワークを反復する学習ループ内で、モデル構造体からこの情報を取得することにより、2つのネットワークに入力値と目標値を割り当てます。予備テストから、理想的なエポック数は、学習ループあたり学習率0.5で約1万回であることがわかりました。これは確かに計算集約的であり、次節で紹介するテスト結果が約250エポックという非常に保守的な値を用いているのはそのためです。

セット出力機能により、初期化時に使用した重みによって設定された基準を上回るパス結果が得られた場合、各パスでネットワークの重みとバイアスをログに記録することができます。初期化時に重みを読み込むオプションがあり、その重みによって設定された基準が現在のテスト実行のベンチマークとなります。


テスト実行

非常にシンプルなネットワーク設定で、2023年のEURUSDを日足でテストしました。需要予測ネットワークは、1つの隠れ層を持つ合計3層で、そのサイズは3、5、1です。供給予測ネットワークにも3つの層がありますが、前述のように入力層のサイズが異なるため、そのサイズは4、5、1となります。両ネットワークの末尾の1には、それぞれのネットワークの出力が格納されます。

いつものように、この記事の最後に添付されているコードをエキスパートアドバイザーに組み立てるには、MQL5ウィザードを使用します。したがって、初めての方や慣れていない方は、こちらこちらの記事を参考にしてください。

これらの2つの設定は非常に基本的なもので、参照されるネットワーククラスが、初期化設定で定義されていれば、それぞれUCHAR_MAXの層を生成できることを考えると、考えつく最も単純なものであることは間違いありません。より多くの層が使用され、さらに大きな層サイズが使用されると、コンピューティングリソースは増加しますが、少数の層で設定されている場合でも、通常は100ユニット範囲の層サイズで十分であると考えられることは指摘する価値があります。

このアプローチはより長期的な傾向があり、主要な価格トレンドをより適切に評価する傾向があるため、シグナルが反転するまでポジションが保持される、出口価格目標なしでいつものように実行します。いくつかの理想的な設定で実のティックパスをおこなうと、以下のようなレポートが得られます。

レポート

エクイティカーブは以下の通りです。

カーブ

このレポートを掘り下げてみると、年間を通じて取引の回数が少なすぎることは明らかです。そもそも、シグナルが反転するまで長期にわたって保有され、このテスト期間中、最小限のドローダウンに見舞われていることから、その質は確かであり、悪いことではありません。しかし、問題なのは、横ばい相場やウィップソー相場では、特にレバレッジが効いている場合に、価格の微小な動きに敏感になることが賢明な場合が多いということです。私たちがテストしたシステムでは日足を使用していました。大局的な視点に集中する傾向があるため、これには問題ありませんが、もう少し現実的なものにするのであれば、より短い時間枠、おそらく4時間足や1時間足を考慮する必要があるでしょう。このようなことをすると、テストのための計算リソースだけでもかなりの大きさになります。この関係は指数関数的といっても過言ではありません。そして、これは隠れ層が5点で、空間行列が行列式に縮小された3層の非常に初歩的なネットワークであることを覚えておいてください。これらの要素はすべて重要です。なぜなら、より短い時間枠を扱うようになると、ノイズをふるいにかける必要性がより重要になり、その最良の方法の1つが、少し衒学的になることだからです。 

さらに、参照されるネットワーククラス内には、各パスの最初と最後にネットワークの重みとバイアスの設定をインポートおよびエクスポートするのに役立つ関数があります。これもプロセスが少し遅くなるため、これらのテストの実行には使用しませんでしたが、長期間テストする場合には使用する必要があります (このテストでは1年しか考慮していません)。これらを使用する場合、ネットワーククラスではデフォルトで大きいほど良いため、テスト実行の基準を慎重に検討する必要があります。そのため、例えばドローダウンをより重視するのであれば、ネットワーククラスに添付されているコードを適宜修正して、各パスの実行時に、ファイルに書き込まれる重みが、その実行の基準値が前の値よりも小さい場合にのみ更新されるようにする必要があります。これはまた、不要なエラーを避けるために、各実行の開始値またはデフォルト値をDBL_MAXまたは十分に高い値にする必要があることを意味します。


結論

STFの二重予測を扱う能力は、確かにあまり一般的ではないアプローチを提示していますが、疑いなく改良と改善の可能性を秘めた魅力的なものです。例えば、テストで使用した空間情報のG行列は、入力データベクトルをより小さな部分に分割することによってn×nに拡張することができる上に、その各値は、ネットワークの入力データ点になる可能性があり、その他にも多くの調整が可能です。ただし、これらの変更は計算リソースの犠牲を伴います。

実際、一般的にニューラルネットワークによるSTFの実装は、本質的に計算量の多い試みです。信頼できる交差検証をおこなうためには、かなり大量のデータでテストする必要があります。これは、ネットワークtransformerが使用された上記の引用論文で実施された場合、さらに明らかです。

NVIDIAがこのような状況においてますます重要性を増しているのを見るにつけ、この技術の側面は徐々に業界に受け入れられつつあります。ランダムフォレストのようなより効率的な代替モデルも、その設定が過度に複雑でなければ検討できますが、計算コストが低下し始めると、その費用対効果は実現不可能になるかもしれません。

MQL5ウィザードはアイデアを素早くプロトタイプ化し、テストするためのツールであることに変わりはありません。



MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/14552

添付されたファイル |
Network.mqh (10.87 KB)
SignalWZ_14_aa.mqh (14.03 KB)
nn_a.mq5 (6.59 KB)
どんな市場でも優位性を得る方法 どんな市場でも優位性を得る方法
現在の技術レベルに関係なく、取引したいどのような市場でも先んじることができる方法を学びましょう。
MetaTrader 5用のMQTTクライアントの開発:TDDアプローチ(最終回) MetaTrader 5用のMQTTクライアントの開発:TDDアプローチ(最終回)
この記事は、MQTT 5.0プロトコルのネイティブMQL5クライアントの開発ステップを説明する連載の最終回です。ライブラリはまだ製品化されていませんが、この部分では、他の証券会社から入手したティック(またはレート)でカスタム銘柄を更新するためにクライアントを使用します。ライブラリの現在の状況、MQTT 5.0プロトコルに完全に準拠するために足りないもの、可能なロードマップ、そしてその開発をフォローし貢献する方法についての詳細は、この記事の最後をご覧ください。
GMDH (The Group Method of Data Handling):MQL5で多層反復アルゴリズムを実装する GMDH (The Group Method of Data Handling):MQL5で多層反復アルゴリズムを実装する
この記事では、MQL5におけるGMDH (The Group Method of Data Handling)の多層反復アルゴリズム実装について説明します。
MQL5で自己最適化エキスパートアドバイザーを構築する MQL5で自己最適化エキスパートアドバイザーを構築する
どのような市場にも対応できる専門的なエキスパートアドバイザー(EA)を構築します。