【MQL5】Dot関数について

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

Dot関数の働き・役割

Dot関数は、2つのベクトル内積を計算するために使用されます。この関数は、ベクトルの対応する成分同士を掛け合わせた値をすべて合計し、1つの数値として出力します。この計算結果はスカラーと呼ばれ、ベクトル演算の基礎的な処理に広く応用されています。

内積とは

内積は、2つのベクトルの間にどの程度の「関係」があるかを数値で表すものです。数学的には、ベクトル成分ごとの積の総和として計算されます。この演算により、ベクトル同士が平行であるかどうかを判断したり、角度を求めたりすることができます。

例えば、ベクトルAが[1, 2, 3]、ベクトルBが[4, 5, 6]である場合、内積は次のように計算されます。

  1. 成分を掛け合わせます。
    • 1 × 4 = 4
    • 2 × 5 = 10
    • 3 × 6 = 18
  2. それらを合計します。
    • 4 + 10 + 18 = 32

この結果、内積は32になります。この計算により、ベクトル同士の方向性や関連性を調べることができます。

Dot関数の引数について

Dot関数には以下の引数を指定します。

第1引数: b

bは、計算対象となる2番目のベクトルを指定します。このベクトルは、内積を計算する際のもう一方のベクトルとして使用されます。

たとえば、ベクトルAに対してベクトルBの内積を計算したい場合、ベクトルAのインスタンスに対してDot関数を呼び出し、引数ベクトルBを指定します。

引数の注意点

Dot関数を使用する場合、以下の点に注意する必要があります。

  1. 内積を計算する2つのベクトルは、同じ次元を持っていなければなりません。同じ長さのベクトルでない場合、エラーや不正確な計算結果が生じます。
  2. Dot関数を呼び出す元のベクトル(呼び出し元)と引数として渡されるベクトルは、いずれもMQL5vectorクラスインスタンスである必要があります。

これにより、Dot関数は2つのベクトル間の内積を効率的に計算します。

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

//+------------------------------------------------------------------+
//| スクリプトの開始時に呼び出されるイベントハンドラー                                             |
//+------------------------------------------------------------------+
void OnStart()
{
    // 行列aとbの行数および列数を定義
    ulong rows = 2; // 行列aの行数(例として2行)
    ulong cols = 2; // 行列bの列数(例として2列)

    // matrix型を使用して行列を初期化(カスタムクラスとして仮定)
    matrix a, b; // 行列aとbを宣言
    a.Resize(rows, cols); // 行列aのサイズを設定
    b.Resize(rows, cols); // 行列bのサイズを設定

    // 行列aとbのサンプルデータを設定
    a[0][0] = 1; a[0][1] = 2;
    a[1][0] = 3; a[1][1] = 4;
    b[0][0] = 5; b[0][1] = 6;
    b[1][0] = 7; b[1][1] = 8;

    // 計算結果を格納するための動的配列resultを初期化
    double result[];
    ArrayResize(result, rows * cols); // 1次元配列で結果を格納

    // 行列積を計算(行列aの行ベクトルと行列bの列ベクトルの内積を計算)
    for(ulong i = 0; i < rows; i++) // 行列aの行をループ
    {
        vector v1 = a.Row(i); // 行列aのi番目の行を取得
        for(ulong j = 0; j < cols; j++) // 行列bの列をループ
        {
            vector v2 = b.Row(j); // 行列bのj番目の列を取得
            result[i * cols + j] = v1.Dot(v2); // Dot関数で内積を計算
        }
    }

    // 計算結果をログに出力
    for(ulong i = 0; i < rows; i++)
    {
        string row_result = "";
        for(ulong j = 0; j < cols; j++)
        {
            row_result += DoubleToString(result[i * cols + j], 2) + " "; // 各要素を文字列に変換
        }
        Print("行 " + IntegerToString(i) + ": " + row_result); // 行ごとに結果を出力
    }
}

サンプルコード解説1

