【MQL5】Split関数について

MQL5リファレンス
スポンサーリンク
スポンサーリンク

Split関数の働き・役割

Split関数は、大きな行列を複数の小さな部分行列に分割するために使用されます。分割方法は、以下の2つの条件で制御できます。

  1. 部分行列の数を指定
    元の行列を、指定した数の「同じサイズの部分行列」に分割します。ただし、この場合、行列の行数または列数が指定した部分数で割り切れる必要があります。
  2. 部分行列のサイズを指定
    各部分行列の行数または列数を具体的に指定する配列を使って分割します。この方法では、指定したサイズがすべて使い切られるまで分割が進み、残りのデータがある場合はそれが最後の部分行列にまとめられます。

この関数は、行や列に沿ったデータを柔軟に操作する際に役立ちます。たとえば、一定期間ごとのデータを個別に分析したり、特定のサイズに分割してデータを扱いやすくしたりすることが可能です。

Split関数を使用することで、複雑な行列データを扱いやすい小さな単位に分割し、効率的に計算や分析を進めることができます。

Split関数の引数について

Split関数には2つの形式があります。それぞれの形式について、引数の詳細を説明します。


形式1: 部分行列の数を指定する場合

bool matrix::Split(
const ulong parts,     // 部分行列の数
  const int    axis,      // 軸
  matrix&     splitted[]  // 結果の部分行列の配列
  );

この形式では、分割後の部分行列の数を指定して分割を行います。

  1. parts
    分割後に作成する部分行列の数を指定します。たとえば、2を指定すると、元の行列は2つの部分行列に分割されます。ただし、元の行列の行数または列数がpartsで割り切れる必要があります。割り切れない場合、分割は失敗します。
  2. axis
    分割する方向を指定します。
    • 0: 水平方向(行ごと)に分割します。
    • 1: 垂直方向(列ごと)に分割します。
  3. splitted
    分割後の部分行列を格納する配列を指定します。この配列には、分割された部分行列が格納されます。

形式2: 部分行列のサイズを指定する場合

void matrix::Split(
const ulong& parts[],   // 部分行列のサイズ
  const int    axis,      // 軸
  matrix&     splitted[]  // 結果の部分行列の配列
  );

この形式では、部分行列の行数や列数を指定する配列を使って分割を行います。

  1. parts
    各部分行列のサイズを指定する配列です。この配列要素を順に使用して分割が進みます。たとえば、{2, 3}を指定すると、最初の部分行列が2行、次の部分行列が3行というように分割されます。
    • 配列のすべての要素を使い切った後に元の行列がまだ分割されていない部分が残っている場合、その部分が最後の部分行列に含まれます。
    • 指定したサイズが元の行列の行数や列数を超えている場合、分割は失敗します。
  2. axis
    分割する方向を指定します。
    • 0: 水平方向(行ごと)に分割します。
    • 1: 垂直方向(列ごと)に分割します。
  3. splitted
    分割後の部分行列を格納する配列を指定します。この配列には、分割された部分行列が格納されます。

補足

  • 形式1と形式2の違い
    形式1では、同じサイズの部分行列を作成する場合に使用します。一方、形式2は、異なるサイズの部分行列を作成する場合に適しています。
  • エラー条件
    分割条件が元の行列のサイズに適合しない場合(たとえば、割り切れない、または指定サイズが大きすぎる場合)、Split関数は失敗し、エラーが返されます。分割が成功したかどうかは戻り値で確認できます。

Split関数の戻り値について

Split関数戻り値は、関数の実行結果が成功したかどうかを示します。戻り値の詳細は以下の通りです。


1. 戻り値がtrueの場合

Split関数が正常に実行され、指定した条件に基づいて行列が分割されたことを意味します。この場合、分割された部分行列はsplitted配列に格納されます。

例: 成功時の動作

  • 分割条件(部分数またはサイズ配列)が元の行列のサイズに適合している。
  • 分割処理が完全に実行され、すべての部分行列がsplittedに格納されている。

2. 戻り値がfalseの場合

Split関数が失敗したことを意味します。この場合、以下の理由で分割に失敗している可能性があります。

失敗の原因例

  • 部分数が割り切れない
    形式1(部分行列の数を指定する場合)で、元の行列の行数または列数が指定した部分数で割り切れない。
  • サイズ配列が不適切
    形式2(部分行列のサイズを指定する場合)で、サイズ配列要素が元の行列の行数や列数を超えている、または全てのサイズを使用しても元の行列が完全に分割されない。
  • その他のエラー
    関数引数が無効である、または内部エラーが発生した場合。

エラー確認

分割が失敗した場合、GetLastError関数を使用してエラーコードを確認することができます。エラーコードを調べることで、具体的な失敗の原因を特定できます。


注意点

