# MQL5 中的矩阵和向量

MetaTrader 5交易 | 3 三月 2022, 09:06
2 168 1

### “向量（vector）”类型

NumPy 类比

void vector.Init( ulong size);   创建指定长度的向量，其中的值未定义
static vector vector::Ones(ulong size);
ones

static vector vector::Zeros(ulong size);
zeros

static vector vector::Full(ulong size,double value);
full

operator =

void vector.Resize(const vector v);
往结尾添加新值来调整向量大小

```void OnStart()
{
//--- vector initialization examples
vector v;
v.Init(7);
Print("v = ", v);

vector v1=vector::Ones(5);
Print("v1 = ", v1);

vector v2=vector::Zeros(3);
Print("v2 = ", v2);

vector v3=vector::Full(6, 2.5);
Print("v3 = ", v3);

vector v4{1, 2, 3};
Print("v4 = ", v4);
v4.Resize(5);
Print("after Resize(5) v4 = ", v4);

vector v5=v4;
Print("v5 = ", v5);
v4.Fill(7);
Print("v4 = ", v4, "   v5 =",v5);

}

/*
Execution result

v = [4,5,6,8,10,12,12]
v1 = [1,1,1,1,1]
v2 = [0,0,0]
v3 = [2.5,2.5,2.5,2.5,2.5,2.5]
v4 = [1,2,3]
after Resize(5) v4 = [1,2,3,7,7]
v5 = [1,2,3,7,7]
v4 = [7,7,7,7,7]   v5 =[1,2,3,7,7]

*/
```

Init() 方法不仅可用于为向量分配内存，还可依据函数值来初始化向量元素。 在这种情况下，向量大小作为第一个参数传递给 Init，函数名作为第二个参数。 如果函数包含参数，则应在函数名后立即指定这些参数，并用逗号分隔。

```void OnStart()
{
//---
vector v;
v.Init(7,Arange,10,0,0.5); // 3 parameters are passed with Arange call
Print("v = ", v);
Print("v.size = ",v.Size());
}
//+------------------------------------------------------------------+
//|  Values are generated within the half-open interval [start, stop)|
//+------------------------------------------------------------------+
void Arange(vector& v, double stop, double start = 0, double step = 1) // the function has 4 parameters
{
if(start >= stop)
{
PrintFormat("%s wrong parameters! start=%G  stop=%G", __FILE__,start, stop);
return;
}
//---
int size = (int)((stop - start) / step);
v.Resize(size);
double value = start;
for(ulong i = 0; i < v.Size(); i++)
{
v[i] = value;
value += step;
}
}

/*
Execution result

v = [0,0.5,1,1.5,2,2.5,3,3.5,4,4.5,5,5.5,6,6.5,7,7.5,8,8.5,9,9.5]
v.size = 20

*/
```

Arange 函数有两个可选参数，“start” 和 “stop”。 因此，Init(7,Arange,10) 的另一个可能调用和相关结果如下：

```//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
//---
vector v;
v.Init(7,Arange,10);
Print("v = ", v);
Print("v.size = ",v.Size());
}
...

/*

v = [0,1,2,3,4,5,6,7,8,9]
v.size = 10

*/
```

### 向量运算

```//+------------------------------------------------------------------+
//|                                              vector2_article.mq5 |
//|                                  Copyright 2021, MetaQuotes Ltd. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property version   "1.00"
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
//---
vector v= {1, 2, 3, 4, 5};
Print("Examples without saving vector changes");
Print("v = ", v);
Print("v+5 = ", v+5);
Print("v-Pi= ", v-M_PI);
Print("v*2.0= ", v*2);
Print("v/3.0= ", v/3.0);

Print("Save all vector changes");
Print("v = ", v);
Print("v+5 = ", v=v+5);
Print("v-Pi= ", v=v-M_PI);
Print("v*2.0= ", v= v*2);
Print("v/3.0= ", v= v/3.0);
}
/*
Execution result

Examples without saving vector changes
v = [1,2,3,4,5]
v+5 = [6,7,8,9,10]
v-Pi= [-2.141592653589793,-1.141592653589793,-0.1415926535897931,0.8584073464102069,1.858407346410207]
v*2.0= [2,4,6,8,10]
v/3.0= [0.3333333333333333,0.6666666666666666,1,1.333333333333333,1.666666666666667]
Save all vector changes
v = [1,2,3,4,5]
v+5 = [6,7,8,9,10]
v-Pi= [2.858407346410207,3.858407346410207,4.858407346410207,5.858407346410207,6.858407346410207]
v*2.0= [5.716814692820414,7.716814692820414,9.716814692820414,11.71681469282041,13.71681469282041]
v/3.0= [1.905604897606805,2.572271564273471,3.238938230940138,3.905604897606805,4.572271564273471]

*/
//+------------------------------------------------------------------+

```

