MQL5 中的矩阵和向量
向量(vector)是一个一维的双精度型(double)数组。 针对向量定义了以下运算:加法和乘法,以及获取向量长度或模(module)的范数(Norm)。 在程序化过程中,向量通常由同质元素的数组来表示,针对这些不能定义非规则向量运算,即数组不能相加或相乘,并且它们没有范数。
在数学中,向量可以表示为行向量,即由一行和 n 列组成的数组,以及字符串向量,即由一列和 n 行组成的矩阵。 在 MQL5 中,“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 examplesvector 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 resultv = [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,函数名作为第二个参数。 如果函数包含参数,则应在函数名后立即指定这些参数,并用逗号分隔。
函数本身必须包含向量的引用,且作为第一个参数传入。 在 Init 调用期间不应传递向量。 我们以 Arange 函数为例来查看方法的运算。 此函数模仿 numpy.arange。
void OnStart(){
//---vector v;v.Init(7,Arange,10,0,0.5); // 3 parameters are passed with Arange callPrint("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 resultv = [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 copyright "Copyright 2021, MetaQuotes Ltd."
#property link "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 resultExamples 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 resulta + 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 resulta = [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]]*/
如您从示例中所见,Outer 方法返回一个矩阵,其中行数和列数对应于相乘向量的大小。 Dot 和 MatMul 的操作方式相同。
向量范数
向量和矩阵范数表示向量长度(量级)和绝对值。 计算向量范数的三种可能方法已罗列在 ENUM_VECTOR_NORM 枚举之中。
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
利用范数,可以测量两个向量之间的距离:
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 resulta = [1,2,3]
b = [2,3,4]
|a-b| = 1.7320508075688772*/
“矩阵(matrix)” 类型
向量是矩阵的特例,它实际上是一个双精度(double)型的二维数组。 故此,矩阵可以被视为大小相同的向量数组。 矩阵的行数对应于向量的数量,而列数等于向量长度。
加法和乘法运算也适用于矩阵。 传统的编程语言使用数组来表示矩阵。 但是,常规数组之间不能相加或相乘,它们也没有范数。数学上考虑了许多不同的矩阵类型。 例如,单位矩阵、对称矩阵、斜对称矩阵、上下三角矩阵、等类型。
与向量方法类似,矩阵也能利用内置方法创建和初始化。
方法
NumPy 中的类比法
说明
void static matrix.Eye(const int rows, const int cols, const int ndiag=0)
eye
构造一个矩阵,在指定的对角线上填 1,在其它地方填 0
void matrix.Identity()
identity
在矩阵主对角线上填 1,并在其它地方填 0
void static matrix.Ones(const int rows, const int cols)
ones
根据行数和列数构造一个新的矩阵,并用 1 填充
void static matrix.Zeros(const int rows, const int cols)
zeros
根据行数和列数构造一个新的矩阵,并用 0 填充
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 matrixmatrix 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 diagonalmatrix 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 resultm =
[[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]]*/
本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!
