English Русский 中文 Español Deutsch
preview
主成分を用いた特徴量選択と次元削減

主成分を用いた特徴量選択と次元削減

MetaTrader 5統計と分析 |
156 1
Francis Dube
Francis Dube

はじめに

金融時系列予測では、多数の特徴量を分析する必要があり、その多くが高い相関を持つ場合があります。次元削減技術として一般的に使用される主成分分析(PCA)は、これらの特徴をよりコンパクトに表現する際に役立ちます。しかし、PCAには限界があり、特に高相関の変数が含まれる場合には課題が生じます。このようなケースでは、PCAは「グループ化効果」と呼ばれる特性を示し、高相関の変数群が特定の主成分に集合的に寄与する傾向があります。PCAは個々の変数を際立たせるのではなく、相関のある変数群全体にわたって影響を比較的均等に分散させるのです。

この均等分散は、主成分が個別のランダムな揺らぎではなく共通のパターンを強調するため、ノイズ抑制には有益です。しかし、その代償として、主成分ごとの個々の変数の寄与が希薄化される場合があります。独立して重要である可能性のある変数も、その影響が変数群に吸収され、変換後の空間内では重要性が低下したように見えることがあります。これは、変数選択で最も影響力のある特徴を特定する場合や、特定の変数の直接的な影響を分析する必要がある根本原因分析において、大きな欠点となる可能性があります。

さらに、PCAの特性はモデルの解釈を難しくする場合があります。各主成分は元の変数すべての線形結合で表現されるため、これらを元の変数の文脈に戻すことは困難です。観察されたパターンを形成する元の変数を特定することが難しくなるため、主成分から具体的な洞察を得るのに苦労することがあります。この問題に対処するために、Luca Puggini氏とSean McLoone氏の研究に着想を得た「Forward Selection Component Analysis (FSCA)」を実装しました。この手法は、高相関の特徴を扱う際にPCAが直面する課題を回避することを目的としています。


Forward Selection Component Analysis

Forward Selection Component Analysis (FSCA)は、次元削減と特徴量選択を統合した手法であり、元のデータを説明するために最も有用な変数を特定します。FSCAは貪欲法を採用しており、データ内の残差分散を最も効果的に説明する変数を1つずつ選択していきます。以下は、FSCA手法の主要なステップの概要です。

  1. 初期化
    • 選択済み変数の空集合と、候補変数の完全集合からスタートします。
    • データセット全体の分散を計算します。
    • すべての他の変数を最もよく予測する変数を選択し、反復プロセスを開始します。この選択により、説明される分散が最大化されることを確認します。
  2. 反復選択
    • 各ステップで、現在の選択済み変数の集合に追加した場合の、候補変数ごとの説明分散への寄与を評価します。
    • 集合に追加した際に説明分散が最大化される変数を選択します。
  3. 更新
    • 選択した変数を選択済み変数の集合に追加します。
    • 選択した変数を候補変数の集合から削除します。
    • 選択済み変数による寄与を考慮した後の未説明分散(残差分散)を再計算します。
  4. 停止基準
    • 事前に定められた停止条件が満たされるまで、プロセスを繰り返します。停止基準は、選択された変数の指定された数、説明される合計分散の目標割合、または新しい変数を追加することによって説明される増分分散の閾値である可能性があります。


      FSCA概要

生の変数セットが与えられた場合、それらを行列形式で整理します。各列は異なる特徴量を、各行は1つのサンプルを表します。まず、生の値は標準化を通じて変換されます。この時点以降、元の変数への言及は、標準化された変数セットを指します。このセットを行列Xと呼びます。この行列Xは、変数の数を表すv列を持っています。FSCAアルゴリズムは、以下の少なくとも3つの新しい変数セットを生成します。

  • 行列Z:この行列は、行列 X の列のサブセット k(ただし、k < v)から構成されます。これらの列は、Xの再構築にどの程度寄与するかに基づいてランク付けされ、Forward Selection Variables (FSV)と呼ばれます。
  • 行列M:この行列の列は Forward Selection Components (FSC) と呼ばれます。各成分は、Z内の対応する列と、場合によってはそれ以前の列を関数として組み合わせたものです。
  • 行列U:この行列には、FSVをFSCに変換するための係数や重みが含まれています。

アルゴリズムの目標は、X に含まれる固有の変動を最もよく表現する変数の最適なサブセットを取得することです。しかし、これは非常に難しい最適化問題です。FSCAは、定義された最適化基準に基づいて必ずしも最適な変数のサブセットを見つけられるわけではありません。大規模なデータセットでは、すべての可能なサブセットを調べるのは現実的ではないため、FSCAはより実用的なアプローチを提供します。それでも、初期のステップで選択された変数が、後に他の変数が追加されるにつれて冗長になる可能性があるため、最適なサブセットを見つけられない場合があります。この問題に対処するため、この記事の冒頭で参照した研究論文では、FSCA手順に「後方選択 (Backward Refinement)」ステップを導入することを提案しています。


後方選択を取り入れたFSCA

後方選択は、以前に選択された変数を削除または置き換えることで、変数選択の質を向上させる手法です。このプロセスでは、選択された各変数が全体の説明分散にどれだけ寄与しているかを再評価し、それに代わる適切な変数を検討します。この方法は最終的な変数セットの品質向上に寄与しますが、純粋な前方選択における厳密な「重要度の順序」が崩れるという欠点があります。

研究論文では、後方選択を取り入れる2つのアプローチが提案されています。1つ目は、FSCAの全手順を完了した後に後処理として後方選択を適用するものです。2つ目は再帰的後方選択と呼ばれるもので、FSCAアルゴリズムの手順3で新しい変数がZに追加されるたびに後方選択を行います。この記事で後に紹介するコードは、後者の再帰的後方選択を実装しています。

後方選択そのものにも2つのバリエーションがあります。1つ目はシングルパス後方選択(SPBR: Single Pass Backward Refinement)と呼ばれるもので、最も古い変数から最新の変数まで順番に評価し、それぞれの関連性を再検討します。2つ目はマルチパス後方選択(MPBR: Multi-Pass Backward Refinement)であり、変数がシーケンスの後半で調整されるにつれて、それまで関連があると考えられていた変数が無関係になる可能性を考慮します。この方法では、さらに改善が行われなくなるまでプロセスが繰り返されます。この記事で紹介するコードは、SPBRのみを実装しています。