void OnStart()
{
    // 行列aとbの行数および列数を定義
    ulong rows = 2; // 行列aの行数(例として2行)
    ulong cols = 2; // 行列bの列数(例として2列)

    // 行列aとbを初期化(例としてシンプルなデータを使用)
    matrix a, b; // matrix型の変数を宣言(カスタムクラスとして仮定)
    a.Resize(rows, cols); // 行列aのサイズを設定
    b.Resize(rows, cols); // 行列bのサイズを設定

この部分は、行列a と b のサイズを定義し、初期化する部分を示しています。以下に、各行について詳しく解説します。


イベントハンドラーの開始

OnStart関数 は、スクリプトが開始されるときに自動的に呼び出される特別な関数です。この関数の中に、スクリプトが実行するすべての処理を記述します。


行列の行数と列数を定義

ここでは、行列a と b の行数と列数を定義しています。

変数 rows は、行列a の行数を表します。この場合、行列a は2行で構成されています。

変数cols は、行列bの列数を表します。この場合、行列b は2列で構成されています。

これらの変数ulong 型で宣言されています。ulong型は正の整数を扱うためのデータ型であり、非常に大きな値を扱うことができます。


行列 a と b を宣言

この行では、matrix型の変数a と b を宣言しています。

matrix型は、行列を扱うために特別に設計されたデータ型です。このデータ型を使用することで、行列のサイズを設定したり、データを格納したりする操作が簡単に行えます。

変数a は行列aを、変数b は行列b を表します。


行列のサイズを設定

ここでは、Resize関数を使用して、行列a と b のサイズを設定しています。

Resize関数 は、行列の行数と列数を指定して、そのサイズを設定するためのものです。

第一引数rows には、行数(2行)を指定します。

第二引数cols には、列数(2列)を指定します。

この処理により、行列a と b は2行2列の行列として初期化されます。ただし、まだ中身のデータは設定されていません。


サンプルコード解説2

この部分では、行列aとbにサンプルデータを設定し、計算結果を格納するための行列resultを初期化しています。それぞれの処理について解説します。


行列aとbにデータを設定

a[0][0] = 1; a[0][1] = 2;
a[1][0] = 3; a[1][1] = 4;
b[0][0] = 5; b[0][1] = 6;
b[1][0] = 7; b[1][1] = 8;

このコードは、行列aとbの各要素に具体的な数値を代入しています。

  • a[0][0]は行列aの1行目1列目の要素を示し、値として1を代入しています。
  • a[0][1]は行列aの1行目2列目の要素で、値として2を代入しています。
  • 他の要素についても、同じ形式で数値を代入しています。

これにより、行列aとbは以下のようになります。

行列a:

1  2
3  4

行列b

5  6
7  8

計算結果を格納する行列の初期化

double result[2][2];

ここでは、計算結果を格納するための2次元配列resultを初期化しています。

  • resultは2行2列の配列であり、行列aとbの行列積の結果を格納します。
  • 初期化時点では配列内に具体的な値は設定されていませんが、後続の計算で値が代入されます。

サンプルコード解説3

この部分では、行列aとbの行列積を計算し、その結果を行列resultに格納しています。コードは、行列aの各行と行列bの各列を内積計算する形に改善されています。それぞれの処理について詳しく解説します。


行列aの行をループ処理

for(ulong i = 0; i < rows; i++) // 行列aの行をループ
{
    vector v1 = a.Row(i); // 行列aのi番目の行を取得

外側のループでは、行列aの各行を処理します。

  • 変数iは、現在処理している行列aの行番号を表します。
  • Row関数を使って、行列aのi番目の行をベクトルv1に取得しています。
    • iが0の場合、v1は行列aの1行目(例:[1, 2])。
    • iが1の場合、v1は行列aの2行目(例:[3, 4])。

行列bの列をループ処理

for(ulong j = 0; j < cols; j++) // 行列bの列をループ
{
    vector v2 = b.Col(j); // 行列bのj番目の列を取得

内側のループでは、行列bの各列を処理します。

  • 変数jは、現在処理している行列bの列番号を表します。
  • Col関数を使って、行列bのj番目の列をベクトルv2に取得しています。
    • jが0の場合、v2は行列bの1列目(例:[5, 7])。
    • jが1の場合、v2は行列bの2列目(例:[6, 8])。

ベクトル内積の計算と結果の格納

result[i][j] = v1.Dot(v2); // ベクトル内積を計算し、結果を格納

ここでは、ベクトルv1とv2の内積を計算し、その結果を配列resultのi行j列に格納しています。

具体的な計算例:

  1. iが0(1行目)、jが0(1列目)の場合:
    • v1 = [1, 2]
    • v2 = [5, 7]
    • 内積= (1 × 5) + (2 × 7) = 5 + 14 = 19
    • 結果はresult[0][0]に格納されます。
  2. iが0(1行目)、jが1(2列目)の場合:
    • v1 = [1, 2]
    • v2 = [6, 8]
    • 内積= (1 × 6) + (2 × 8) = 6 + 16 = 22
    • 結果はresult[0][1]に格納されます。
  3. iが1(2行目)、jが0(1列目)の場合:
    • v1 = [3, 4]
    • v2 = [5, 7]
    • 内積= (3 × 5) + (4 × 7) = 15 + 28 = 43
    • 結果はresult[1][0]に格納されます。
  4. iが1(2行目)、jが1(2列目)の場合:
    • v1 = [3, 4]
    • v2 = [6, 8]
    • 内積= (3 × 6) + (4 × 8) = 18 + 32 = 50
    • 結果はresult[1][1]に格納されます。

計算結果

このループによって計算された行列resultは以下のようになります:

19  22
43  50

サンプルコード解説4

この部分では、計算された行列resultをエキスパートログに出力する処理を行っています。行列の各行の内容を文字列として整形し、行ごとにログに表示する仕組みです。


行ごとのループ処理

for(ulong i = 0; i < rows; i++)

外側のループでは、行列resultの各行を処理します。

  • 変数iは現在処理している行の番号を表します。
  • 例えば、iが0の場合、行列resultの1行目を処理します。

行の文字列整形

string row_result = "";

ここでは、1行分のデータを保持する文字列変数row_resultを初期化しています。この変数に、現在の行に含まれる各要素文字列として追加していきます。


列ごとのループ処理

for(ulong j = 0; j < cols; j++)

内側のループでは、現在処理中の行に含まれる各要素を処理します。

  • 変数jは現在処理している列の番号を表します。
  • 例えば、jが0の場合、現在の行の1列目を処理します。

要素を文字列に変換して追加

row_result += DoubleToString(result[i][j], 2) + " ";

ここでは、行列resultのi行j列の要素文字列に変換し、それをrow_resultに追加しています。


ログへの出力

Print("行 " + IntegerToString(i) + ": " + row_result);

現在の行の内容をエキスパートログに出力しています。

  • “行 ” + IntegerToString(i)で、現在の行番号を文字列として表現します。
  • row_resultには、現在の行に含まれる各要素文字列として格納されています。
  • Print関数を使用して、ログに行番号と行の内容を出力します。

出力の例

行列resultが次のような内容だった場合:

19  22
43  50

ログには以下のように出力されます:

行 0: 19.00 22.00 
行 1: 43.00 50.00 

補足:Dot関数を使わない場合の、ベクトル内積計算の例

// ベクトルの内積を計算する関数
// 入力:2つのベクトル vector_a と vector_b
// 出力:2つのベクトルの内積(スカラー値として返されます)
double VectorDot(const vector& vector_a, const vector& vector_b)
{
    // 内積の結果を格納するための変数を初期化
    // 初期値は0です
    double dot = 0;

    // 2つのベクトルのサイズが等しい場合にのみ計算を実行します
    // ベクトルのサイズが異なる場合、内積は計算できません
    if(vector_a.Size() == vector_b.Size())
    {
        // ベクトルの要素数分ループを実行
        // ループ変数 i は現在の要素番号を示します
        for(ulong i = 0; i < vector_a.Size(); i++)
        {
            // ベクトルの各要素同士を掛け合わせ、その積を内積に加算します
            // vector_a[i] はベクトル vector_a の i 番目の要素を示します
            // vector_b[i] はベクトル vector_b の i 番目の要素を示します
            dot += vector_a[i] * vector_b[i];
        }
    }

    // 計算結果を返します
    // ベクトルの内積がスカラー値として返されます
    return dot;
}

VectorDot関数の解説

この関数は、2つのベクトル内積を計算して返す役割を持っています。ベクトル内積は、対応する要素同士を掛け算し、その結果をすべて足し合わせた値(スカラー値)です。この計算は、数学やプログラミングで頻繁に使用される重要な演算の一つです。

以下に、コードを構成する各部分について詳しく解説します。


関数の宣言

この関数は、VectorDotという名前で定義されています。関数は、ベクトル型の変数を2つ入力として受け取り、その内積を計算して返します。

関数が始まる部分には、関数の本体を囲む波括弧が含まれます。この波括弧の中に、関数が実行する具体的な処理を記述します。


内積結果を格納する変数の初期化

関数の最初の部分で、内積を計算して格納するための変数dotを定義しています。この変数double型で宣言されており、計算結果を保持する役割を持ちます。

変数dotの初期値は0に設定されています。この初期値を設定することで、後の計算で値を安全に累積していくことができます。


ベクトルのサイズ確認

関数の中でif文を使用して、ベクトルのサイズが一致しているかを確認しています。

  • Size関数を使用して、それぞれのベクトル(vector_aとvector_b)の要素数を取得します。この関数は、ベクトルが持つ要素の数を返します。
  • 条件式vector_a.Size() == vector_b.Size()は、2つのベクトルのサイズが等しいかどうかを比較しています。この条件が真(True)の場合にのみ、内積の計算を行います。

ベクトルのサイズが異なる場合、対応する要素同士を掛け算することができないため、内積を計算しません。


内積の計算ループ

内積の計算は、for文を使用してベクトルの各要素を順に処理する形で行われます。

具体的な例を挙げると、vector_aが[1, 2]、vector_bが[3, 4]の場合、次のように計算が進みます。

  1. iが0のとき:
    • vector_a[0] × vector_b[0] = 1 × 3 = 3
    • dotに3を加算(dotは3になる)
  2. iが1のとき:
    • vector_a[1] × vector_b[1] = 2 × 4 = 8
    • dotに8を加算(dotは11になる)

最終的に変数dotには内積の計算結果が格納されます。


戻り値を返す

return文を使用して、計算した内積の結果を関数の呼び出し元に返します。

  • return(dot)とすることで、変数dotの値が関数戻り値として返されます。
  • 呼び出し元のコードでは、この戻り値変数に格納したり、次の処理に利用したりします。

この関数の利用例

たとえば、次のようなコードでVectorDot関数を使用することができます。

  1. vector型の変数vec1とvec2を定義し、それぞれにデータを設定します。
  2. VectorDot関数を呼び出し、引数としてvec1とvec2を渡します。
  3. 戻り値変数resultに格納し、内積の計算結果として利用します。

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