加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

[金字塔教程二]金字塔的控制语句

(2014-01-13 20:12:09)
标签:

开盘价

教程

语法

程序化交易

股票

分类: 金字塔决策交易系统

    金字塔是个强大的脚本执行平台,除了我们在基础教程部分介绍的顺序执行语句外,可以执行带条件分支和循环以及无条件跳转都是金字塔的特色功能,金字塔的模型在工作时,由于内部运行机制不同,分为序列模式以及逐K线模式,我们这里先从序列模式介绍公式系统的运行机理,逐K线模式我们在后面会另有介绍。下面我们将逐步向大家介绍如何使用金字塔的控制语句编写模型。

 

    2.1序列变量与数组
    在金字塔的新公式系统的增加部分中,需要大量运用并区分数组、单值变量及序列变量的概念,这些概念也是进一步学习编程(比如编DLL)所必需的,因此有必要简单描述并初步掌握这些概念。

 

    2.1.1常数与单值变量
    常数,在金字塔中,就是不允许改变的数值,在我们平常写公式时,为了公式更加灵活,大量使用了参数,这些参数就是常数,不允许在公式中改变,比如参数n(1,1,25),表示参数n最小值是1、最大值是25、默认值是1,如果在公式中再写一行“n:=30;”就是非法的。
    单值变量,即只有一个数值,不随时间而改变,比如“x:100;”,就是定义了一个单值变量x=100,这个值不随时间而改变,做成副图指标看,今天x是100明天x也是100,直到最后1根K线也是100,即副图指标是一条数值为100的水平直线。
 
    2.1.2数组
    所谓数组,就是有序数据的集合
  如{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开始的。
  在金字塔中,如何定义、初始化并使用数组?下面简单示例说明:
  
  例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;
  前面所举的关于数组例子,都是概念性的,单纯数组的应用一般都比较复杂,比如,从每天的分笔成交中统计,各个成交价位成交的笔数。等到后面讲完循环有机会时再写具体的代码。

 

2.1.3序列变量:
  我们平时接触最多的是收盘价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线的收盘价,可以写成如下代码:
    代码:
    fc:=close;//定义一个序列变量,相当于是一个数组
    k1:fc[1];//第1根K线的收盘价
    k2:fc[2];//第2根K线的收盘价
    k3:fc[5];//第5根K线的收盘价
    k_end:fc[datacount];//最后1根K线的收盘价

    2.2循环语句
    金字塔的循环语句有两个类别,一个是 FOR TO … ,另一个是REPEAT UNTIL …,这里我们重点介绍FOR循环,REPEAT UNTIL的例子,用户请自行在金字塔软件函数列表中查看使用方法。

    2.2.1  FOR递增循环
    先从一个的实例开始,求当前股票收盘价的2日算术平均价,为了方便起见,以刚上市不久的600340国祥股价来说明,首先定义序列变量fc为收盘价,根据上一讲我们知道,fc可以看成是一个数组,因此,数组fc的每一个元素如下表所示:
600340    国祥股份
         时间    收盘
fc[1]     2003/12/30    8.92
fc[2]     2003/12/31    8.96
fc[3]     2004/01/02    9.25
fc[4]     2004/01/05    9.64
fc[5]     2004/01/06    9.92
fc[6]     2004/01/07    9.74
fc[7]     2004/01/08    10.44
fc[8]     2004/01/09    9.99

    显然, 2日平均收盘价必须是从第2根K线即上市后第2日开始,到最后一天结束,设2日平均股价用序列变量ma2来表示,由于2日平均收盘价等于当日收盘价加昨收盘除以2,如果手工一行一行来写代码计算,则:
    ma2[2]:=(fc[1]+fc[2])/2;  //今收盘与昨收盘之和除以2,等于今2日平均收盘价
    ma2[3]:=(fc[2]+fc[3])/2;
    ma2[4]:=(fc[3]+fc[4])/2;
    ma2[5]:=(fc[4]+fc[5])/2;
    ma2[6]:=(fc[5]+fc[6])/2;
    ma2[7]:=(fc[6]+fc[7])/2;
    ma2[8]:=(fc[7]+fc[8])/2;

    分析上面代码,2日平均价的计算特点是:
    ① 从第2根K线开始计算的
    ② 每天的均价都等于(今收盘+昨收盘)/2
    ③ 直到最后1根K线结束
    容易知道,如果有1000根K线,则要写999行代码,显然效率太低了。
    我们来找找规律,如果是中间的某天即第i天,则上面的表达式可以写为
    ma2[i]:=(fc[i-1]+fc[i])/2;

    这个i是从第2根K线开始直到最后1根K线。这些计算都是重复同样的计算,只不过i不同罢了。如果有一种方法,可以自动重复计算这些表达式,并且每重复一次,i自动增加1,就可以达到目的了。由此我们定义一种循环语句,可以自动循环、重复运行某一行代码。在金字塔中,循环语句有2种,下面先介绍FOR循环语句
    语法:
    FOR var=n1 TO n2 DO expr;
    {从 var=n1 开始,直到 var=n2,开始循环执行 expr 语句,每执行一次var加1。这里,var称之为循环变量。}
    用循环语句表达上面计算2日平均收盘价,公式代码如下:
    fc:=close;  //定义序列变量fc为收盘价
    for  i=2  to  datacount  do  ma2[i] : (fc[i-1]+fc[i])/2;
    //从i=2到i=datacount循环执行ma2[i] : (fc[i-1]+fc[i])/2
 
    2.2.2 FOR递减循环
   上面的FOR循环,循环变量是每次递增1,可称之为递增FOR循环。还有一种FOR循环是递减FOR循环,循环变量是每次递减1,语法如下:
    FOR var=n1 DOWNTO n2 DO expr2;
    {从 var=n1 开始到 var=n2 开始循环执行 expr 语句,每执行一次var减1}
    上面我们设计2日平均收盘价的公式时,是从前面往后面计算的,仔细想想,其实也可以从后面往前面计算,公式代码如下:
    fc:=close;
    for i=datacount downto 2 do ma2[i] : (fc[i-1]+fc[i])/2;

 

     2.2.3设置序列变量下界语句
    原因是我们把ma2定义成序列值收盘价,在上面的循环代码中,只是从第2根K线开始计算均价,第1根K线的位置没有计算,仍然保留了原来收盘价的数值。怎样去掉第1根K线位置的数值,使得ma2的起始有效位置是从第2根K线开始的?使用下面的语句就可以实现:

     设置序列变量下界(有效数据起始下标),函数返回序列下界
    用法:
    SETLBOUND(X,N),设置序列变量X的下界(最小下标),N为0或N超过上界则整个序列数据都无效
    例如:
    VAR1:C;n1:=SETLBOUND(VAR1,10);
    用“设置序列变量下界”语句setlbound(x,n),改写上面的公式,代码如下:

    ma2:=close;  //定义序列变量ma2等于收盘价
    aa:=setlbound(ma2,2); //设置序列变量ma2的下界为2,起始有效位置是从第2根K线开始
    fc:=close;
    for i=datacount downto 2 do ma2[i]:(fc[i-1]+fc[i])/2;

 

    2.2.4复合语句
    复合语句注释:
    把多条语句看作一条语句
    语法:BEGIN...END
    这里,begin和end是成对出现的,被begin和end包围起来的语句可以有很多条,这些语句可以看成是一条复合语句。
    下面我们用begin…end来改写递增循环计算2日平均收盘价的公式:
    fc:=close;  //定义序列变量为收盘价
    for  i=2  to  datacount  do
    begin
        a:= fc[i-1]+fc[i];  //定义一个临时的单值变量a,保存中间计算结果
        ma2[i] : a/2;
     end;
     这段代码,就是由2行代码组成的复合语句,被循环执行若干次。为了代码容易分辨,我们特别把复合语句中的2行代码,都向右缩了4格,表明这是2行复合语句,是被循环语句所控制的。以前对于这类分层次的语句,都要进行缩格,便于看懂代码,特别是复杂的代码,如果不进行缩格,时间久了,恐怕连自己都很难看懂,大家一开始就要养成好习惯。
     有人会问,书写代码不缩格行吗?不缩格公式会不会出错?答案是,缩格书写代码,仅仅是为了方便看清程序代码的逻辑层次,对公式的运行没有影响。
    有了复合语句,循环的功能就更加强大了,可以轻松实现多重循环,即循环中套循环。在计算N日的平均价时会用到,如果事先不知道N是多少,就要用到二重循环。对于循环中要执行的语句,如果重复太多,也可以使用多重循环来简化。以二重循环为例,大致结构如下:

for i=n1 to n2 do
begin
    语句;
   
    for j=m1 to m2 do
    begin
        语句;
       
    end;
    语句;
   
end;

 

    2.3条件语句
    条件语句的语法如下:
    IF条件语句
    语法:IF cond THEN expr1 ELSE expr2
    如果 cond 条件成立,则执行语句 expr1,否则执行 expr2 语句。
    说明:
   1、在条件判断比较简单的情况下,ELSE expr2 子句可以省略。
   2、条件 cond 可以是单值变量,也可以为序列变量。当为序列变量时,cond将取最后一个周期的值做为条件判断语句。


   条件语句的语法比较简单,但使用时却容易出错,下面举若干示例。

例1:修改成交量公式VOL,当流通盘不为零且当前周期为日以上周期时,显示换手率,代码参考如下(仿此,大家绕过指标模组,可以自行设计,“绑定”到周期、券种等的公式)
     代码:

     VOL,VOLSTICK;
     MA1:MA(VOL,M1);
     MA2:MA(VOL,M2);
     MA3:MA(VOL,M3);
     if capital>0 and DATATYPE>=6 then
     换手率:vol/capital; //日以上周期及非指数个股,显示换手率

     当切换到60分钟及以下周期,或者切换到大盘(此时流通盘=0),会发现“换手率”指标线、名称及数值都不显示。
  以上是较简单的情况,没有使用 ELSE expr2 子句。上面代码稍加改进,使用复合语句,使之适用于任意周期:
  
例2,修改成交量公式,流通盘不为0时,显示换手率(60分钟及以下周期,计算当日最新的换手率),代码参考如下:
代码:

VOL,VOLSTICK;
MA1:MA(VOL,M1);
MA2:MA(VOL,M2);
MA3:MA(VOL,M3);

IF CAPITAL>0 then //如果换手率>0,则
  IF DATATYPE>=6 then //如果周期为日及以上的较长周期,则
    b:=VOL/CAPITAL*100;
  else //否则
  begin //复合语句开始,即以下3条语句,视为1条语句,end表示复合语句结束
    tj:=DAY>REF(DAY,1) or BARSSINCE(CLOSE)=0;
    ts:=BARSLAST(tj)+1;
    b:=SUM(VOL,ts)/CAPITAL*100;
  end;
换手率:b;


  例3、通过参数N,控制调整均线数,代码参考如下:
代码:


input:p1(5,0,300),p2(10,0,300),p3(20,0,300),p4(30,0,300),n(4,1,4);{参数定义}
IF n>0 then MA1:MA(CLOSE,P1);{如果n>=1则输出ma1指标线}
IF n>1 then MA2:MA(CLOSE,P2);{如果n>=2则输出ma1指标线}
IF n>2 then MA3:MA(CLOSE,P3);{如果n>=3则输出ma1指标线}
IF n>3 then MA4:MA(CLOSE,P4);{如果n>=4则输出ma1指标线}


  在使用条件语句“IF cond THEN”中,序列模式下,cond如果是序列变量,那么IF语句只取最后序列值做为条件判断,比如:
代码:


fc:=close;
fo:=open;
if fc>fo then  //这里的fc、fo是序列变量,因此只取最后一个周期的条件做为判断依据
  xx:=1;
else
  xx:=0;
y:xx;

这里,if fc>fo then 这种写法的本意是,“如果收盘价大于开盘价则”,是针对序列变量的每个数据(相当于数组的每个元素),但是在序列模式下是不会得到执行结果的,在金字塔的序列模式运行中,正确的写法应该是这样的:
代码:


//如果xx是序列变量,则代码参考如下
fc:=close;
fo:=open;
for i=1 to datacount do
begin
  if fc[i]>fo[i] then
    xx[i]:=1;  //请注意这里跟上面代码的不同
  else
    xx[i]:=0;
end
y:xx;

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有