後方選択の図

次のセクションでは、数学的表現とコードを用いて、FSCAアルゴリズムの手順についてさらに詳しく説明します。記事内で言及されているコードスニペットはすべて、この記事の最後に添付されているfsca.mqhから抜粋したものです。


主成分

FSCAアルゴリズムは、データセットX内の固有の変動源を特定するために主成分を利用します。このステップでは、Z行列に含まれる成分変数の最大数を決定する指標も得られ、それがkの値(先に定義済み)となります。研究論文では、アルゴリズムがユーザーによって指定されたkの値を用いるとされていますが、私たちの実装では、kを主成分の数と常に等しく設定しています。主成分は、データセットXの相関行列の固有値を分解することで導出されます。以下のコードスニペットは、compute_factor_structure()関数を使用して因子構造を計算するルーチンを示しています。

//+------------------------------------------------------------------+
//| computes the factor structure of a correlation matrix            |
//+------------------------------------------------------------------+
matrix            compute_factor_structure(matrix &covar,matrix &eigenvectors,vector &eigenvalues,vector &cumeigenvalues)
  {
   if(!covar.EigenSymmetricDC(EIGVALUES_V,eigenvalues,eigenvectors))
     {
      Print(__FUNCTION__, " error ", GetLastError());
      return matrix::Zeros(1,1);
     }
   double sum = 0.0;


   if(!np::reverseVector(eigenvalues) ||  !np::reverseMatrixCols(eigenvectors))
     {
      Print(__FUNCTION__, " reverse operation error ", GetLastError());
      return matrix::Zeros(1,1);
     }

   double cumulate[];
   for(ulong i=0 ; i<eigenvalues.Size() ; i++)
     {
      if(eigenvalues[i]>1.e-8)
        {
         sum += eigenvalues[i] ;
         if(!cumulate.Push(sum))
           {
            Print(__FUNCTION__," error adding element ", GetLastError());
            return matrix::Zeros(1,1);
           }
        }
     }

   if(!cumeigenvalues.Assign(cumulate))
     {
      Print(__FUNCTION__," vector assignment error ", GetLastError());
      return matrix::Zeros(1,1);
     }

   cumeigenvalues/=cumeigenvalues[cumeigenvalues.Size()-1];

   cumeigenvalues*=100.0;

   matrix structmat=eigenvectors;

   for(ulong i = 0; i<structmat.Cols(); i++)
      if(!structmat.Col(eigenvectors.Col(i)*sqrt(eigenvalues[i]>=0.0?eigenvalues[i]:0.0),i))
        {
         Print(__FUNCTION__, "error ", GetLastError());
         return matrix::Zeros(1,1);
        }

   if(!structmat.Clip(-1.0,1.0))
     {
      Print(__FUNCTION__, "error ", GetLastError());
      return matrix::Zeros(1,1);
     }

   return structmat;
  }
//+------------------------------------------------------------------+
//| computes the factor structure of a correlation matrix            |
//+------------------------------------------------------------------+
matrix compute_factor_structure(matrix &covar, matrix &eigenvectors, vector &eigenvalues, vector &cumeigenvalues) {
    if (!covar.EigenSymmetricDC(EIGVALUES_V, eigenvalues, eigenvectors)) {
        Print(__FUNCTION__, " error ", GetLastError());
        return matrix::Zeros(1, 1);
    }

    double sum = 0.0;

    if (!np::reverseVector(eigenvalues) || !np::reverseMatrixCols(eigenvectors)) {
        Print(__FUNCTION__, " reverse operation error ", GetLastError());
        return matrix::Zeros(1, 1);
    }

    double cumulate[];
    for (ulong i = 0; i < eigenvalues.Size(); i++) {
        if (eigenvalues[i] > 1.e-8) {
            sum += eigenvalues[i];
            if (!cumulate.Push(sum)) {
                Print(__FUNCTION__, " error adding element ", GetLastError());
                return matrix::Zeros(1, 1);
            }
        }
    }

    if (!cumeigenvalues.Assign(cumulate)) {
        Print(__FUNCTION__, " vector assignment error ", GetLastError());
        return matrix::Zeros(1, 1);
    }

    cumeigenvalues /= cumeigenvalues[cumeigenvalues.Size() - 1];
    cumeigenvalues *= 100.0;

    matrix structmat = eigenvectors;

    for (ulong i = 0; i < structmat.Cols(); i++) {
        if (!structmat.Col(eigenvectors.Col(i) * sqrt(eigenvalues[i] >= 0.0 ? eigenvalues[i] : 0.0), i)) {
            Print(__FUNCTION__, "error ", GetLastError());
            return matrix::Zeros(1, 1);
        }
    }

    if (!structmat.Clip(-1.0, 1.0)) {
        Print(__FUNCTION__, "error ", GetLastError());
        return matrix::Zeros(1, 1);
    }

    return structmat;
}

この関数は、相関行列covarを入力として受け取り、因子負荷を含む行列を生成します。EigenSymmetricDC関数を使用して、相関行列の固有値分解を実行します。計算結果の固有値はeigenvaluesベクトルに格納され、対応する固有ベクトルはeigenvectors行列に格納されます。次に、固有値と固有ベクトルの順序を逆にして、それらが降順で並べ替えられることを確認します。累積固有値は、それらを順次合計することで計算され、cumeigenvaluesベクトルに格納されます。また、累積固有値はデータ全体の分散に対する割合を表すように正規化されます。

次に、各固有ベクトルを対応する固有値の平方根で乗算することで因子負荷を計算し、その結果をstructmat行列に格納します。さらに、因子負荷が妥当な範囲内(-1から1の間)に収まるようにクリップ処理が施されます。最後に、この関数は計算された因子負荷を含むstructmat行列を返します。

相関行列から得られた因子構造は、変数とその基盤となる潜在因子との関係を表す因子負荷で構成されています。これらの負荷は、潜在因子の意味を解釈し、データの分散を説明する上で各変数の重要性を評価する際に役立ちます。

compute_factor_structure()からの出力は、主成分を計算するためにcompute_principal_components()関数で使用されます。