Split関数戻り値がfalseの場合でも、splitted配列には何も格納されません。そのため、分割結果を利用する前に必ず戻り値をチェックし、分割が成功していることを確認する必要があります。

Split関数を使ったサンプルコード

以下はSplit関数を使用して、行列を部分行列に分割するサンプルコードです。

// スクリプトのエントリーポイント
void OnStart()
{
   // 元の行列を定義します
   // 行列は5行6列で、値は1から30まで順に割り当てられています
   matrix matrix_a = {
       { 1,  2,  3,  4,  5,  6 },
       { 7,  8,  9, 10, 11, 12 },
       {13, 14, 15, 16, 17, 18 },
       {19, 20, 21, 22, 23, 24 },
       {25, 26, 27, 28, 29, 30 }
   };

   // 分割後の部分行列を格納する配列
   matrix splitted[];

   // --------------------------
   // 例1: 行列を水平方向に2つの部分行列に分割する
   // --------------------------

   // 水平方向(axis=0)に2つの部分行列に分割
   bool result = matrix_a.Split(2, 0, splitted);

   // 分割結果をコンソールに出力
   Print("水平分割結果: ", result, " エラーコード: ", GetLastError());
   
   // 分割された部分行列を確認
   for (uint i = 0; i < splitted.Size(); i++)
   {
       // 各部分行列を順に表示
       Print("部分行列 ", i, ":\n", splitted[i]);
   }

   // --------------------------
   // 例2: 行列を垂直方向に2つの部分行列に分割する
   // --------------------------

   // 垂直方向(axis=1)に2つの部分行列に分割
   result = matrix_a.Split(2, 1, splitted);

   // 分割結果をコンソールに出力
   Print("垂直分割結果: ", result, " エラーコード: ", GetLastError());

   // 分割された部分行列を確認
   for (uint i = 0; i < splitted.Size(); i++)
   {
       // 各部分行列を順に表示
       Print("部分行列 ", i, ":\n", splitted[i]);
   }

   // --------------------------
   // 例3: 部分行列のサイズを指定して分割する
   // --------------------------

   // 各部分行列のサイズを定義(行数を指定)
   ulong parts[] = {2, 2};

   // 水平方向(axis=0)に、指定したサイズで分割
   result = matrix_a.Split(parts, 0, splitted);

   // 分割結果をコンソールに出力
   Print("サイズ指定分割結果: ", result, " エラーコード: ", GetLastError());

   // 分割された部分行列を確認
   for (uint i = 0; i < splitted.Size(); i++)
   {
       // 各部分行列を順に表示
       Print("部分行列 ", i, ":\n", splitted[i]);
   }
}

サンプルコードの解説


1. スクリプトのエントリーポイント: OnStart関数

OnStart関数は、スクリプトが実行されるときに最初に呼び出される関数です。この関数内にSplit関数を使った処理を記述しています。voidという戻り値の型は、この関数が値を返さないことを意味します。


2. 行列の定義: matrix_a

以下のコードで行列matrix_aを定義しています。

matrix matrix_a = {
    { 1,  2,  3,  4,  5,  6 },
    { 7,  8,  9, 10, 11, 12 },
    {13, 14, 15, 16, 17, 18 },
    {19, 20, 21, 22, 23, 24 },
    {25, 26, 27, 28, 29, 30 }
};
  • matrix
    MQL5で提供される行列を扱うデータ型です。このコードでは、5行6列の行列を作成しています。
  • データの記述方法
    {}を使って行や列を指定します。行はカンマで区切られた配列として書き、それをさらに外側の{}で囲んで行列を表現します。

3. 分割後の部分行列の格納用: splitted配列

matrix splitted[];
  • matrix splitted[]
    これは分割後の部分行列を格納するための配列です。[]を付けることで「サイズが決まっていない配列」として宣言しています。分割後のデータはこの配列に保存されます。

4. 例1: 水平方向に分割する

以下のコードで、水平方向(行ごと)に分割を行っています。

bool result = matrix_a.Split(2, 0, splitted);

この例では分割が失敗します

元の行列matrix_aの行数は5行で、部分行列の数として指定した2で割り切れません。Split関数はこの条件では分割できないため、戻り値はfalseになり、分割は失敗します。


5. エキスパートログへの出力: Print関数

分割結果を確認するために、以下のようにPrint関数で情報をエキスパートログに出力しています。

Print("水平分割結果: ", result, " エラーコード: ", GetLastError());
  • Print関数
    文字列や数値をエキスパートログに出力するための関数です。複数の値をカンマで区切って出力できます。
  • GetLastError関数
    最後に発生したエラーコードを取得します。エラーがない場合は0が返ります。

6. 分割された部分行列をループで確認

以下のコードで、分割された部分行列を順に出力しています。