```void OnStart()
{
//---
vector a = {1, 2, 3};
vector b = {2, 4, 6};
Print("a + b = ", a + b);
Print("a - b = ", a - b);
Print("a * b = ", a * b);
Print("b / a = ", b / a);
}

/*
Execution result

a + b = [3,6,9]
a - b = [-1,-2,-3]
a * b = [2,8,18]
b / a = [2,2,2]

*/
```

```void OnStart()
{
//---
vector a={1, 2, 3};
vector b={4, 5, 6};
Print("a = ", a);
Print("b = ", b);
Print("1) a.Dot(b) = ", a.Dot(b));
Print("2) a.MatMul(b) = ", a.MatMul(b));
Print("3) a.Kron(b) = ", a.Kron(b));
Print("4) a.Outer(b) = \n", a.Outer(b));
}
/*
Execution result

a = [1,2,3]
b = [4,5,6]
1) a.Dot(b) = 32.0
2) a.MatMul(b) = 32.0
3) a.Kron(b) = [[4,5,6,8,10,12,12,15,18]]
4) a.Outer(b) =
[[4,5,6]
[8,10,12]
[12,15,18]]

*/
```

### 向量范数

```void OnStart()
{
//---
struct str_vector_norm
{
ENUM_VECTOR_NORM  norm;
int               value;
};
str_vector_norm vector_norm[]=
{
{VECTOR_NORM_INF,       0},
{VECTOR_NORM_MINUS_INF, 0},
{VECTOR_NORM_P,         0},
{VECTOR_NORM_P,         1},
{VECTOR_NORM_P,         2},
{VECTOR_NORM_P,         3},
{VECTOR_NORM_P,         4},
{VECTOR_NORM_P,         5},
{VECTOR_NORM_P,         6},
{VECTOR_NORM_P,         7},
{VECTOR_NORM_P,        -1},
{VECTOR_NORM_P,        -2},
{VECTOR_NORM_P,        -3},
{VECTOR_NORM_P,        -4},
{VECTOR_NORM_P,        -5},
{VECTOR_NORM_P,        -6},
{VECTOR_NORM_P,        -7}
};
vector v{1, 2, 3, 4, 5, 6, 7};
double norm;
Print("v = ", v);
//---
for(int i=0; i<ArraySize(vector_norm); i++)
{
switch(vector_norm[i].norm)
{
case VECTOR_NORM_INF :
norm=v.Norm(VECTOR_NORM_INF);
Print("v.Norm(VECTOR_NORM_INF) = ", norm);
break;
case VECTOR_NORM_MINUS_INF :
norm=v.Norm(VECTOR_NORM_MINUS_INF);
Print("v.Norm(VECTOR_NORM_MINUS_INF) = ", norm);
break;
case VECTOR_NORM_P :
norm=v.Norm(VECTOR_NORM_P, vector_norm[i].value);
PrintFormat("v.Norm(VECTOR_NORM_P,%d) = %G", vector_norm[i].value, norm);
}
}
}
/*

v = [1,2,3,4,5,6,7]
v.Norm(VECTOR_NORM_INF) = 7.0
v.Norm(VECTOR_NORM_MINUS_INF) = 1.0
v.Norm(VECTOR_NORM_P,0) = 7
v.Norm(VECTOR_NORM_P,1) = 28
v.Norm(VECTOR_NORM_P,2) = 11.8322
v.Norm(VECTOR_NORM_P,3) = 9.22087
v.Norm(VECTOR_NORM_P,4) = 8.2693
v.Norm(VECTOR_NORM_P,5) = 7.80735
v.Norm(VECTOR_NORM_P,6) = 7.5473
v.Norm(VECTOR_NORM_P,7) = 7.38704
v.Norm(VECTOR_NORM_P,-1) = 0.385675
v.Norm(VECTOR_NORM_P,-2) = 0.813305
v.Norm(VECTOR_NORM_P,-3) = 0.942818
v.Norm(VECTOR_NORM_P,-4) = 0.980594
v.Norm(VECTOR_NORM_P,-5) = 0.992789
v.Norm(VECTOR_NORM_P,-6) = 0.99714
v.Norm(VECTOR_NORM_P,-7) = 0.998813

*/
```