//+------------------------------------------------------------------+
//|   calculates the principal components                            |
//+------------------------------------------------------------------+
matrix compute_principal_components(void) {
    matrix out(m_data.Rows(), ulong(m_num_comps));
    vector drow, eigcol, nv;
    double sum;

    for (ulong i = 0; i < m_data.Rows(); i++) {
        drow = m_data.Row(i);
        for (ulong j = 0; j < m_num_comps; j++) {
            sum = 0.0;
            for (ulong k = 0; k < m_data.Cols(); k++) {
                sum += drow[k] * m_eigvectors[k][j] / sqrt(m_eigvalues[j]);
            }
            out[i][j] = sum;
        }
    }

    return out;
}

compute_principal_components()関数は入力パラメータを取らず、主成分を含む行列を返します。出力行列out入力データの行数と必要な主成分の数に等しい次元を持つ主成分を格納するために初期化されます。この関数は、入力データ行列の各行を反復処理し、行と共分散行列の対応する固有ベクトルのドット積を、関連する固有値の平方根で割って、各主成分を計算します。結果として得られた主成分は出力行列に格納されます。この関数は、データポイントを主成分サブスペースに投影するための標準的な式を使用して主成分を計算します。

主成分分析の基本的な概念は、多くの変数を含む元のデータ行列Xを、縮小された成分変数のセットを使用して近似することです。この近似は線形変換によって実現されます。

主成分

Xとその近似値の差の二乗の合計を計算することで、この近似値の誤差を評価できます。

近似誤差

あるいは、成分変数によって説明されるXの総分散の割合を計算することによって、近似の品質を評価することもできます。

説明された差異

最適な近似値を得るには、成分変数の計算に使用される列のサブセットをXからZまで戦略的に選択する必要があります。行列Mで表される主成分と最終成分変数は異なることに注意することが重要です。


説明された分散の最大化

FSCAアルゴリズムの重要なステップの1つは、既存のサブセットに追加する最適な変数を選択することです。これをおこなうために、各潜在的変数にスコアを割り当て、最も高いスコアの変数を選択します。研究論文に記載されているように、この基準(スコア)の計算は比較的複雑です。しかし、著者らは、競合する変数に対するこの基準の順位が、それらの説明される分散の順位と一致することを数学的に証明しています。これは、スコアが最も高い変数が説明される分散も最大化することを意味します。

各潜在的変数のスコア計算をより簡単に説明するために、以下の式が使用されます。式の数学的な導出に興味のある読者は、研究論文を参照してください。

中間項の計算式

基準の計算式

Z(i)は、Xの列iが追加された行列Zです。
変数x(j)はXのj列目です。
vはXの変数(列)の数です。
中間項qはk要素の長さを持つ列ベクトルです。

以下は、基準の計算を実装するコードです。

//+------------------------------------------------------------------+
//|  calculates the criterion for assessing a component              |
//+------------------------------------------------------------------+
double compute_criterion(matrix &covar, ulong &keptcols[], ulong nkept, ulong trial_col) {
    ulong i, j, k, irow, new_kept;
    double sum, crit, dtemp;
    new_kept = nkept + 1;
    matrix mt(new_kept, new_kept);

    for (i = 0; i < new_kept; i++) {
        if (i < nkept)
            irow = keptcols[i];
        else
            irow = trial_col;

        for (j = 0; j < nkept; j++)
            mt[i][j] = covar[irow][keptcols[j]];

        mt[i][nkept] = covar[irow][trial_col];
    }

    matrix mtinv = mt.Inv();
    vector vec(new_kept);

    crit = 0.0;
    for (j = 0; j < m_preds; j++) {
        for (i = 0; i < nkept; i++)
            vec[i] = covar[j][keptcols[i]];

        vec[nkept] = covar[j][trial_col];

        sum = 0.0;
        for (i = 0; i < new_kept; i++)
            sum += vec[i] * vec[i] * mtinv[i][i];

        crit += sum;

        sum = 0.0;
        for (i = 1; i < new_kept; i++) {
            dtemp = vec[i];
            for (k = 0; k < i; k++)
                sum += dtemp * vec[k] * mtinv[i][k];
        }

        crit += 2.0 * sum;
    }

    return crit;
}

compute_criterion()関数は、特徴量選択プロセスで成分を評価するための基準を計算します。入力として、相関行列covar、選択された変数の配列keptcols、選択された変数の数nkept、および評価される試行変数のインデックスを受け取ります。

この関数は、選択された変数の既存のセットを試行変数で拡張する新しい行列mtを作成することから始まります。次に、この拡張行列mtの逆行列を計算します。この関数は、元のデータセット内のすべての変数を反復処理し、その変数と選択された変数間の共分散に基づいて、mt行列の逆行列で重み付けされた各変数の基準を計算します。計算された基準は、変数critに蓄積されます。

この関数の目的は、選択した変数のセットに新しい変数を追加した場合の影響を評価することです。基準値が高いほど、新しい変数がモデルのパフォーマンスを向上させる可能性が高く、基準値が低いほど、有益ではない可能性があることを示唆します。この関数は、特徴量選択アルゴリズム内で使用して、特定のモデルにとって最も有益な変数を識別するために利用できます。


再帰的後方選択

後方選択は前方選択のバリエーションであり、以下のbackward_refinement()コードリストで示されます。

//+------------------------------------------------------------------+
//| backward refinement routine                                      |
//+------------------------------------------------------------------+
ulong backward_refinement(matrix &covar, ulong &kept_columns[], ulong nkept, double &best_crit) {
    ulong i, old_col, new_col, best_col, refined;
    double crit;

    best_crit = substvar(covar, kept_columns, nkept, 0, kept_columns[0]);
    refined = 0;

    for (old_col = 0; old_col < nkept; old_col++) {

        if (old_col == nkept - 1 && !refined)
            break;

        best_col = ULONG_MAX;
        for (new_col = 0; new_col < m_preds; new_col++) {

            for (i = 0; i < nkept; i++) {
                if (new_col == kept_columns[i])
                    break;
            }

            if (i < nkept)
                continue;

            crit = substvar(covar, kept_columns, nkept, old_col, new_col);

            if (crit > best_crit) {
                best_crit = crit;
                best_col = new_col;
            }
        }

        if (best_col != ULONG_MAX && best_col >= 0) {
            // Print(__FUNCTION__,"  Replaced predictor at column ",kept_columns[old_col], " with ",best_col," to get criterion = ", best_crit);
            kept_columns[old_col] = best_col;
            refined = 1;
        }
    }
    return refined;
}

