量化投资_EasyLanguage/PowerLanguage教学课程__【第一篇基础】__【第五章数组】

第五章:数组

第一节:认识数组

   数组指的是具有一定长度的数据集合,在MC中常用的数组包括一维数组和二维数组(太高维度实用性不大,逻辑一样,这里只举例一维数组和二维数组)。所谓一维数组我们可以理解为一组数据,按照顺序放置在一定的容器中,所谓二维数组我们可以理解为一个二维的表格,如图:

   因此,数组与我们前面认识的bar数据最本质的不同在于,他是一组数据集合。另外我们还可以理解为,一个bar数据,或者一个K线的bar上面的值都是确定、或者说是单一的数据。数组可以在一个单一的bar上面存储我们想要的一组数据,并且方便用于计算和统计。

 

第二节:索引、维度、元素

2.1 索引

  如果我们已经定义好了一个数组后,想要查看数组中某一个/多个位置中的数值、修改某一个/多个位置的数值,我们必须要采取索引的形式。所谓索引就是对数组每一个位置进行编号,就像班级点名一样。一维数组的点名就是从左向右的定义方式;但是二维数组的点名,需要有两个索引值进行定位,如下图:

   如上图一维数组,如果想找到3个数值的位置,它的编号就是2,以此类推,要找到5的这个数值,编号就是4。

   如上图二维数组,如果想找到绿色高亮的5,我们要从横向索引找到1,竖向索引找到5。

 

2.2 维度

  维度是一个很好理解的概念,这里略。

 

2.3 元素

  前面都用里面的数值来说,在数组当中,每一个的值我们统一换一个名词,叫做元素。有多少个元素就叫多少个元素的个数。在MC中,元素的类型共有三种基本数据类型:数值型、布尔型、字符串型,分别也是对应前面提到的数据类型,这是一致的。

  

第三节:定义静态一维数组和静态二维数组

  前面的知识是解释数组,下面是需要我们手动创建数组。

  所谓创建静态数组就是在声明时,已经规定好了数组的“尺寸”或者说“维度”。

# 示例1创建一个一维数组

array:arr[4](0);

cleardebug;

print(array_getmaxindex(arr));
print(arr[0]);
print(arr[1]);
print(arr[2]);
print(arr[4]);
#//返回值:

4.00
0.00
0.00
0.00
0.00

# 说明:我们看到生命时采用的是array:/arrays:这样的方式来声明数组。其中需要包括方括号和圆括号([] ()),其中方括号里面需要填写的就是数组的最大索引值(也就是允许的最大索引是什么),圆括号是默认数组每个元素的初始值是什么。这样就创建了一个静态的一维数组。其中array_getmaxindex是获取数组的最大索引函数,后面会总结这些内容。这里特别说明的是:数组的最大索引是从0开始计数的,而不是从1开始

# 示例2:当然我们还可以创建布尔型的一维数组和字符串的一维数组

array:arr[4](False);

cleardebug;

print(array_getmaxindex(arr));
print(arr[0]);
print(arr[1]);
print(arr[2]);
print(arr[4]);
//返回值:
   4.00
FALSE
FALSE
FALSE
FALSE

array:arr[4]("Hello World");

cleardebug;

print(array_getmaxindex(arr));
print(arr[0]);
print(arr[1]);
print(arr[2]);
print(arr[4]);
//返回值:
   4.00
Hello World
Hello World
Hello World
Hello World

 

# 示例3:我们再次创建一个二维数组

array:arr[1,1](0);

cleardebug;

//print(array_getmaxindex(arr));
print(arr[0,0]);
print(arr[0,1]);
print(arr[1,0]);
print(arr[1,1]);

# 说明:与一维数组不一样的是,二维数组在声明时需要用逗号分隔,分别定义横向和竖向的最大索引值。另外,数组的查找和声明数组最大索引的方式一样,也是通过方括号进行访问和修改。

  

第四节:修改值和快速赋值

4.1 修改值:

  在初始化之后,想要修改值,也是通过索引的方式进行修改。

# 示例1:修改0,1这个位置元素的值

array:arr[1,1](0);

//cleardebug;

//print(array_getmaxindex(arr));
print(arr[0,0]);
print(arr[0,1]);
print(arr[1,0]);
print(arr[1,1]);

arr[0,1] = 100;