```void OnStart()
{
//---
vector a{1,2,3};
vector b{2,3,4};
double distance=(b-a).Norm(VECTOR_NORM_P,2);
Print("a = ",a);
Print("b = ",b);
Print("|a-b| = ",distance);
}
/*
Execution result

a = [1,2,3]
b = [2,3,4]
|a-b| = 1.7320508075688772

*/
```

### “矩阵（matrix）” 类型

NumPy 中的类比法

void static matrix.Eye(const int rows, const int cols, const int ndiag=0)

eye

void matrix.Identity()

identity

void static matrix.Ones(const int rows, const int cols)

ones

void static matrix.Zeros(const int rows, const int cols)

zeros

void static matrix.Tri(const int rows, const int cols, const int ndiag=0)
tri  构造一个矩阵，在指定对角线上填 1，在其下和其它地方填 0
void matrix.Diag(const vector v, const int ndiag=0)  diag  提取对角线或构造对角线矩阵

void matrix.Full(const int rows, const int cols, const scalar value)

full

void matrix.Fill(const scalar value)     用指定的值填充矩阵

```void OnStart()
{
//---
matrix m{{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
Print("m = \n", m);
matrix ones=matrix::Ones(4, 4);
Print("ones = \n", ones);
matrix zeros=matrix::Zeros(4, 4);
Print("zeros = \n", zeros);
matrix eye=matrix::Eye(4, 4);
Print("eye = \n", eye);

matrix identity(4, 5);
Print("matrix_identity\n", identity);
identity.Identity();
Print("matrix_identity\n", identity);

matrix tri=matrix::Tri(3, 4);
Print("tri = \n", tri);
Print("tri.Transpose() = \n", tri.Transpose()); // transpose the matrix

matrix diag(5, 5);
Print("diag = \n", diag);
vector d{1, 2, 3, 4, 5};
diag.Diag(d);
Print("diag = \n", diag); // insert values from the vector into the matrix diagonal

matrix fill(5, 5);
fill.Fill(10);
Print("fill = \n", fill);

matrix full =matrix::Full(5, 5, 100);
Print("full = \n", full);

matrix init(5, 7);
Print("init = \n", init);
m.Init(4, 6);
Print("init = \n", init);

matrix resize=matrix::Full(2, 2, 5);
resize.Resize(5,5);
Print("resize = \n", resize);
}
/*
Execution result

m =
[[1,2,3]
[4,5,6]
[7,8,9]]
ones =
[[1,1,1,1]
[1,1,1,1]
[1,1,1,1]
[1,1,1,1]]
zeros =
[[0,0,0,0]
[0,0,0,0]
[0,0,0,0]
[0,0,0,0]]
eye =
[[1,0,0,0]
[0,1,0,0]
[0,0,1,0]
[0,0,0,1]]
matrix_identity
[[1,0,0,0,0]
[0,1,0,0,0]
[0,0,1,0,0]
[0,0,0,1,0]]
matrix_identity
[[1,0,0,0,0]
[0,1,0,0,0]
[0,0,1,0,0]
[0,0,0,1,0]]
tri =
[[1,0,0,0]
[1,1,0,0]
[1,1,1,0]]
tri.Transpose() =
[[1,1,1]
[0,1,1]
[0,0,1]
[0,0,0]]
diag =
[[0,0,0,0,0]
[0,0,0,0,0]
[0,0,0,0,0]
[0,0,0,0,0]
[0,0,0,0,0]]
diag =
[[1,0,0,0,0]
[0,2,0,0,0]
[0,0,3,0,0]
[0,0,0,4,0]
[0,0,0,0,5]]
fill =
[[10,10,10,10,10]
[10,10,10,10,10]
[10,10,10,10,10]
[10,10,10,10,10]
[10,10,10,10,10]]
full =
[[100,100,100,100,100]
[100,100,100,100,100]
[100,100,100,100,100]
[100,100,100,100,100]
[100,100,100,100,100]]
resize =
[[5,5,0,0,0]
[5,5,0,0,0]
[0,0,0,0,0]
[0,0,0,0,0]
[0,0,0,0,0]]

*/

```