このMQL5コードは、特徴量選択のための後方選択アルゴリズムを実装しています。指定された基準に基づいて、選択された各変数を削除した場合の影響を繰り返し評価します。各変数を削除した際の基準を計算することにより、関数はどの変数を削除しても基準に最も大きな変化がないものを特定します。変更が事前定義された閾値を下回る場合、その変数は選択されたセットから削除され、追加の調整が不可能になるまでこのプロセスが繰り返されます。この関数は、改良がおこなわれた場合には1を返し、それ以外の場合には0を返します。

backward_refinement()関数内で呼び出されるsubstvar()ルーチンは、相関行列と選択された変数のセットに基づいて基準を計算する変数置換メカニズムを実装します。このルーチンは、ある変数を別の変数に置き換えた場合の影響を評価するために特徴量選択アルゴリズムで使用されます。

//+------------------------------------------------------------------+
//| variable substitution routine                                    |
//+------------------------------------------------------------------+
double substvar(matrix &covar, ulong &keptcols[], ulong nkept, ulong old_col, ulong new_col) {
    ulong i, j, k, irow, saved_col;
    double sum, crit, dtemp;
    matrix mt(nkept, nkept);

    saved_col = keptcols[old_col];
    keptcols[old_col] = new_col;

    for (i = 0; i < nkept; i++) {
        irow = keptcols[i];
        for (j = 0; j < nkept; j++) {
            mt[i][j] = covar[irow][keptcols[j]];
        }
    }

    matrix mtinv = mt.Inv();
    vector vec(nkept);

    crit = 0.0;
    for (j = 0; j < m_preds; j++) {

        for (i = 0; i < nkept; i++) {
            vec[i] = covar[j][keptcols[i]];
        }

        sum = 0.0;
        for (i = 0; i < nkept; i++) {
            sum += vec[i] * vec[i] * mtinv[i][i];
        }
        crit += sum;

        sum = 0.0;
        for (i = 1; i < nkept; i++) {
            dtemp = vec[i];
            for (k = 0; k < i; k++) {
                sum += dtemp * vec[k] * mtinv[i][k];
            }
        }
        crit += 2.0 * sum;
    }

    keptcols[old_col] = saved_col;

    return crit;
}

この関数は、相関行列covar、選択された変数の配列keptcols、選択された変数の数nkept、および置換される古い変数と新しい変数のインデックスを入力として受け取ります。選択された変数に対応するcovarのサブ行列を格納するための一時行列mtを作成します。次に、関数はInv()関数を使用してmt行列の逆行列を計算します。元のデータセット内のすべての変数に対して反復処理をおこない、各変数と選択された変数間の共分散に基づいて基準を計算し、mt行列の逆行列で重み付けします。計算された基準は、変数critに蓄積されます。基準の計算後、関数はkeptcols配列内の元の変数を復元し、計算された基準を返します。

この関数の目的は、ある変数を別の変数に置き換えた場合、モデル全体に与える影響を評価することです。基準値が高いほど、その置き換えがモデルのパフォーマンスを向上させる可能性が高く、基準値が低い場合は、置き換えが有益でないことを示唆します。この関数は、特徴量選択アルゴリズムに組み込んで、特定のモデルにとって最適な変数の組み合わせを見つけるために使用できます。


成分の直交化

後方選択を組み込まずに、厳密な前方選択を通じて変数を選択すると、最も影響力のあるものから始まり、重要度が徐々に低くなる階層順序が確立されます。この順序は、実際のアプリケーションで非常に価値があることがよくあります。生の値はそのまま使用できますが、元の変数の線形結合として構築された直交成分変数には明確な利点があります。これらの成分は互いに相関していないため、モデルの学習が容易になり、冗長性が最小化されます。さらに、これらの変数間に冗長性がないため、その貢献度の解釈が簡素化されます。

元の順序を保持しながら直交成分変数を得るためには、グラム・シュミット直交化法が適しています。この手法は、初期成分をスケーリングされた最初の選択変数として定義することから始まります。次の成分については、既存の成分に対して投影を減算します。これらの投影を体系的に減算し、単位長さに正規化することで、成分の直交性が保証されます。最後に、標準偏差を単位として再スケーリングして一貫性を保ちます。本質的に、グラム・シュミット直交化法は、選択された変数を元の重要度の順序を保持したまま、直交成分のセットに変換し、モデルの解釈可能性と効率を向上させる可能性があります。

以下はグラム・シュミット変換の実装例です。関数の出力は、各列が直交化されたベクトルを表す新しい行列です。

//+------------------------------------------------------------------+
//|   Gram Schmidt routine                                           |
//+------------------------------------------------------------------+
matrix gram_schmidt(matrix &input_) {
    ulong irow, icol, inner;
    double dtemp, sum;
    ulong nrows = input_.Rows();
    ulong ncols = input_.Cols();
    matrix output = input_;

    sum = 0.0;

    vector colsum = output.Col(0);
    colsum = MathPow(colsum, 2.0);
    sum = colsum.Sum();
    sum = sqrt(sum);

    if (sum == 0.0) {
        Print(__FUNCTION__, " sum == 0.0 ");
        return matrix::Zeros(0, 0);
    }

    if (!output.Col(output.Col(0) / sum, 0)) {
        Print(__FUNCTION__, " failed column insertion ", GetLastError());
        return matrix::Zeros(0, 0);
    }

    for (icol = 1; icol < ncols; icol++) {
        for (inner = 0; inner < icol; inner++) {
            sum = 0.0;
            for (irow = 0; irow < nrows; irow++)
                sum += (output[irow][icol] * output[irow][inner]);

            for (irow = 0; irow < nrows; irow++)
                output[irow][icol] -= (sum * output[irow][inner]);
        }

        sum = 0.0;
        for (irow = 0; irow < nrows; irow++) {
            dtemp = output[irow][icol];
            sum += dtemp * dtemp;
        }

        sum = sqrt(sum);

        if (sum == 0.0) {
            Print(__FUNCTION__, " sum == 0.0 ");
            return matrix::Zeros(0, 0);
        }

        if (!output.Col(output.Col(icol) / sum, icol)) {
            Print(__FUNCTION__, " failed column insertion ", GetLastError());
            return matrix::Zeros(0, 0);
        }
    }

    return output;
}