print(arr[0,0]);
print(arr[0,1]);
print(arr[1,0]);
print(arr[1,1]);
//返回值
   0.00
   0.00
   0.00
   0.00
   0.00

 100.00
   0.00
   0.00
   0.00

 

4.2 快速赋值

  手动敲值不太实际,如果我们像保存最近5个bar的close价格。快速赋值用的最多的方式就是用循环。

# 示例1:通过循环赋值

array:arr[4](0);

for value1 = array_getmaxindex(arr) downto 0
    begin
        arr[array_getmaxindex(arr)-value1] = Close[value1];
    end;
    

print("========");
for value2 = 0 to array_getmaxindex(arr)
    begin
        print(arr[value2]);
    end;

//返回值:
========
5296.00
5278.00
5253.00
5274.00
5274.00

 

 第五节:数组的全局性

   数组的运算也是tick by tick(逐笔)的方式进行的。就是一个新的tick进来时,数组会重新运算一次。说到全局性是MC对于数值的一个默认设置。前面提到过完成bar的问题,如果一个bar完成了,新的bar来到,那么在上一个完成bar计算的数组,在新的这个bar数值是不是还存在。比如像TBQuant(交易开拓者Quant版本)中存在全局变量和非全局变量这么一说(当然数组也是一个变量),也就是说,新的bar来到,如果是非全局变量的话,上一个bar的数组值会全部清空,重新计算,也就是在新的bar里面是无法取到上一个bar已经计算好的数组值。因此在TBQuant在声明数组时,在前面需要加上global全局声明的字段。但是在MC中就不会存在这么一个问题,因为数组在MC中全部都是全局的。为了应征这么一个问题,我们用once语句,一次初始化运行计算一个数组,然后在动态过程每一个bar和逐笔的状态观察,这些数组中的数值是否还存在。

# 示例

array:arr[4](0);

once begin

for value1 = array_getmaxindex(arr) downto 0
    begin
        arr[array_getmaxindex(arr)-value1] = Close[value1];
    end;
end;
    

print("========");
for value2 = 0 to array_getmaxindex(arr)
    begin
        print("time:=",Time,"===",arr[value2]);
    end;
//返回值:
========
time:=2200.00===5160.00
time:=2200.00===5163.00
time:=2200.00===5170.00
time:=2200.00===5174.00
time:=2200.00===5168.00
========
time:=2300.00===5160.00
time:=2300.00===5163.00
time:=2300.00===5170.00
time:=2300.00===5174.00
time:=2300.00===5168.00
========
time:=1000.00===5160.00
time:=1000.00===5163.00
time:=1000.00===5170.00
time:=1000.00===5174.00
......后面略

 # 说明:通过这个实验表明,在加载图表时,用once做一次初始化的操作,只取需要开始的5个bar的收盘价存入数组,后面再不进行修改,此时逐笔和后面新的bar都会取到前面时刻的数组值。也就是手在MC中数组是全局性的。这一点虽然对于初学者来说并不重要,但是这里要特别说明一下。

 

第六节:动态数组

  第四节说到在声明的时候指定数组的长度,也就是在方括号[]当中定义数组的最大索引值。其实也可以根据实际的生产需要,动态定义数组的大小。此时就会用到数组函数Array_SetMaxindex,(与Array_GetMaxindex对应为获取最大索引值)后面有两个参数,分别是数组名称,和最大索引值,但是可惜的是,在MC中,这个函数只能默认定义一维数组,对于二维数组的操作无能为力。

  如果需要定义动态的数组,此时在方括号中的最大索引值就无需填写

# 示例1:定义动态数组的最大索引值

array:arr[](0);

array_setmaxindex(arr,4);

print(array_getmaxindex(arr));

 

 # 示例2:动态调整数组的最大索引值,这里设置两个bar的时间如果不一致,对数组动态调整最大索引值

array:arr[](0);
var:value1(0);

print("=======");

if Time<>Time[1] then value1 = value1 + 1;

array_setmaxindex(arr,value1);

print(array_getmaxindex(arr));
//返回值:

=======
0.00
=======
=======
1.00
=======
2.00
=======
3.00
=======
4.00
=======
5.00
=======
6.00
=======
7.00
=======
8.00
=======
9.00
=======

.....略

 

问题:这里有一个提问,如果按照示例2所示,我们动态调整数组的话,那其他的值会不会改变?我们做下面这个实验:

# 示例3:对动态数组进行递减定义最大索引的方式

array:arr[](0);
var:value1(5);

print("=======");

once begin
    array_setmaxindex(arr,4);
    arr[0] = 1;
    arr[1] = 2;
    arr[2] = 3;
    arr[3] = 4;
    arr[4] = 5;
end;

if Time<>Time[1] then value1 = value1 - 1;

if value1 > -1 then array_setmaxindex(arr,value1);

print("array length = ",array_getmaxindex(arr));

if array_getmaxindex(arr) <> 0 then
    begin
    
    for value2 = 0 to array_getmaxindex(arr)
        begin
            print(arr[value2]);
        end;
    end;

//返回值:
array length =    4.00
   1.00
   2.00
   3.00
   4.00
   5.00
=======
array length =    3.00
   1.00
   2.00
   3.00
   4.00
=======
array length =    2.00
   1.00
   2.00
   3.00
=======
array length =    1.00
   1.00
   2.00
=======
array length =    0.00

# 说明:我们惊奇的发现,虽然我们改变了数组的长度,但是之前的值还是存在的,因此证明了:数组是具有全局性,且数组当中的元素也是具有全局性的!这一点是非常重要的

 

第七节:数组的函数

  说在前面:前面一直提到了函数这个概念,所谓函数可以理解为不需要人为的去手工写代码,我们可以事先写好组合起来,或者MC提供给我们的一些写好的代码,我们可以直接使用,而不需要重复每次再写的东西,后面的章节会详细的讲解函数这个概念。

  数组的函数大多是动态数组的函数。前面见过了两个分别是Array_SetMaxindex和Array_GetMaxindex。后面这两个就不在举例了。

 

7.1 Array_Compare

# 语法

Array_Compare(源数组,源索引,目标数组,目标索引,元素个
数)
参数:
源数组——要比较的第一个数组
源索引——数值表达式,指定数组 1 的开始索引值
目标数组——要比较的第二个数组
目标索引——数值表达式,指定数组 2 的开始索引值
元素个数——数值表达式,要比较的元素个数
索引从 0 开始计数

返回:
0——比较的每组元素完全相同;
1——源数组的元素大于目标数组;
-1——源数组的元素小于目标数组。

# 示例

比较数组元素 Array1[3]和 Array2[2]的大小,以及 Array1[4]
和 Array2[3]的大小:
Array:Array1[4](0),Array2[6](0);
for Value1=0 to 4 begin Array1[Value1]=Value1*2; end;
for value2=0 to 6 begin Array2[value2]=value2*3; end;

Value3=Array_Compare(Array1,3,Array2,2,2);
由上可知 Array1[3]= Array2[2]且 Array1[4]< Array2[3],则
Value3=-1
若 Array1 为{false, false, false, false, false, false, true, false},
Array2 为{false, false, false, false, false, false, true, false},则
Value3=0
若 Array1 为{a,b,c,d,e,f,g,h},Array2 为{a,b,c,d,e,f,g,h},则
Value3=1

# 说明

比较源数组和目标数组中的指定起始位置及指定数量的元 素是否相同 源数组和目标数组可以是相同或不同的一维数组。 若比较的数组为数值数组,会比较每组元素的数值大小。 若比较的数组为字符串数组,会比较每组元素的 ASCII 值的 大小。 若比较的数组为布林数组,会比较每组元素的布林值是否相 同,若不相同时,真(true)大于假(false)。

 

7.2 Array_Copy

# 语法

Array_Copy(源数组,来源索引,目标数组,目标索引,元素个数)

参数
源数组——要复制的源数组
源索引——数值表达式,指定源数组的索引值
目标数组——要复制的目标数组
目标索引——数值表达式,指定目标数组的索引值
元素个数——数值表达式,要比较的元素个数

# 示例

复制 Array1 索引 4 开始的 2 个元素至 Array2 索引 6 开始的 2
个元素位置:
Array_Copy(Array1,4,Array2,6,2);
复制 Array1 索引 4 开始的 2 个元素至索引 6 开始的 2 个元
素位置:
Array_Copy(Array1,4,Array1,6,2);

# 说明

复制源数组中的指定起始位置及数量的元素至目标数组指 定的起始位置。 源数组和目标数组可以是相同或不同的一维数组。

 

7.3 Array_GetType

# 语法