```//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
//---
matrix random(4, 5, MatrixRandom);
Print("random = \n",random);

matrix init(3, 6, MatrixSetValues);
Print("init = \n", init);

}
//+------------------------------------------------------------------+
//| Fills the matrix with random values                              |
//+------------------------------------------------------------------+
void MatrixRandom(matrix& m)
{
for(ulong r=0; r<m.Rows(); r++)
{
for(ulong c=0; c<m.Cols(); c++)
{
m[r][c]=double(MathRand())/32767.;
}
}
}
//+------------------------------------------------------------------+
//| Fills the matrix with powers of a number                         |
//+------------------------------------------------------------------+
void MatrixSetValues(matrix& m, double initial=1)
{
double value=initial;
for(ulong r=0; r<m.Rows(); r++)
{
for(ulong c=0; c<m.Cols(); c++)
{
m[r][c]=value;
value*=2;
}
}
}

/*
Execution result

random =
[[0.4200262459181494,0.5014496292001098,0.7520371105075229,0.652058473464156,0.08783227027191992]
[0.5991088595233008,0.4311960203863643,0.8718832972197638,0.1350138859218116,0.901882992034669]
[0.4964445936460463,0.8354747154148991,0.5258339182714317,0.6055482650227363,0.5952940458388012]
[0.3959166234321116,0.8146916104617451,0.2053590502639851,0.2657551805169835,0.3672292245246742]]
init =
[[1,2,4,8,16,32]
[64,128,256,512,1024,2048]
[4096,8192,16384,32768,65536,131072]]

*/
```

```//--- create a matrix of a given 'rows x cols' size
matrix m(3, 3);

// ------ equivalent
matrix m;
m.Resize(3, 3);
```

```void OnStart()
{
//---
ENUM_MATRIX_NORM matrix_norm[]= {MATRIX_NORM_FROBENIUS,
MATRIX_NORM_SPECTRAL,
MATRIX_NORM_NUCLEAR,
MATRIX_NORM_INF,
MATRIX_NORM_MINUS_INF,
MATRIX_NORM_P1,
MATRIX_NORM_MINUS_P1,
MATRIX_NORM_P2,
MATRIX_NORM_MINUS_P2
};
matrix m{{1,2,3},{4,5,6},{7,8,9}};
Print("matrix m:\n",m);
//--- compute the norm using all ways
double norm;
for(int i=0; i<ArraySize(matrix_norm); i++)
{
norm=m.Norm(matrix_norm[i]);
PrintFormat("%d. Norm(%s) = %.6f",i+1, EnumToString(matrix_norm[i]),norm);
}
//---
return;
}

/*
Execution result

matrix m:
[[1,2,3]
[4,5,6]
[7,8,9]]
1. Norm(MATRIX_NORM_FROBENIUS) = 16.881943
2. Norm(MATRIX_NORM_SPECTRAL) = 14.790157
3. Norm(MATRIX_NORM_NUCLEAR) = 17.916473
4. Norm(MATRIX_NORM_INF) = 24.000000
5. Norm(MATRIX_NORM_MINUS_INF) = 6.000000
6. Norm(MATRIX_NORM_P1) = 18.000000
7. Norm(MATRIX_NORM_MINUS_P1) = 12.000000
8. Norm(MATRIX_NORM_P2) = 16.848103
9. Norm(MATRIX_NORM_MINUS_P2) = 0.000000

*/
```