このアルゴリズムは、以前に直交化された列に対して、入力行列の各列を繰り返し直交化することによって機能します。これは、現在の列を前の列によって張られたサブスペースに投影し、その投影を現在の列から減算することで実現されます。結果として得られたベクトルは、単位の長さになるように正規化されます。コードには、計算にベクトル演算を使用したり、不必要な計算を避けたりするなど、効率を向上させるためのいくつかの最適化が含まれています。さらに、この関数には、長さゼロのベクトルや列挿入の失敗などの潜在的な問題をチェックする誤差処理も組み込まれています。

オプションの後方選択を伴う前方選択を実行するためのすべてのコアルーチンについて説明しました。次のセクションでは、これらのルーチンがFSCAアルゴリズムの完全な実装でどのように利用されるかを示します。


CFscaクラス

CFscaというクラスは、データセットに対してFSCAを実行する機能をカプセル化しています。完全なクラスは、stdmat()という簡単な標準化変換ルーチンとともに、fsca.mqh内で定義されています。この関数は行列を入力として受け取り、標準化された行列を返します。

//+------------------------------------------------------------------+
//| standardize a matrix                                             |
//+------------------------------------------------------------------+
matrix stdmat(matrix &in) {
    vector mean = in.Mean(0);
    vector std = in.Std(0);
    std += 1e-10;
    matrix out = in;

    for (ulong row = 0; row < out.Rows(); row++) {
        if (!out.Row((in.Row(row) - mean) / std, row)) {
            Print(__FUNCTION__, " error ", GetLastError());
            return matrix::Zeros(in.Rows(), in.Cols());
        }
    }

    return out;
}

stdmat()関数は、Mean関数とStd関数を使用して、入力行列の各列の平均と標準偏差を計算します。その後、入力行列と同じ次元を持つ出力行列outを作成します。この関数は入力行列の各行を反復処理し、対応する列の平均を減算し、列の標準偏差で割ることで標準化します。標準化された行は出力行列outに格納され、関数の最後で返されます。この関数は独立して利用できるように、CFscaクラスの外部に配置されています。


CFscaクラスは、FSCAに必要なデータ構造や中間結果を格納するために使用されるprivateメンバーを定義することから始まります。

