はじめに
行列やベクトルは数学やプログラミングにおいて重要な概念であり、特にデータ処理や数値計算の分野で頻繁に使われます。本記事では、行列とベクトルに対して適用できる数学演算について、MQL5のスクリプト内でどのように操作するかを解説します。
行列とベクトルの基礎
行列とは、数値が縦横に並んだ二次元のデータ構造です。一方、ベクトルは一列に並んだ一次元のデータ構造です。これらは、数値計算を効率的に行うための基本単位として広く利用されています。
- 行列:
[[1, 4],
[9, 16]]
ベクトル:
[1, 2, 3, 4, 5]
行列とベクトルに対して行える数学演算には、足し算、引き算、掛け算、割り算、さらには平方根や対数といった数学関数の適用があります
※平方根とは、ある数値を2乗した結果が元の数値となるような数のことです。例えば、4の平方根は2であり、16の平方根は4です。
※対数とは、ある数値を特定の基数(例えば10やe)で何回掛けるとその数になるかを示す値です。例えば、10を基数とする対数(常用対数)で、100の対数は2です。これは、10を2回掛けると100になるからです。
行列とベクトルに対する数学演算の基本操作
足し算と引き算
行列やベクトルの足し算や引き算は、対応する要素ごとに計算を行います。たとえば、以下のような行列があったとします。
行列A
[[1, 2],
[3, 4]]
行列B
[[5, 6],
[7, 8]]
これらを足し算すると、次のように計算します。
- 1行1列目の要素: 行列Aの1行1列目「1」と行列Bの1行1列目「5」を足します。結果は「1 + 5 = 6」。
- 1行2列目の要素: 行列Aの1行2列目「2」と行列Bの1行2列目「6」を足します。結果は「2 + 6 = 8」。
- 2行1列目の要素: 行列Aの2行1列目「3」と行列Bの2行1列目「7」を足します。結果は「3 + 7 = 10」。
- 2行2列目の要素: 行列Aの2行2列目「4」と行列Bの2行2列目「8」を足します。結果は「4 + 8 = 12」。
A + B:
[[6, 8],
[10, 12]]
引き算の場合も同じように、対応する位置の要素同士を引き算するだけです。
たとえば、同じ行列Aと行列Bを使って引き算をすると次のようになります。
結果は次の行列になります。
A – B:
[[-4, -4],
[-4, -4]]
このように、行列やベクトルの足し算・引き算は、対応する要素同士を計算する単純な操作です。
掛け算と割り算
行列やベクトルの掛け算と割り算では、各要素ごとに指定した値(スカラー値)で計算を行います。
スカラー値とは?
スカラー値とは、単一の数値のことを指します。行列やベクトル全体ではなく、単独の値(例えば、2や3.5など)を指します。このスカラー値を使って行列やベクトルの全要素に同じ操作を適用します。
掛け算の例
行列A:
[[1, 2],
[3, 4]]
この行列にスカラー値「2」を掛けると、次のように計算します。
結果の行列:
[[2, 4],
[6, 8]]
割り算の例
同じ行列Aをスカラー値「2」で割ると、次のように計算します。
結果の行列:
[[0.5, 1],
[1.5, 2]]
スカラー値を用いることで、行列やベクトル全体に一括で計算を適用できる点が特徴です。
行列同士の掛け算
行列同士の掛け算は、各要素を単純に掛け合わせるわけではありません。特定のルールに基づいて計算を行い、新しい行列を作ります。
行列同士の掛け算のルール
行列同士の掛け算では、左側の行列の行と右側の行列の列を掛け合わせて新しい行列の要素を作ります。このとき、左側の行列の列数と右側の行列の行数が一致している必要があります。
新しい行列のサイズは、左側の行列の行数×右側の行列の列数になります。
具体例で理解する
元の行列
次のような2つの行列を考えます。
行列A(2行3列):
A = [[1, 2, 3],
[4, 5, 6]]
行列B(3行2列):
B = [[7, 8],
[9, 10],
[11, 12]]
行列Aの列数(3)と行列Bの行数(3)が一致しているため、掛け算が可能です。計算結果の行列Cのサイズは、行列Aの行数(2行)×行列Bの列数(2列)となります。つまり、行列Cは2行2列の行列になります。
計算手順
- 行列Cの1行1列目の要素を計算する
行列Aの1行目[1, 2, 3]
と行列Bの1列目[7, 9, 11]
を掛け合わせ、それらを足します。
(1×7) + (2×9) + (3×11) = 7 + 18 + 33 = 58 行列Cの1行1列目の要素は58
です。 - 行列Cの1行2列目の要素を計算する
行列Aの1行目[1, 2, 3]
と行列Bの2列目[8, 10, 12]
を掛け合わせ、それらを足します。
(1×8) + (2×10) + (3×12) = 8 + 20 + 36 = 64
行列Cの1行2列目の要素は64です。 - 行列Cの2行1列目の要素を計算する
行列Aの2行目[4, 5, 6]
と行列Bの1列目[7, 9, 11]
を掛け合わせ、それらを足します。
(4×7) + (5×9) + (6×11) = 28 + 45 + 66 = 139
行列Cの2行1列目の要素は139
です。 - 行列Cの2行2列目の要素を計算する
行列Aの2行目[4, 5, 6]
と行列Bの2列目[8, 10, 12]
を掛け合わせ、それらを足します。
(4×8) + (5×10) + (6×12) = 32 + 50 + 72 = 154
行列Cの2行2列目の要素は154
です。
計算結果
以上の計算から、行列Cは次のようになります。
C = [[58, 64],
[139, 154]]
注意点
- 掛け算ができる条件
左側の行列の列数と右側の行列の行数が一致していない場合、行列同士の掛け算は定義されません。 - 計算順序に注意
行列同士の掛け算は順序に依存します。A×BとB×Aは、計算結果が異なる場合があります。
数学関数の適用
MQL5では、さまざまな数学関数を行列やベクトルに適用できます。たとえば、平方根を求めるMathSqrt関数を使うと、次のように計算されます。
元の行列:
[[1, 4],
[9, 16]]
平方根を求めた結果:
[[1, 2],
[3, 4]]
MQL5での行列とベクトル操作の実例
以下は、MQL5で行列とベクトルの数学演算を実際に実装したコード例です。この例では、乱数を使ったベクトルを作成し、その平均値や標準偏差を計算します。
// スクリプトプログラムの開始関数
void OnStart()
{
// ベクトルをランダムな値で初期化
// vector型の変数rを作成し、10個の要素を持つように初期化
// 各要素にはArrayRandom関数で生成された0~1の範囲の乱数が格納される
vector r(10, ArrayRandom);
// 初期化されたベクトルの内容を出力
Print("ベクトル r: ", r);
// 平均値を計算
// ベクトルrの全要素の平均値を計算し、変数avrに格納
double avr = r.Mean();
// 平均値を出力
Print("平均値 avr: ", avr);
// 平均からの偏差を計算
// ベクトルrの各要素から平均値avrを引いた新しいベクトルを作成し、dに格納
vector d = r - avr;
// 偏差のベクトルを出力
Print("平均からの偏差 d: ", d);
// 偏差の二乗を計算
// ベクトルdの各要素を2乗した新しいベクトルを作成し、s2に格納
vector s2 = MathPow(d, 2);
// 偏差の二乗和を計算
// ベクトルs2の全要素を合計し、変数sumに格納
double sum = s2.Sum();
// 標準偏差を計算
// 偏差の二乗和をベクトルrの要素数で割った値の平方根を計算し、stdに格納
double std = MathSqrt(sum / r.Size());
// 標準偏差を出力
Print("標準偏差 std: ", std);
}
// ベクトルにランダムな値を書き込む関数
void ArrayRandom(vector& v)
{
// ベクトルvのサイズ分繰り返し処理を行う
for (ulong i = 0; i < v.Size(); i++)
{
// MathRand()関数で0~32767の乱数を生成
// 生成された値を32767で割ることで、0~1の範囲に正規化
// 計算された値をベクトルvの各要素に格納
v[i] = double(MathRand()) / 32767.;
}
}
コード解説
以下のコードは、MQL5を使ってベクトル(一次元配列)のランダムな値を生成し、その値をもとに統計量(平均値、偏差、標準偏差)を計算するプログラムです。一つひとつのステップを詳しく解説していきます。
OnStart関数の定義
OnStart関数は、スクリプトの実行が始まったときに1回だけ自動的に呼び出される関数です。
OnStart関数内の処理は波括弧の中に記述します。
ベクトルrの初期化
ベクトル型は、MQL5で提供されるデータ型で、一次元の数値配列(ベクトル)を表します。これは、データを一括で扱う際に便利です。
ベクトルrは、10個の要素を持つ一次元配列として定義されています。このベクトルに後で乱数を代入します。
括弧内の最初の引数10は、このベクトルが持つ要素を指定しています。2番目の引数であるArrayRandom関数は、ベクトルの初期化に使用する関数を指定しています。この関数は後で詳しく説明します。
ベクトルrの内容を出力
Print関数は、エキスパートログにテキストや変数の値を表示するための関数です。
内容としては、”ベクトルr:”という文字列と、ベクトルrの内容がエキスパートログに出力されます。
平均値の計算と出力
double型は、小数点を含む数値を格納するデータ型です。avrは、計算された平均値を格納するために使用される変数です。
r.Meanメソッドは、ベクトルrのすべての要素の平均値を計算するメソッドです。例えば、rの要素が[0.2, 0.4, 0.6]だった場合、r.Meanの戻り値は(0.2 + 0.4 + 0.6) / 3 = 0.4となります。
Print関数を使って、平均値avrをエキスパートログに出力します。
偏差の計算と出力
偏差とは、各データが平均値からどれだけ離れているかを示す値です。たとえば、データ0.6の平均値が0.4の場合、その偏差は0.6 – 0.4 = 0.2です。
ベクトルrの各要素から平均値avrを引き算した結果を新しいベクトルdに格納します。これにより、各要素が平均値からどれだけ離れているかが分かります。
偏差ベクトルdの内容がエキスパートログに表示されます。
偏差の二乗を計算
MathPow関数は、指定した数値やベクトルの要素を指定した指数で累乗します。この場合、ベクトルdの各要素を2乗しています。
偏差ベクトルdの各要素を2乗した新しいベクトルをs2に格納します。たとえば、dが[0.2, -0.3, 0.1]であれば、s2の内容は[0.04, 0.09, 0.01]となります。
偏差の二乗和を計算
s2.Sumメソッドは、ベクトルs2の全要素を合計します。たとえば、s2が[0.04, 0.09, 0.01]の場合、s2.Sumの戻り値は0.04 + 0.09 + 0.01 = 0.14となります。
変数sumには、偏差の二乗和が格納されます。
標準偏差を計算
標準偏差とは、データのばらつきを示す値です。偏差の二乗和をデータ数で割り、それを平方根で計算します。
MathSqrt関数は平方根を計算する関数です。
標準偏差stdは、sumをベクトルrの要素数で割った値の平方根を計算して得られます。r.Sizeはベクトルrの要素数(この場合は10)を返します。
計算された標準偏差がエキスパートログに表示されます。
ArrayRandom関数
ArrayRandom関数は、ベクトルvの各要素を0から1の範囲のランダムな値で初期化します。
引数としてベクトルvを参照渡ししています。参照渡しにより、関数内で変更した値が呼び出し元にも反映されます。
forループでベクトルを初期化
for文は、繰り返し処理を行う制御構文です。ループカウンタ変数iを0に初期化し、ループがベクトルのサイズ分だけ繰り返される条件が設定されています。
MathRand関数で0~32767の範囲でランダムな整数を生成します。この乱数を32767で割り、小数点以下を持つ0~1の範囲の値を生成します。
まとめ
このプログラムは、ベクトルの乱数生成から始まり、平均値、偏差、標準偏差を順次計算していきます。MQL5の基本的な構文(forループ、関数定義、参照渡し)や統計関数の使い方を学ぶための良い例です。各要素が一連の計算にどのように使われるかを理解することで、データ処理の基礎が身につきます。
行列に適用できる数学関数の種類
MQL5では、以下の数学関数を行列やベクトルに適用することができます。これらの関数は、行列やベクトルの各要素ごとに計算を行います。
- MathAbs(絶対値)
- MathArccos(アークコサイン)
- MathArcsin(アークサイン)
- MathArctan(アークタンジェント)
- MathCeil(切り上げ)
- MathFloor(切り捨て)
- MathLog(自然対数)
- MathLog10(常用対数)
- MathMod(剰余)
- MathPow(累乗)
- MathExpm1(eのべき乗から1を引いた値)
- MathLog1p(1プラスxの自然対数)
- MathSinh(双曲線正弦)
- MathCosh(双曲線余弦)
- MathTanh関数(双曲線正接)
これらの各関数について詳しい解説やサンプルコードは、対応する各関数の記事をご覧ください。それぞれの使い方を理解することで、行列やベクトルを用いた数値計算の幅が広がります。