### 矩阵和向量运算

• 换位
• 元素级矩阵加法、减法、乘法、除法
• 矩阵元素与标量的加法、减法、乘法和除法
• 矩阵和向量的 MatMul 积（矩阵积）
• Inner()
• Outer()
• Kron()
• Inv() — 矩阵逆转换
• Solve() — 解线性方程组
• LstSq() — 返回线性代数方程组的最小二乘解（对于非平方或退化矩阵）
• PInv() — 伪逆最小二乘矩阵
• 按照列、行和对角线运算

NumPy 中的类比法

bool matrix.Cholesky(matrix& L) cholesky 计算 Cholesky 分解
bool matrix.QR(matrix& Q, matrix& R) qr

bool matrix.SVD(matrix& U, matrix& V, vector& singular_values)

svd

bool matrix.Eig(matrix& eigen_vectors, vector& eigen_values)

eig

bool matrix.EigVals(vector& eigen_values)

eigvals

bool matrix.LU(matrix& L, matrix& U)

bool matrix.LUP(matrix& L, matrix& U, matrix& P)

### 矩阵与向量的乘积

MatMul() 计算矩阵和向量的矩阵积。 这种方法常用于解决各种数学问题。 将矩阵和向量相乘时，有以下两个选项：

• 左边的水平向量乘以右边的矩阵；向量长度等于矩阵中的列数；
• 左边的矩阵乘以右边的垂直向量；矩阵列的数量等于向量长度。