//+------------------------------------------------------------------+
//| fsca class implementation                                        |
//+------------------------------------------------------------------+
class CFsca
  {
private:
   bool              m_fitted;              //flag showing if principal factors were extracted
   matrix m_corrmat,             //correlation matrix
          m_covar,               //altered correlation matrix
          m_data,                //standardized data is here
          m_eigvectors,          //matrix of eigen vectors of m_corrmat matrix
          m_structmat,           //factor loading matrix of m_corrmat matrix
          m_principal_components,             //principal components
          m_fscv_struct,        //fsca factor structure
          m_fscv_eigvects,      //fsca eigen structure
          m_Fsca,        //ordered fsca variables
          m_coeffs,      //fsca component coefficients
          m_Fscv;        //refined fsca variables
   vector m_eigvalues,           //vector of eigen values of m_corrmat matrix
          m_sqcorr,              //mean squared correlation matrix
          m_fscv_eigvals,        //fsca eigen values
          m_fscv_cumeigvals,     //fsca cumulative variance contribution
          m_cumeigvalues;        //cumulative variance contributions of m_corrmat matrix
   ulong             m_num_comps;           //unique instances of redundent variation in m_data
   ulong             m_preds;               //number of variables (columns) in dataset (m_data)
   ulong  m_keptorderedcolumns[],//indices of columns upon which components are calculated for ordered fsca
          m_keptrefinedcolumns[],//indices of columns upon which components are calculated for backward refined fsca
          m_keptcolumns[],
          m_bestcolumn;          //index of first selected column in analysis
   double            m_best_crit;           //best criterion value

次は、CFscaクラスのprivateメソッドです。このうちのいくつかについては、このテキストの前のセクションで説明しました。他のメソッドについては、クラスのpublicメソッドについて説明するときに簡単に説明します。

publicメソッドはCFscaクラスの最後に定義されます。クラスのインスタンスを初期化した後、最初にfit()メソッドを呼び出す必要があります。このメソッドでは、生のデータセットに対してFSCAを実行します。元の生データを含む行列を入力として受け取り、フィッティングプロセスが成功したかどうかを示すブール値を返します。

//+------------------------------------------------------------------+
//| perform forward selection component analysis on a raw dataset    |
//+------------------------------------------------------------------+
bool fit(matrix &data) {
    m_preds = data.Cols();
    m_fitted = false;
    m_sqcorr = vector::Zeros(m_preds);

    m_data = stdmat(data);
    m_corrmat = m_data.CorrCoef(false);

    m_structmat = compute_factor_structure(m_corrmat, m_eigvectors, m_eigvalues, m_cumeigvalues);

    if (m_structmat.Rows() == 1)
        return false;

    m_num_comps = m_cumeigvalues.Size();

    if (ArrayResize(m_keptorderedcolumns, int(m_num_comps)) < 0 || 
        ArrayResize(m_keptrefinedcolumns, int(m_num_comps)) < 0 ||
        ArrayResize(m_keptcolumns, int(m_num_comps)) < 0 || 
        ArrayInitialize(m_keptcolumns, ULONG_MAX) < 0) {
        Print(__FUNCTION__, " array error ", GetLastError());
        return false;
    }

    m_principal_components = compute_principal_components();

    for (ulong i = 0; i < m_preds; i++)
        m_sqcorr[i] = (compute_criterion(m_corrmat, m_keptcolumns, 0, i) - 1.0) / double(m_preds - 1);

    vector evd_vals = m_eigvalues;
    while (evd_vals[m_preds - 1] <= 0.0) {
        for (ulong j = 1; j < m_preds; j++) {
            for (ulong k = 0; k < j; k++) {
                m_corrmat[j][k] *= 0.99999;
                m_corrmat[k][j] = m_corrmat[j][k];
            }
        }

        matrix empty;
        if (!m_corrmat.EigenSymmetricDC(EIGVALUES_N, evd_vals, empty)) {
            Print(__FUNCTION__, " failed eig decomp ", GetLastError());
            return false;
        }
    }

    m_Fsca = compute_fsca_components(m_data);
    m_Fscv = compute_fscv_components(m_data);

    m_fitted = (m_Fsca.Rows() > 1 && m_Fscv.Rows() > 1);

    return m_fitted;
}

fit()関数は、FSCAプロセスで使用されるさまざまな変数と行列を初期化します。まず、入力データ行列を標準化し、平均がゼロで分散が1であることを確認します。次に、標準化されたデータの相関行列を計算し、それをm_corrmatに保存します。その後、compute_factor_structure関数を使用して相関行列の因子構造を計算します。この因子構造には、相関行列の固有ベクトル(m_eigvectors)、固有値(m_eigvalues)、および累積固有値(m_cumeigvalues)が含まれます。関数は、因子構造行列(m_structmat)に行が1つしかないかどうかをチェックします。もし1つしかない場合、因子構造の評価に誤りが生じたことを示し、関数はfalseを返します。

成分の数(m_num_comps)は、ゼロ以外の固有値の数と同じに設定されます。次に、FSCAプロセスで使用されるさまざまな配列を初期化します。compute_principal_components関数を使用して標準化されたデータの主成分を計算し、各変数と最初の主成分との二乗相関を計算します。さらに、負の固有値が存在するかどうかを確認します。もし見つかれば、相関行列をわずかに調整し、すべてが正であることを確認するまで固有値を再計算します。最後に関数を使用してFSCA成分を計算し、compute_fscv_components関数を使用してFSCV成分を計算します。FSCA成分とFSCV成分の両方が正常に計算された場合、関数はm_fittedフラグをtrueに設定します。

CFscaクラスの定義の最後には、FSCAプロセス中に実行された分析計算のさまざまな側面にアクセスするためのゲッター関数が含まれています。

//+------------------------------------------------------------------+
//| get the principal components                                     |
//+------------------------------------------------------------------+
matrix get_principal_components(void) {
    if (!m_fitted) {
        Print(__FUNCTION__, " either analyze() returned an error or it was not called ");
        return matrix::Zeros(0, 0);
    }

    return m_principal_components;
}

//+------------------------------------------------------------------+
//| get the ordered fsca components                                  |
//+------------------------------------------------------------------+
matrix get_fsca_components(void) {
    if (!m_fitted) {
        Print(__FUNCTION__, " either analyze() returned an error or it was not called ");
        return matrix::Zeros(0, 0);
    }

    return m_Fsca;
}

//+------------------------------------------------------------------+
//| get the backward refined fsca components                         |
//+------------------------------------------------------------------+
matrix get_fscv_components(void) {
    if (!m_fitted) {
        Print(__FUNCTION__, " either analyze() returned an error or it was not called ");
        return matrix::Zeros(0, 0);
    }

    return m_Fscv;
}

//+------------------------------------------------------------------+
//| get indices of variables defining the ordered fsca components    |
//+------------------------------------------------------------------+
bool get_fsca_var_indices(ulong &indices[]) {
    if (!m_fitted) {
        Print(__FUNCTION__, " either analyze() returned an error or it was not called ");
        return false;
    }

    return (ArrayCopy(indices, m_keptorderedcolumns, 0, 0, int(m_num_comps)) > 0);
}

//+---------------------------------------------------------------------------+
//| get indices of variables defining the backward refined fsca components    |
//+---------------------------------------------------------------------------+
bool get_fscv_var_indices(ulong &indices[]) {
    if (!m_fitted) {
        Print(__FUNCTION__, " either analyze() returned an error or it was not called ");
        return false;
    }

    return (ArrayCopy(indices, m_keptrefinedcolumns, 0, 0, int(m_num_comps)) > 0);
}

//+-------------------------------------------------------------------+
//| get cumulative variance contribution based on principal components|
//+-------------------------------------------------------------------+
vector get_principal_components_cumulative_variance_contribution(void) {
    if (!m_fitted) {
        Print(__FUNCTION__, " either analyze() returned an error or it was not called ");
        return vector::Zeros(0);
    }

    return m_cumeigvalues;
}

//+-------------------------------------------------------------------+
//| get cumulative variance contribution based on fscv components     |
//+-------------------------------------------------------------------+
vector get_fscv_cumulative_variance_contribution(void) {
    if (!m_fitted) {
        Print(__FUNCTION__, " either analyze() returned an error or it was not called ");
        return vector::Zeros(0);
    }

    return m_fscv_cumeigvals;
}

//+-------------------------------------------------------------------+
//| get eigen structure of principal components                       |
//+-------------------------------------------------------------------+
bool get_principal_components_eigstructure(matrix &vectors, vector &values) {
    if (!m_fitted) {
        Print(__FUNCTION__, " either analyze() returned an error or it was not called ");
        return false;
    }

    vectors = m_eigvectors;
    values = m_eigvalues;

    return true;
}

//+-------------------------------------------------------------------+
//| get eigen structure of backward refined FSCs                      |
//+-------------------------------------------------------------------+
bool get_fscv_eigstructure(matrix &vectors, vector &values) {
    if (!m_fitted) {
        Print(__FUNCTION__, " either analyze() returned an error or it was not called ");
        return false;
    }

    vectors = m_fscv_eigvects;
    values = m_fscv_eigvals;

    return true;
}

//+-------------------------------------------------------------------+
//| get principal components factor structure                         |
//+-------------------------------------------------------------------+
matrix get_principal_components_factorstructure(void) {
    if (!m_fitted) {
        Print(__FUNCTION__, " either analyze() returned an error or it was not called ");
        return matrix::Zeros(0, 0);
    }

    return m_structmat;
}

//+-------------------------------------------------------------------+
//| get the factor structure of FSC with backward refinement          |
//+-------------------------------------------------------------------+
matrix get_fscv_factorstructure(void) {
    if (!m_fitted) {
        Print(__FUNCTION__, " either analyze() returned an error or it was not called ");
        return matrix::Zeros(0, 0);
    }

    return m_fscv_struct;
}

//+------------------------------------------------------------------+
//| get mean squared correlations                                    |
//+------------------------------------------------------------------+
vector get_avg_correlations(void) {
    if (!m_fitted) {
        Print(__FUNCTION__, " either analyze() returned an error or it was not called ");
        return vector::Zeros(0);
    }

    return m_sqcorr;
}

//+-------------------------------------------------------------------+
//| get forward selection component coefficients matrix               |
//+-------------------------------------------------------------------+
matrix get_fsca_component_coeffs(void) {
    if (!m_fitted) {
        Print(__FUNCTION__, " either analyze() returned an error or it was not called ");
        return matrix::Zeros(0, 0);
    }

    return m_coeffs;
}

これらの関数により、ユーザーは標準化されたデータ、相関行列、因子構造、主成分、構成変数などの重要な結果を取得でき、これにより結果のさらなる分析と解釈が容易になります。この説明の最後に、CFscaクラスの使用方法を実演します。


以下のコードは、ランダムに生成されたデータセットに対してFSCAを実行するMQL5スクリプト「FSCA_Demo.mq5」を定義しています。このスクリプトには、FSCA分析に使用されるCFscaクラスの定義が含まれているfsca.mqhヘッダファイルが組み込まれています。

//+------------------------------------------------------------------+
//|                                                    FSCA_Demo.mq5 |
//|                                  Copyright 2024, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"
#include<fsca.mqh>
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   MathSrand(120);
//---
   matrix mat(100,9);
//---
   mat.Random(0.0,1.0);
//---
   vector var1 = mat.Col(0) + mat.Col(1);
// ---
   vector var2 = mat.Col(2) + mat.Col(3);
//---
   vector var3 = var1 + var2;
//---
   if(!mat.Col(var1,6) || !mat.Col(var2,7) || !mat.Col(var3,8))
     {
      Print("failed column assignment ", GetLastError());
      return;
     }
//---
   CFsca fsca;
//---
   if(!fsca.fit(mat))
      return;
//---
   ulong index[];
   Print("Principal components cumulative variance conributions \n", fsca.get_principal_components_cumulative_variance_contribution());
   Print(" Principal components factor structure \n", fsca.get_principal_components_factorstructure());
   Print("Mean squared correlation of each variable with all others \n", fsca.get_avg_correlations());
//---
   if(fsca.get_fsca_var_indices(index))
     {
      Print(" Ordered FSCA components based on variables located in column indices ");
      ArrayPrint(index);
     }
//---
   Print(" Ordered FSCA component coefficients matrix \n", fsca.get_fsca_component_coeffs());
//---
   if(fsca.get_fscv_var_indices(index))
     {
      Print(" Backward refined FSCA components based on variables located in column indices ");
      ArrayPrint(index);
     }
//---
   matrix vects;
   vector vals;
//---
   if(fsca.get_fscv_eigstructure(vects,vals))
     Print("Backward refined fsca component eigenvalues \n", vals);
//---
   Print(" Backward refined cumulative variance contributions \n", fsca.get_fscv_cumulative_variance_contribution());
//---
   Print(" Backward refined fsca components factor structure \n", fsca.get_fscv_factorstructure());
  }
