金字塔数组使用的高级编程技巧

Discussion in '金字塔决策交易系统' started by Superview, Dec 22, 2012.

  1. 做为一款专业的量化交易软件,对于统计学的支持自然必不可少,金字塔在2.90版升级以来增加了大量的统计函数,但是对数组的支持确比较有限,影响到了大量统计函数的使用,从2.931版升级以来,金字塔对数组的支持更进一步增强,本教程就是着手金字塔的数组使用,结合范例,对大家一一做细致的讲解,祝大家在看完这篇教程后,都能编出更加有力的程序化交易武器。


    数组的概念:

    所谓数组,就是有序数据的集合
      如{1,2,5,7,9}这样一组有先后顺序的数据,我们可以把它们定义成一个数组,例如定义为A,数组A就表示这组有序的数据,这里A就是数组的名称(即数组名)。
      数组中的每1个数据,称之为数组中的一个元素,显然上面所说的数组A,第1个元素是1,第2个元素是2,第3个元素是5......,用A[1]、A[2]、A[3]......来表示,用方括号括起来的部分称之为下标,用下标来表示第几个元素。大家可以看出,在本例中,A[1]等于1,A[2]等于2,A[5]等于7,数组A共5个元素,我们就说数组A的长度是5。
      上面所举的例子,数组的每一个元素是数值型的,称之为数值型数组,数组的每个元素也可以是字符串的,即字符串型数组。
      一般来说,数组的使用,要先定义,然后初始化(即赋予数组的每个元素一个初始的数据)。在金字塔中,目前只支持一维数组,并且下标是从1开始的。

    数组的定义:
    金字塔中,数组有两种表现方式,序列变量和声明数组.
    序列变量:
      序列变量其实就是一个数组,我们平时接触最多的是收盘价close,写一行代码“fc:close",就是定义了一个变量fc,并把收盘价赋值给变量fc。这里变量fc就是序列变量,因为fc不是一个值,而是一序列随时间而变化的值(收盘价),在K线图中,从第1根K线到最后1根K线都有一个收盘价,因此fc跟单值变量不同,是由一系列的值组成的变量,因此我们称之为序列变量。事实上,把“fc:close”这行代码做成一个指标,就可以看出fc是一条变化的曲线而不是一条水平直线。
      金字塔新的公式系统,可以把序列变量等同于一个数组,这是一个特殊的数组,这个数组的最小下标是从序列变量的起始有效位置开始,数组的最大下标是K线数量,其中K线的数量,可以从datacount函数得到。
      比如“fc:close;",这行代码,可以把fc看成是一个下标从1开始直到datacount的数组。如果我们想知道第1、2、5、最后1根K线的收盘价,可以写成如下代码:
    代码:
    runmode:1;//序列模式
    fc:=close;//定义一个序列变量,相当于是一个数组
    k1:fc[1];//第1根K线的收盘价
    k2:fc[2];//第2根K线的收盘价
    k3:fc[5];//第5根K线的收盘价
    k_end:fc[datacount];//最后1根K线的收盘价
    声明数组:
    在金字塔中,如何定义、初始化并使用数组?下面简单示例说明:
      
      例1、在金字塔中,定义一个含10个元素的数值型数组
      定义数组的语句是variable,公式代码如下:
    variable:A[10]=0; //定义一个含10个元素的数值型数组A,并把所有元素初始化为0;
      例2:定义一个3个元素的字符串型的数组
      公式代码如下:

    variable:B[3]='abc'; //定义一个含3个元素的字符串型数组B,并把所有元素初始化为'abc'
      例3:把{1,3,5,7,9}定义为数组
      分析:这组数据共有5个数值型数据,因此应定义长度为5的数组,并给每个元素赋值。公式代码如下:
    variable:A[5]=0;
    A[1]:=1;
    A[2]:=3;
    A[3]:=5;
    A[4]:=7;
    A[5]:=9;
      
    得到数组的长度大小:
    数组在定义完成后,我们可以通过UBOUND函数来得到数组的长度.该函数的使用说明如下:
    UBOUND(X),返回序列的上界(最大下标)
    若X为序列数据,则返回当前可用的数组数据上界,若为VARIABLE定义的数组,则返回该数组当前的大小.
    例如:
    VARIABLE :x[5]=0;
    A:c;
    CDC:UBOUND(x); //返回定义数组的长度
    CDD:UBOUND(A); //返回序列数据的长度



    重新定义数组的大小:
    数据在定义完毕之后,在实际的操作中我们可能会重新对数组定义其大小用来动态伸缩扩展,金字塔通过函数SETUBOUND对其进行了支持,SETUBOUND函数的使用范例如下:
    VARIABLE :x[5]=0;//定义一个5个数据的数组
    SETUBOUND(x,10);//扩充数组个数为10个
    CDC:UBOUND(x); //显示重设数组大小后的数组大小
    小技巧:SETUBOUND(x,0);若将数组长度设为0,则表示清空该数组



    删除数组的数据:
    REMOVEBOUND(X,D),X为数组名称,D为数据的下标
    例如:REMOVEBOUND(X,5);表示删除数组X的第5个数组数据



    序列模式下数组与序列数据的转换:
    通过以上的描述大家应该清楚的了解序列数据和数组的使用和处理方法,在金字塔的策略编写时,难免需要用户做一些两种数组之间的转换操作,因为比如某些统计函数需要对2个数组的参数进行统计的时候,是需要2个参数都必须为同一类型.

    //范例1: 序列变量转定义数组变量
    VARIABLE :x[5]=0;
    A:c;
    x:=a; //将序列变量传递到定义数组x并自动扩充设置x数组的大小与序列变量数组a大小一致

    //范例2: 定义数组变量转序列变量
    VARIABLE :x[5]=0;
    A:c;
    a:=x; //数组变量传递到序列变量
    在执行数组变量传递到序列变量操作时需要注意的是,序列变量的长度是不可以被调整的,若序列变量的长度与定义数组变量不一致,那么金字塔将执行如下转换:
    1.若A>X,那么将x数据覆盖传递到a的后方位置,即原有a[datacount]的数据位置将等于x[5]
    2.若A<X,那么将x之前超过a大小数量的数据截掉,然后赋值到a中



    逐K线模式下数组转定义数组变量
    逐K线模式下数组之间的转换与序列模式有所不同,序列模式因为是只执行一次解析返回的是序列变量,因此可以完成直接的数组拷贝,而逐K线则每根K线都回去执行一遍公式的解析,因此在数组之间的转换上也有不同,在执行相互之间转换时,金字塔采用的是只处理数组最后数据的方法,即在逐K线解析时,自动扩充累加数组元素,我们举例如下:
    要求:分别计算阳线和阴线收盘价10个数字的平均价,该需求需要我们分别定义2个数组来保存各自不同的价格,逐K线模式下的这种运行机制便正好可以满足我们的这个需要
    RUNMODE:0;
    VARIABLE:DOWN[]=0;//定义一个空的数组,计算下跌的阳线收盘价,注意这里一定要置空数组用来保存数据
    VARIABLE:UP[]=0;//定义一个空的数组,计算上涨阳线收盘价,注意这里一定要置空数组用来保存数据

    IF CLOSE > OPEN THEN
    UP:=CLOSE;//将上涨K线收盘价插入数组UP中
    ELSE
    DOWN:=CLOSE;//将下跌K线收盘价插入DOWN数组中

    A:MA(UP,10);
    B:MA(DOWN,10);

    //下面2行调试代码
    DD:UBOUND(UP),NODRAW; //显示输出UP数组数据个数
    SS:UBOUND(DOWN),NODRAW; //显示输出DOWN数组数据个数

    注意:

    通过上述的代码我们需要注意的是,UP和DOWN数组前面我们一定要置一个空的数组,这个空数组金字塔会在逐K线执行的时候去自动的填充我们的数据.

    在逐K线模式下对数组的转换操作,应该避免在循环语句中使用,因为可能会导致循环对数组数据积累而导致计算出错



    使用统计函数中数组使用的举例:

    例一:
    INTERCEPT线性回归截距

    利用现有的 x 值与 y 值计算直线与 y 轴的截距。截距为穿过已知的 known_x's 和 known_y's 数据点的线性回归线与 y 轴的交点。当自变量为 0(零)时,使用 INTERCEPT 函数可以决定因变量的值。例如,当所有的数据点都是在室温或更高的温度下取得的,可以用 INTERCEPT 函数预测在 0°C 时金属的电阻。
    用法:INTERCEPT(Y,X,N),求序列Y,X的线性回归线截距,Y为因变的观察值或数据集合,X为自变的观察值或数据集合。

    实例: 已知 y 已知 x
    2 6
    3 5
    9 11
    1 7
    8 5

    代码如下:
    VARIABLE:A[5]=0,B[5]=0;
    A[1]:=2;
    A[2]:=3;
    A[3]:=9;
    A[4]:=1;
    A[5]:=8;

    B[1]:=6;
    B[2]:=5;
    B[3]:=11;
    B[4]:=7;
    B[5]:=5;

    D:INTERCEPT( A,B ,5 );
    上述计算将返回数值 0.0484



    例二:
    STEYX 线性回归法预测标准误差
    返回通过线性回归法计算每个 x 的 y 预测值时所产生的标准误差。标准误差用来度量根据单个 x 变量计算出的 y 预测值的误差量。
    用法:STEYX(Y,X,N),计算Y,X序列变量的线性回归法预测标准误差

    已知 y 已知 x
    2 6
    3 5
    9 11
    1 7
    8 5
    7 4
    5 4

    代码如下:
    VARIABLE:A[7]=0,B[7]=0;
    A[1]:=2;
    A[2]:=3;
    A[3]:=9;
    A[4]:=1;
    A[5]:=8;
    A[6]:=7;
    A[7]:=5;

    B[1]:=6;
    B[2]:=5;
    B[3]:=11;
    B[4]:=7;
    B[5]:=5;
    B[6]:=4;
    B[7]:=4;

    D:STEYX( a,b ,7 );
    上述计算将返回值 3.1508



    例三:
    统计指定数值与一组序列数据的F检验检验结果,该范例是一个序列数据与数组混用的例子,金字塔的统计函数不支持数组的混用,因此我们需要对数组进行转换后进行.

    代码如下:
    VARIABLE:A[]=0;//建立空数组,用来保存转换过来的序列数据
    VARIABLE:B[7]=0;//建立一个7个元素的数组,用这个数组来对序列数据进行统计

    //对数组数据进行初始化
    B[1]:=2336;
    B[2]:=2345;
    B[3]:=2311;
    B[4]:=2237;
    B[5]:=2345;
    B[6]:=2342;
    B[7]:=2433;

    //数据转换
    A:=C;//将收盘价序列数据置数组

    //计算统计结果
    D:FTEST(A,B,7);