语法 Array_GetType(数组名称)
参数 数组名称——要查询的数组名称
返回值
2——布林型数组
3——字符串型数组
7——数值型数组

# 示例

查询 Array1 的类型,并将结果存入变量 Value1:
Array: Array1[10](false);
Value1=Array_GetType(Array1);
则 Value1=2
Array: Array1[10](“”);
Value1=Array_GetType(Array1)
则 Value1=3
Array: Array1[10](0);
Value1=Array_

# 说明

  取得数组的类型。

 

7.4 Array_SetValRange

# 语法

Array_SetValRange(数组名称, 起始索引,结束索引,数值)
参数
数组名称——要赋值的数组名称
起始索引——数值表达式,指定数组赋值范围的开始索引
值
结束索引——数值表达式,指定数组赋值范围的结束索引
值
数值——数值表达式、字符串表达式或布林表达式,数组
元素要设定的值。数值的类型要和数组定义类型一致。

# 示例

重新赋值 Array1 索引 4 至索引 6 的元素:
Array_SetValRange(Array1,4,6,0);
若数组为{1,2,3,4,5,6,7,8},则赋值后数组为{1,2,3,4,0,0,0,8}
Array_SetValRange(Array1,4,6,True);
若数组为{false, false, false, false, false, false, true, false},则
赋值后数组为{false, false, false, false, true, true, true, false}
Array_SetValRange(Array1,4,6,”a”);
若数组为{a,b,c,d,e,f,g,h},则赋值后数组为{a,b,c,d,a,a,a,h}

# 说明

  同时为数组指定范围的元素赋值

 

7.5 Array_Sort

# 语法

Array_Sort(数组名称, 起始索引, 结束索引, 排序方式)
参数
数组名称——要排序的数组名称
起始索引——数值表达式,指定数组排序范围的开始索引值
结束索引——数值表达式,指定数组排序范围的结束索引值
排序方式——布林表达式,指定数组的排序方式,True 为
递增,False 为递减

# 示例

重新排序 Array1 索引 4 至索引 6 的元素:
Array_Sort(Array1,4,6,false);
若数组为{1,2,3,4,5,6,7,8},则赋值后数组为{1,2,3,4,7,6,5,8}
若数组为{false, false, false, false, false, false, true, false},则
赋值后数组为{false, false, false, false, true, false, false, false}
若数组为{a,b,c,d,e,f,g,h},则赋值后数组为{a,b,c,d,g,f,e,h}

# 说明

  重新排序数组中的指定范围数值,若数值数组依据数值大小排序,若为布尔数组,依据True=1,False=0的大小排序,若为字符串数组,依据ASCII码的值进行排序

 

7.6 Array_Sum

# 语法

Array_Sum(数组名称,起始索引,结束索引)
参数
数组名称——要加总的数组名称
起始索引——数值表达式,指定数组加总范围的开始索引值
结束索引——数值表达式,指定数组加总范围的结束索引值

# 示例

加总 Array1 索引 4 至索引 6 的元素,并将结果存入变数
Value1:
Value1=Array_Sum(Array1,4,6);
若数组为{1,2,3,4,5,6,7,8},则 Value1=18

# 说明

  返回数值数组中之指定范围额数值总和

 

7.7 Fill_Array

# 语法

Fill_Array(数组名称,数值)
参数
数组名称——要设定值的数组名称
数值——数值表达式、字符串表达式或布林表达式,要指
派给数组元素的值。数值的类型要和数组定义类型一致

# 示例

将 Array1 中的每个元素设定为 True:
Array: Array1[10](False);
Fill_Array(Array1,True);

# 说明

  将数组中的元素设定指定的值  

 

7.8 Array_indexof

# 语法

array_indexof(数组名,元素值)

# 示例

array:arr[2](0);

var: var0(0), var1(0);

arr[0] = 1;
arr[1] = 2;
arr[2] = 3;

var0=array_indexof(arr,3);

print("var0= ",var0);

//返回值:2

# 说明

  返回一维数组中指定元素的索引值,若元素值不存在于数组中,则返回-1

 

=================================================

之前的文章感谢大家的转载,希望转载时请注明出处,本人转自其它网站的图表一并感谢,谢谢~!

https://www.cnblogs.com/noah0532/

posted @ 2020-09-16 23:07  时海涛|Thomas  阅读(862)  评论(0编辑  收藏  举报