//+------------------------------------------------------------------+

まず、ランダムシードを設定し、ランダム値の行列を作成します。次に、行列内の既存の列を合計することで、3つの新しいベクトルが作成されます。その後、スクリプトは行列データをFSCAモデルに適合させ、累積分散寄与、因子構造、平均二乗相関などのさまざまなFSCA結果を取得します。また、標準FSCAと後方改良FSCAの両方を実行し、順序付けられた変数インデックスと成分係数を出力します。さらに、後方改良されたFSCA成分の因子構造も表示されます。このスクリプトは、100個のサンプルと9つの特徴量を持つランダム変数のデータセットを生成します。データセットの最後の3つの変数は他の変数に依存するように設定されていますが、残りは独立しています。 

スクリプトを実行して主成分の特性を分析すると、9つの変数のうち、固有の変動源は6つしかないことがわかります。

DG      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)   Principal components cumulative variance conributions 
RM      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)   [31.72121326219056,54.98374706330443,70.21399790786099,82.34742379766755,91.9067775629936,100]
CM      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)    Principal components factor structure 
MH      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)   [[-0.5430877600903072,0.4698851388299595,-0.02139789374204959,0.5468988095320395,-0.4254498037566715,-0.06082703269184352,-1.3842452210817e-09,-7.527559895073524e-10,0]
RH      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)    [-0.5283294988376427,0.4246506210338227,-0.1190026606589024,-0.6285471675075863,0.3351428244532062,0.1377893424956133,-1.351333204556555e-09,-7.34858353171856e-10,0]
ES      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)    [-0.5563230307728618,-0.3632156082945803,0.4770295070287525,0.3051596297191441,0.4575827252246154,-0.1688715686919785,-1.694159101189325e-09,2.164855665400724e-10,0]
NF      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)    [-0.2379617600470182,-0.6943076552356867,-0.4580766878219635,-0.2737307249578351,-0.4112051990027778,0.08636320534609224,-1.769139142521297e-09,2.260667780777343e-10,0]
DO      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)    [0.02487447101754412,-0.08203927651647476,-0.6079889924620585,0.4701685445643955,0.3604839483405348,0.5215295442601863,1.313244252124911e-25,1.228203109452781e-25,0]
IP      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)    [-0.07016546285360215,-0.110242984252018,0.7306990214221818,-0.07491798042552207,-0.2276538908363994,0.6257501374625694,4.158606798395552e-25,-7.369218656716687e-26,0]
NE      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)    [-0.7598477338270035,0.6346843827822741,-0.09872272409405579,-0.04786755450396145,-0.0705236166963274,0.05287812507625003,-1.359967783374346e-10,1.333715775589249e-09,0]
NO      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)    [-0.5934182368659159,-0.8024046895986707,-0.000973814713973191,0.01424096330384607,0.02077689502375221,-0.05801790712583575,2.667167815186452e-10,-1.355042254629964e-11,0]
RM      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)    [-0.9897757278036692,-0.1138316306178367,-0.07343616940955985,-0.02494592427830717,-0.03690113231990194,-0.0030829919659495,2.802923111601039e-09,-3.865027968054199e-10,0]]

変数のうち3つは他の変数の組み合わせであるため、これは予想どおりです。各変数の累積分散寄与を見てみると、最初の主成分が全体の分散の約3分の1を占めていることがわかります。因子構造は、第1主成分と列0から3および6から8の変数との間に中程度から強い逆相関があることを示しており、列4と5の変数は逆の傾向を示しています。第2主成分は、変数0と1と、変数2と3の違いを表しています。最初の2つの主成分を合わせると、全体の変動の55パーセント以上が説明されます。

QK      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)   Mean squared correlation of each variable with all others 
GK      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)   [0.09874555673359317,0.09196664871445229,0.09678803260182336,0.08640965168371836,0.009232616218980055,0.01341075732654295,0.1892345119240549,0.1695472310064176,0.2291509382521983]

