主角,请注意身份txt:大智慧L-2软件指标编辑实例--循环语句
来源:百度文库 编辑:中财网 时间:2024/05/08 07:57:03
1.公式系统简介
公式系统为用户提供了两个公式编辑器:一个是专业公式编辑器,通过公式管理器可以进入,它提供了公式编辑、编译、调试等多种功能,是一个功能强大的编辑器;另一个是标准编辑器,它与过去版本界面类似,通过除了公式管理器以外的位置均进入到这个标准编辑器,它短小精干,易于使用。
这些新增的内容有一定的难度,适合具有计算机编程知识的用户阅读。通过下面章节的学习,你将会逐步了解到这些新特性将给你带来的方便。
2.
在公式系统中,每一个公式是按照语句顺序执行的,例如:
V0:=MA(CLOSE,5);
V1:=MA(CLOSE,10);
在公式系统中,每一个公式是按照语句顺序执行的,例如:
V0:=MA(CLOSE,5);
V1:=MA(CLOSE,10);
将首先执行5日均线的计算,然后再计算10日均线,但是我们忽略了一个问题,那就是其中还隐含了一个时间顺序的问题,也就是说先计算昨天的数值再计算今天的数值。这样,我们就有了两个顺序——语句顺序和时间顺序,我们到底以哪一个顺序为优先呢?答案是以时间顺序为优先,也就是说计算第一天的V0,第一天的V1,然后是第二天的V0,第二天的V1…。对于上面这个例子,由于前后语句之间不存在相互影响,所以到底哪个顺序优先并不影响结果,因此很多人都忽略了这个问题,认为应该首先计算完所有的V0,然后再计算V1。但是在看下面例子:
V0:=IF(V1>CLOSE,CLOSE,V1);
V1:=MA(CLOSE,10);
前面的语句引用了后面的数据,这样V1昨天的计算结果就会影响到V0的计算,此时就必须以时间顺序为优先。
有了这个时间顺序优先,我们就可以解决过去前后数据互相引用、变量重新赋值、迭代计算等问题了。
因此我们应当按照这样的方式思考:我们用公式描述一天的情况,而不是描述一条曲线,整个公式又隐含着一个时间循环,当算完一天的数据后,又重新回到公式起点,计算第二天的数据,如此循环直到计算完所有的数据。需要注意的是,这个隐含循环中可能存在前面语句引用后面数据的问题,如上例中第一个语句中引用了V1变量,而V1变量需要到第二句才有赋值,所以此时它的数值是在上一轮循环中第二条语句所赋值的,也就是昨天的10日均线数值。这是不是有点太复杂了,但是我们将看到这种循环为我们带来的好处。
我们在分析中经常会用到迭代的概念,比如说指数平滑移动平均线EMA,今日均线等于昨日均线*(N-1)加上今日收盘价*2,然后再除以N+1。这样的问题还包括SMA、DMA等等。所谓迭代就是用上一周期的数值来计算本周期的数值。
过去由于公式系统不能直接支持迭代,所以只能用函数来实现这些迭代功能,用新公式系统后,迭代变得可以自己实现了,而且非常简单。以EMA为例:
V1 := (V1*(N-1) + CLOSE*2) / (N+1);
就这么简单,直接按照其原理书写就可以了。我们来分析一下为什么可以这样写。赋值符号 := 左边的V1表示本周期的数值,而右边的V1由于还没有赋值,还保持着上一周期的数值,因此这个V1就还维持着上次计算的结果,也就是上周期的数值,此时它等同于REF(V1,1)。同样的,SMA可以表述为:
V1 := (V1*(N-1) + CLOSE) / N;
需要注意的是,在本语句之后,由于V1已经被赋值,所以它的数值也就变成本周期的数值了。类似的例子还包括:若上周期V1值大于收盘价,则V1等于最高价,否则等于最低价:
V1:= IF(V1>CLOSE, HIGH, LOW);
前面的例子:
V1 := (V1*(N-1)+CLOSE)/N;
我们可能会问,计算第一天的时候,V1的数值是多少。如无特殊说明,变量的初始数值等于0。显然在这个问题中这个设定是不正确的,因为V1等于0的话,计算结果就等于CLOSE/N,显然他不等于第一天的均值,因此我们需要这样说明:
V1 :=IF(BARPOS=0,CLOSE, (V1*(N-1)+CLOSE)/N);
当计算第一天的时候,V1等于收盘价,随后等于指数平滑移动平均。
迭代这个概念理解起来有一定的难度,但如果能够很好地应用它能为我们解决很多问题。
任何变量在使用之前必须先赋值,那么迭代就有可能出现一个问题:变量还没有赋值怎么使用。我们需要用变量声明来解决这个问题:直接说明变量的初始数值和变量的类型,其语法如下:
VARIABLE: P=1;
表示声明一个变量P,设定其初始数值为1,也就是说在计算的第一天,它的数值为1。这样就可以在迭代中使用变量P了。变量声明必须写在任何语句之前,但如果有INPUT参数说明,则应当放在它的后面。
一个完整的指数平滑移动平均线公式可以写成:
VARIABLE: V1=0;
V1 :=IF(BARPOS=0,CLOSE, (V1*(N-1)+CLOSE*2)/(N+1));
再举个例子,我们需要知道当前正在计算第几根K线?第一天为1,第二天为2,我们可以写成:
VARIABLE: P=0;
P := P+1;
使用迭代,方便地描述了这个要求,今天的数值等于昨天的数值+1。这个例子也很好地说明了迭代的简洁和功能强大。
在这里需要特别指出的是,变量声明设定的初始值表示计算的第一天的数值,今后每次计算新的一天并不对该变量设定初始值,例如:
VARIABLE: V1=0;
V2:=0;
V1:=V1+1;
V2:=V2+1;
这当中V1、V2的计算结果将截然不同,V1设定了初始数值0,每次隐含循环加1,他的计算结果为1、2、3、4…,是一个递增的序列;而V2则由于每次循环均被重新设定为数值0,因此V2:=V2+1这条语句将V2设置为1。因此,如果我们需要每天设定初始数值,则需要一条赋值语句来设定;如果我们不需要每天设初始值而是第一天需要,则使用VARIABLE语句声明变量并且赋予初始数值。
新公式系统引入参数说明语句:
INPUT: (,,,);
其中默认值是必需的,其他值若没有指定,则使用其默认值0,100和1。参数说明语句必须放在公式的最前面。
参数说明等同于在公式编辑器中直接在参数输入框中输入参数。系统将参数输入框中和INPUT语句说明的参数累加起来,其总数不能不超过16个。使用参数说明语句,可以使公式程序放在一段文字中,可以方便一部分喜欢这种方式的用户。你可以使用两种方法中的任意一种,他们不存在区别。
我们可以在INPUT语句中说明多个参数,它们之间用逗号分隔。例如:
INPUT: P1(10,0,20), P2(20,0,100);
5.
新公式系统的核心在于:我们只需要描述每一天的行为,如果当天没有改变一个变量,则该变量维持昨天的数值不变。
1.
所谓分支,就是如果满足某个条件就执行某些指令,否则就指令另外一些指令。有了分支,计算机就有了智能,知道根据具体情况作出不同的动作,这是计算机最重要的功能之一。
2.
过去,我们也在函数中隐含地使用了一些分支概念,在函数中直接将分支包含进去。例如绘图函数DRAWTEXT(Cond,Price,Text),表示如果Cond条件满足就输出文字。再例如,IF(Cond,V1,V2)表示如果Cond条件成立就返回V1,否则就返回V2。
但是这种包含在函数中间的条件也有许多缺陷,那就是它只能控制一条语句,而且只在有限的几个函数中包含条件,这极大地限制了分支的应用。例如,我们就无法描述如果条件成立,V1就等于CLOSE,否则V2就等于CLOSE。
3.
我们使用IF THEN 来描述如果条件成立就执行语句这样一个逻辑,例如
IF CLOSE>OPEN THEN
它表示如果收盘价大于开盘价,P的数值就增加1,否则P值维持不变,也就是说统计历史阳线的数量。
需要注意,IF语句和IF函数使用同样的关键字,区分它们的办法是在IF语句之后必然存在THEN语句,而IF函数则没有。因此我们不能在IF语句条件部分包含IF函数,例如:
IF IF(CLOSE>OPEN, OPEN, CLOSE)>10 THEN
该语句将混淆两个IF的作用,可以使用以下方法来解决:
C1 := IF(CLOSE>OPEN, OPEN, CLOSE)>10;
IF C1 THEN
如果我们想要在条件满足的情况下多做几件事情怎么办?在此我们引入BEGIN…END这样一个语句来形成组合语句,也就是说将它们中间所包含的语句看作一个整体,一起执行。组合语句被认为是一个整体,在接下来的分支、循环等作中均需要用到。例如:
IF CLOSE>OPEN THEN BEGIN
END
它表示如果条件成立,将执行对P和Q的赋值语句,否则这两条语句均不执行。
BEGIN…END语句可以嵌套,END与之前面最接近的还没有配对的BEGIN进行配对。例如:
IF CLOSE>OPEN THEN BEGIN
END