```void OnStart()
{
//--- initialize matrices
matrix m35, m52;
m35.Init(3,5,Arange);
m52.Init(5,2,Arange);
//---
Print("1. Product of horizontal vector v[3] and matrix m[3,5]");
vector v3 = {1,2,3};
Print("On the left v3 = ",v3);
Print("On the right m35 = \n",m35);
Print("v3.MatMul(m35) = horizontal vector v[5] \n",v3.MatMul(m35));
//--- show that this is really a horizontal vector
Print("\n2. Product of matrix m[1,3] and matrix m[3,5]");
matrix m13;
m13.Init(1,3,Arange,1);
Print("On the left m13 = \n",m13);
Print("On the right m35 = \n",m35);
Print("m13.MatMul(m35) = matrix m[1,5] \n",m13.MatMul(m35));

Print("\n3. Product of matrix m[3,5] and vertical vector v[5]");
vector v5 = {1,2,3,4,5};
Print("On the left m35 = \n",m35);
Print("On the right v5 = ",v5);
Print("m35.MatMul(v5) = vertical vector v[3] \n",m35.MatMul(v5));
//--- show that this is really a vertical vector
Print("\n4. Product of matrix m[3,5] and matrix m[5,1]");
matrix m51;
m51.Init(5,1,Arange,1);
Print("On the left m35 = \n",m35);
Print("On the right m51 = \n",m51);
Print("m35.MatMul(m51) = matrix v[3] \n",m35.MatMul(m51));

Print("\n5. Product of matrix m[3,5] and matrix m[5,2]");
Print("On the left m35 = \n",m35);
Print("On the right m52 = \n",m52);
Print("m35.MatMul(m52) = matrix m[3,2] \n",m35.MatMul(m52));

Print("\n6. Product of horizontal vector v[5] and matrix m[5,2]");
Print("On the left v5 = \n",v5);
Print("On the right m52 = \n",m52);
Print("v5.MatMul(m52) = horizontal vector v[2] \n",v5.MatMul(m52));

Print("\n7. Outer() product of horizontal vector v[5] and vertical vector v[3]");
Print("On the left v5 = \n",v5);
Print("On the right v3 = \n",v3);
Print("v5.Outer(v3) = matrix m[5,3] \n",v5.Outer(v3));
//--- show that the product of matrices generates the same result
Print("\n8. Outer() product of the matrix m[1,5] and matrix m[3,1]");
matrix m15,m31;
m15.Init(1,5,Arange,1);
m31.Init(3,1,Arange,1);
Print("On the left m[1,5] = \n",m15);
Print("On the right m31 = \n",m31);
Print("m15.Outer(m31) = matrix m[5,3] \n",m15.Outer(m31));
}
//+------------------------------------------------------------------+
//|  Fill the matrix with increasing values                          |
//+------------------------------------------------------------------+
void Arange(matrix & m, double start = 0, double step = 1) // the function has three parameters
{
//---
ulong cols = m.Cols();
ulong rows = m.Rows();
double value = start;
for(ulong r = 0; r < rows; r++)
{
for(ulong c = 0; c < cols; c++)
{
m[r][c] = value;
value += step;
}
}
//---
}
/*
Execution result

1. Product of horizontal vector v[3] and matrix m[3,5]
On the left v3 = [1,2,3]
On the right m35 =
[[0,1,2,3,4]
[5,6,7,8,9]
[10,11,12,13,14]]
v3.MatMul(m35) = horizontal vector v[5]
[40,46,52,58,64]

2. Product of matrix m[1,3] and matrix m[3,5]
On the left m13 =
[[1,2,3]]
On the right m35 =
[[0,1,2,3,4]
[5,6,7,8,9]
[10,11,12,13,14]]
m13.MatMul(m35) = matrix m[1,5]
[[40,46,52,58,64]]

3. Product of matrix m[3,5] and vertical vector v[5]
On the left m35 =
[[0,1,2,3,4]
[5,6,7,8,9]
[10,11,12,13,14]]
On the right v5 = [1,2,3,4,5]
m35.MatMul(v5) = vertical vector v[3]
[40,115,190]

4. Product of matrix m[3,5] and matrix m[5,1]
On the left m35 =
[[0,1,2,3,4]
[5,6,7,8,9]
[10,11,12,13,14]]
On the right m51 =
[[1]
[2]
[3]
[4]
[5]]
m35.MatMul(m51) = matrix v[3]
[[40]
[115]
[190]]

5. Product of matrix m[3,5] and matrix m[5,2]
On the left m35 =
[[0,1,2,3,4]
[5,6,7,8,9]
[10,11,12,13,14]]
On the right m52 =
[[0,1]
[2,3]
[4,5]
[6,7]
[8,9]]
m35.MatMul(m52) = matrix m[3,2]
[[60,70]
[160,195]
[260,320]]

6. The product of horizontal vector v[5] and matrix m[5,2]
On the left v5 =
[1,2,3,4,5]
On the right m52 =
[[0,1]
[2,3]
[4,5]
[6,7]
[8,9]]
v5.MatMul(m52) = horizontal vector v[2]
[80,95]

7. Outer() product of horizontal vector v[5] and vertical vector v[3]
On the left v5 =
[1,2,3,4,5]
On the right v3 =
[1,2,3]
v5.Outer(v3) = matrix m[5,3]
[[1,2,3]
[2,4,6]
[3,6,9]
[4,8,12]
[5,10,15]]

8. Outer() product of the matrix m[1,5] and matrix m[3,1]
On the left m[1,5] =
[[1,2,3,4,5]]
On the right m31 =
[[1]
[2]
[3]]
m15.Outer(m31) = matrix m[5,3]
[[1,2,3]
[2,4,6]
[3,6,9]
[4,8,12]
[5,10,15]]

*/
```

### “complex（复数）”类型的复数

```struct complex
{
double             real;   // real part
double             imag;   // imaginary part
};
```
“complex” 类型可以作为 MQL5 函数的参数按值传递（与普通结构不同，普通结构只能通过引用传递）。 对于从 DLL 导入的函数，“complex” 类型只能通过引用传递。

```complex square(complex c)
{
return(c*c);
}

void OnStart()
{
Print(square(1+2i));  // a constant is passed as a parameter
}

// will print "(-3,4)" - a string representation of a complex number
```

#### 该作者的其他文章

| 5 3月 2022 在 14:45
MetaQuotes:

DoEasy 函数库中的图形（第九十一部分）：标准图形对象事件。 对象名称更改历史记录

DoEasy 函数库中的图形（第九十部分）：标准图形对象事件。 基本功能