すべての変数を組み合わせたコレクションと各変数の平均二乗相関のベクトルに進むと、このベクトルは元のデータセットにおける変数の順番で相関をリストします。最後の3つの変数は平均相関が最も高く、列4と5の変数は最も低い平均相関を持っています。

LR      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)    Ordered FSCA components based on variables located in column indices 
QQ      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)   8 6 2 4 1 5

次に、get_fscv_var_indices()を呼び出して得られる前方選択された値を確認します。これは、データセット内の変動の大部分を最もよく捉える変数のインデックスを、データ全体の変動に最も寄与する変数の順に降順で表示します。ここでは、最後の変数が最も大きな変動を捉えており、最初に表示されています。

QJ      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)    Ordered FSCA component coefficients matrix 
DM      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)   [[0.9999999989356357,-0.9551778313323678,-1.196676438579672,-0.163265209103464,-0.1301792726137802,0.0741114239785734]
IR      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)    [7.62883988565579e-10,1.382882745177175,0.7080052470472653,0.1327136589445282,-0.8962870520067646,-0.01038862969019799]
LF      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)    [6.044914586250671e-10,-1.162965671680505e-09,1.327736785211269,0.1291890234653878,0.1244453203448803,-0.2315140872599129]
EM      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)    [5.84342504938995e-11,-9.115276242144255e-11,-1.685031073006549e-10,1.005785752630206,0.08917398176616295,0.2288955899392838]
JM      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)    [6.626278020206711e-11,8.05911615654048e-10,2.135397240976555e-10,-3.939133914887538e-11,1.404086244047662,0.03569800251260542]
KK      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)    [-2.859616016204214e-11,3.48387846349496e-11,2.600743786995707e-10,-1.479500966183878e-10,-3.333024481411151e-11,1.048952273510343]]

次に、6つの成分を計算するために必要な係数の表を調べます。変数は、先ほど確認した配列のインデックスに従って、重要度の順に並べられています。ここでは、最後の変数が最も重要であり、対応する係数は1に非常に近いことがわかります。この行列を下に進むと、係数が非常に小さくなり、実質的にゼロに近づくことがわかります。

CM      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)    Backward refined FSCA components based on variables located in column indices 
ND      0       07:16:46.014    FSCA_Demo (BTCUSD,D1)   3 0 2 4 1 5

最後に、前方選択と後方選択を組み合わせて選ばれた変数のインデックスを調べます。このFSCAのバリエーションでは、選択された変数の順序に重要性はありません。ただし、選ばれた変数のセットは、独立したランダム変数のみを保持し、依存関係を示す変数を除外するため、厳密な順序付けによる方法よりも意味があります。これは、標準的な前方選択と後方精緻化前方選択の結果を比較することで明確に示されます。


結論

結論として、MQL5におけるFSCAの実装を紹介し、次元削減および特徴量選択のツールとしての有効性を示しました。また、このツールは探索的データ分析にも使用できます。アルゴリズムの副産物の1つはデータセットの因子構造であり、これは作用する効果を理解するのに役立ちます。この記事で紹介したコードは以下に添付されています。
ファイル名
 詳細
MQL5/include/np.mqh
汎用ベクトルおよび行列ユーティリティ関数のヘッダファイル
MQL5/include/fsca.mqh
FSCAを実装するCFscaクラスの定義を含むヘッダファイル
MQL5/scripts/FSCA_Demo.mq5
CFscaクラスの使用方法を示すMetaTrader 5スクリプト

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

添付されたファイル |
np.mqh (74.16 KB)
fsca.mqh (26.89 KB)
FSCA_Demo.mq5 (2.46 KB)
Mql5.zip (16.32 KB)
最後のコメント | ディスカッションに移動 (1)
Aleksey Vyazmikin
Aleksey Vyazmikin | 11 7月 2025 において 12:07

もちろん、このテーマは永遠であり、常に関連性がある。

合成データではなく、実際のデータで、その有効性を比較するために、異なる方法を記事にするのは良いことだろう。

特徴数を5000に、行数を10000に増やしてみたが、結果を3日間待ったが結果は出なかった。では、特徴量の数をグループ分けして、例えば100例ずつにして、各グループから勝者を集めて最終的な選択をしたら、品質が著しく低下するのではないだろうか?

知っておくべきMQL5ウィザードのテクニック(第44回):ATR (Average True Range)テクニカル指標 知っておくべきMQL5ウィザードのテクニック(第44回):ATR (Average True Range)テクニカル指標
ATRオシレーターは、特に外国為替市場において、ボラティリティの代理として機能する非常に人気のあるインジケーターです。これは、特にボリュームデータが不足している市場で広く活用されています。以前のインジケーターと同様に、パターンに基づいて分析をおこない、MQL5ウィザードライブラリのクラスとアセンブリを活用して、戦略およびテストレポートを共有します。
MacOSでのMetaTrader 5 MacOSでのMetaTrader 5
macOS上のMetaTrader 5取引プラットフォーム用の特別なインストーラーを提供します。これは、アプリケーションをネイティブにインストールできる本格的なウィザードです。インストーラーは、システムの識別、最新のWineバージョンのダウンロードとインストール、設定の適用、その後のMetaTraderのインストールまで、すべての手順を自動で実行します。インストールが完了すると、すぐにプラットフォームを使用できます。
MQL5経済指標カレンダーを使った取引(第1回):MQL5経済指標カレンダーの機能をマスターする MQL5経済指標カレンダーを使った取引(第1回):MQL5経済指標カレンダーの機能をマスターする
この記事では、まず、MQL5経済指標カレンダーの基本機能を理解し、それを取引に活用する方法を探ります。次に、MQL5で経済指標カレンダーの主要機能を実装し、取引の判断に役立つニュースを取得する方法を説明します。最後に、この情報を活用して取引戦略を効果的に強化する方法を紹介します。
ニュース取引が簡単に(第5回):取引の実施(II) ニュース取引が簡単に(第5回):取引の実施(II)
この記事では、取引管理クラスを拡張し、ニュースイベントを取引するための買い逆指値注文(買いストップ注文)と売り逆指値注文(売りストップ注文)を追加します。また、オーバーナイト取引を防ぐために、これらの注文に有効期限の制約を実装します。さらに、逆指値注文(ストップ注文)を使用する際に発生しうるスリッページ、特にニュースイベント中に発生する可能性のあるスリッページを防止または最小限に抑えるために、スリッページ関数をエキスパートアドバイザー(EA)に組み込みます。