for (uint i = 0; i < splitted.Size(); i++)
{
    Print("部分行列 ", i, ":\n", splitted[i]);
}
  • forループ
    配列要素を順に操作するために使用します。
    • 初期化: uint i = 0(カウンタを0に初期化)
    • 継続条件: i < splitted.Size()配列splittedのサイズより小さい間ループを続ける)
    • カウンタの増加: i++(ループごとにカウンタを1増やす)
  • splitted.Size()
    配列splittedのサイズ(部分行列の数)を取得するメソッドです。
  • 出力される内容
    各部分行列インデックス(番号)と内容をエキスパートログに表示しています。

7. 例2: 垂直方向に分割する

以下のコードで、垂直方向(列ごと)に分割を行っています。

result = matrix_a.Split(2, 1, splitted);
  • 第二引数1
    分割軸を1に指定することで、列ごとに分割されます。その他の部分は例1と同様です。

8. 例3: サイズ指定で分割する

以下のコードで、部分行列のサイズを指定して分割を行っています。

ulong parts[] = {2, 2};
result = matrix_a.Split(parts, 0, splitted);
  • サイズ指定の配列parts
    • 配列partsには、各部分行列の行数を指定します。この場合、最初の部分行列が2行、次の部分行列も2行で分割されます。
    • 行列内の全てのサイズが使用された後に残る行(または列)は最後の部分行列にまとめられます。

9. エラー処理

分割に失敗した場合、falseが返ります。その際にGetLastError関数を使ってエラーコードを確認しています。エラーが発生した場合、入力パラメータや元の行列の構造を見直す必要があります。


総括

  • 例1では、元の行列が部分行列の数で割り切れないため分割が失敗します。
  • 例2では、列数が部分行列の数で割り切れるため分割が成功します。
  • 例3では、サイズを具体的に指定して分割するため成功します。

Split関数を使ってEAを作る際のアイディア


1. 期間ごとのトレンド分析

過去の価格データを行列として扱い、Split関数で一定期間ごとに分割することで、トレンドの変化を個別に分析することができます。これにより、短期的な変動や長期的なトレンドを効率的に評価できます。

応用例

  • 週ごとの移動平均の比較
    過去データを1週間単位に分割し、各週ごとに移動平均を計算して比較します。
  • 期間別のボラティリティ分析
    分割したデータごとにボラティリティを計算し、トレンドの安定性を評価します。

2. 多通貨ペアの関連性解析

複数の通貨ペアのデータを行列として取得し、Split関数で通貨ペアごとに分割することで、通貨間の相関や関連性を解析できます。これにより、通貨ペアを選択したペアトレード戦略が構築できます。

応用例

  • 通貨ペア間の相関分析
    各通貨ペアの価格変動を分割し、相関係数を計算して関連性を評価します。
  • 相関に基づくペアトレード戦略
    相関が高い通貨ペアを利用して、リスクを抑えた取引戦略を構築します。

3. 機械学習用データセットの作成

機械学習に必要なトレーニングデータやテストデータをSplit関数で作成できます。特に、過去の価格データを分割して特徴量ラベルを生成する際に便利です。

応用例

  • 時系列データの分割
    一定期間ごとに分割して時系列データを整理します。これを用いて、価格予測モデルのトレーニングデータを作成します。
  • トレーニングとテストデータの分離
    過去データを分割してトレーニング用とテスト用に振り分け、モデルの性能を評価します。

4. チャートパターンの検出

行列データとして保存された価格情報を分割し、それぞれの部分行列内でチャートパターン(例: ダブルボトムやヘッドアンドショルダー)を検出します。特定のパターンが出現したときに売買シグナルを生成することで、戦略的な取引を実現できます。

応用例

  • パターン検出スキャン
    分割した部分行列ごとにパターン検出を実行し、該当する部分にシグナルを設定します。
  • 条件に基づくエントリーとエグジット
    特定のパターンが出現した場合にのみエントリーし、リスクを抑える取引を行います。

5. リソース効率を考慮したバックテスト

大規模なヒストリカルデータを分割して処理することで、メモリ使用量を抑えながら効率的なババックテストが可能になります。データを小さな部分ごとに処理することで、EAのパフォーマンスも向上します。

応用例

  • 期間ごとの戦略テスト
    過去データを月ごとに分割し、それぞれの月で戦略を検証します。
  • 部分処理による速度向上
    分割したデータを一つずつ処理することで、大規模データを扱う際の負荷を軽減します。

6. ポートフォリオ管理と分析

複数の資産や通貨ペアのデータを行列として扱い、Split関数で分割することで、ポートフォリオの構成を分析し、リスクやリターンを評価します。

応用例

  • 資産クラスごとのリターン評価
    各資産クラスを分割してリターンを計算し、全体のパフォーマンスを評価します。
  • リバランス戦略の支援
    分割されたデータを基に、リスクを最小化するための最適な資産配分を提案します。

タイトルとURLをコピーしました