配色: 字号:
飞狐公式函数系统,循环、分支语句入门
2012-08-29 | 阅:  转:  |  分享 
  
《飞狐公式系统,循环、分支语句入门》--南客国内外股票期货历史数据下载:http://gpqh.net.cn



?序:飞狐内嵌的VBS(或JS)脚本语言,功能已经非常强大,可以真正在编程的意义上编制各种强大的公式,不比DLL弱,甚至某些无法用DLL实现的功能,亦可在VBS(或JS)中实现,但比较明显的弱点是,VBS(或JS)语言是解释执行的,速度比DLL慢。为此,飞狐在3.7以上版本中,开发了内置的循环、判断语句,提供字符串处理函数等功能,可以把飞狐中的序列变量等同于数组处理,任意访问序列变量,进一步加强了飞狐的公式系统。下面以入门的形式,分若干专题并配以适当的示例、练习、思考,与大家一起共同学习。由于涉及编程的许多概念比较复杂,因此在讲述的过程,假定大家已经有了一定的编公式的基础,对许多编一般公式的细节不再详述。网络论坛上开设互动专题,受到诸多条件的局限,不知道大家的学习效果如何,希望能够在专题的贴子后,提出建议、问题,以便下一专题能够及时调整难易程度。此外,我也会尽量抽时间回答贴子中的问题。同时也请高手们帮助解答,并指出专题中的错误!谢谢大家!一、序列变量与数组:在飞狐的新公式系统的增加部分中,需要大量运用并区分数组、单值变量及序列变量的概念,这些概念也是进一步学习编程(比如编DLL)所必需的,因此有必要简单描述并初步掌握这些概念。1、常数与单值变量:常数,在飞狐中,就是不允许改变的数值,在我们平常写公式时,为了公式更加灵活,大量使用了参数,这些参数就是常数,不允许在公式中改变,比如参数n(1,1,25),表示参数n最小值是1、最大值是25、默认值是1,如果在公式中再写一行“n:=30;”就是非法的。单值变量,即只有一个数值,不随时间而改变,比如“x:100;”,就是定义了一个单值变量x=100,这个值不随时间而改变,做成副图指标看,今天是100明天也是100,直到最后1根K线也是100,即副图指标是一条数值为100的水平直线。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;例4:把{1,5}和{''a'',''b'',''c''}定义为数组分析:variable语句,可以同时定义多个变量、数组,之间用逗号隔开。公式代码如下:variable:A[2]=0,B[3]='''';A[1]:=1;A[2]:=5;B[1]:=''a'';B[2]:=''b'';B[3]:=''c'';前面所举的关于数组例子,都是概念性的,单纯数组的应用一般都比较复杂,比如,从每天的分笔成交中统计,各个成交价位成交的笔数。等到后面讲完循环时再写具体的代码。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;fc[1];fc[2];fc[5];fc[datacount];

再看一例“fm:ma(c,5)”,这里的5日均价fm也是一个序列变量,可以看成下标从5开始直到datacount的数组。想想看,为什么起始下标不是从1开始,而是从5开始?我想知道K线图上倒数第2根K线对应的5日均价怎么写公式代码?今天就说这些,下面提供一些练习与思考:思考1:如何知道当前股票的K线数?使用什么函数?思考2:如果“fv:=vol”,那么fv[9]表示什么?思考3:“fmh:ma(h,5)”,fmh[datacount]表示什么?试试:在飞狐中新建一个公式,编一段下面的公式代码:LL:=MA(Low,10);A:LL[9];这段代码想表达什么?可以通过吗?为什么?练习1:根据序列变量可以看成一个数组,编一个公式,求出当前股票的上市日期。练习2:函数barpos返回当前是第几根K线,由此,设计一个公式,在最后1根K线和倒数第10根K线处,用函数drawicon做一标记。练习3:画一醮由鲜械?天开始的水平直线,其高度等于当前股票的历史最高价。练习4:画一条从上市第1天开始的水平直线,其高度位于当前股票历史最高、最低价的一半位置。练习5:当前股票,2003年最高价是多少?首次出现该最高价的日期是哪天?循环语句

1、FOR递增循环:先从一个的实例开始,求当前股票收盘价的2日算术平均价,为了方便起见,以刚上市不久的600340国祥股价来说明,首先定义序列变量fc为收盘价,根据上一讲我们知道,fc可以看成是一个数组,因此,数组fc的每一个元素如下表所示:600340??????国祥股份????????时间??????收盘fc[1]??????2003/12/30??????8.92fc[2]??????2003/12/31??????8.96fc[3]??????2004/01/02??????9.25fc[4]??????2004/01/05??????9.64fc[5]??????2004/01/06??????9.92fc[6]??????2004/01/07??????9.74fc[7]??????2004/01/08??????10.44fc[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循环语句语法:FORvar=n1TOn2DOexpr;从var=n1开始到var=n2开始循环执行expr语句,每执行一次var加1。这里,var称之为循环变量。用循环语句表达上面计算2日平均收盘价,公式代码如下:fc:=close;??//定义序列变量为收盘价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、FOR递减循环:上面的FOR循环,循环变量是每次递增1,可称之为递增FOR循环。还有一种FOR循环是递减FOR循环,循环变量是每次递减1,语法如下:FORvar=n1DOWNTOn2DOexpr2;从var=n1开始到var=n2开始循环执行expr语句,每执行一次var减1上面我们设计2日平均收盘价的公式时,是从前面往后面计算的,仔细想想,其实也可以从后面往前面计算,公式代码如下:fc:=close;fori=datacountdownto2doma2[i]:(fc[i-1]+fc[i])/2;新建一个公式,输入上面代码,验证一番,结果如下图:



循环语句

咦?什么也没有显示,是怎么回事?问题出在ma2,ma2在这里事先没有定义,飞狐不知道ma2是什么变量,因此无法输出。改写公式代码如下:ma2:=close;??//定义序列变量ma2等于收盘价fc:=close;fori=datacountdownto2doma2:(fc[i-1]+fc)/2;再看看这回的结果图示:

循环语句

现在有输出了,但仔细观察,还有点问题,第1根K线的位置应该没有输出才行,现在却有输出?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;fori=datacountdownto2doma2[i]:(fc[i-1]+fc[i])/2;图示如下:



循环语句

这个结果就对了!但大家可能会有疑问了,在前面递增循环中,ma2同样没有事先定义,结果却是正确的,这是为什么?回顾一下前面递增循环的代码:fc:=close;??//定义序列变量为收盘价for??i=2??to??datacount??do??ma2[i]:(fc[i-1]+fc[i])/2;这里ma2[i]是从前面往后面计算的,对于这种情况,即如果是前面往后计算,则第1次遇到ma2[i]时,就默认把ma2定义成是序列变量,并把首次计算ma2[i]的位置作为ma2的起始有效位置。如果是递减循环,就不会这样处理。至此我们体会到了循环语句的强大功能了,不过,大家可能还会产生一个疑问,上面的循环语句,只是让一条语句重复计算,如果我们想让多条语句同时进行重复计算,可以吗?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是多少,就要用到二重循环。对于循环中要执行的语句,如果重复太多,也可以使用多重循环来简化。以二重循环为例,大致结构如下:fori=n1ton2dobegin语句;…??forj=m1ton2do??begin??????语句;??????…??end;??语句;??…end;不举具体的例子了,留在练习中,让大家练习。小结:1、今天学习了FOR循环,包括递增循环、递减循环,其中包括序列变量的概念2、学习了设置序列变量下界的语句,即setlbound()函数。3、讲学习了复合语句begin…end;4、初步了解了多重循环下面给若干思考与练习:思考1:循环语句,就是让某条语句循环执行若干次,每循环一次,循环变量就递增一次。这种说法对吗?思考2:循环语句,就是让某条语句循环执行若干次,循环变量总是从1开始,直到对应最后1根K线的位置。这种说法对吗?思考3:递增循环和递减循环的区别是什么?思考4:什么是复合语句,由何处开始,到何处结束?练习1:计算2日平均成交量,请用循环语句写出公式代码。练习2:计算5日平均收盘价,请用循环语句写出公式代码。练习3:计算20日平均收盘价,请用循环语句写出公式代码。练习4:有人写了下面一段代码,你能说出结果是什么吗?Fc:=close;A:=setlbound(fc,datacount/2);Fc;练习5:读懂下面这段代码,用基本函数来写,相当是什么代码?这段代码可以简化吗?Hh:=high;Fori=2todatacountdoBegin??Hh[i]:=max(Hh[i-1],Hh[i]);End;Hh;练习6:LLV(LOW,0);意思是求出上市以来的最低价,请用循环语句写出相同的代码来替换这行代码。练习7:下面代码,可以用循环语句来写吗?a:=(3c+l+o+h)/6;b:(20a+19ref(a,1)+18ref(a,2)+17ref(a,3)+16ref(a,4)+15ref(a,5)+14ref(a,6)+13ref(a,7)+12ref(a,8)+11ref(a,9)+10ref(a,10)+9ref(a,11)+8ref(a,12)+7ref(a,13)+6ref(a,14)+5ref(a,15)+4ref(a,16)+3ref(a,17)+2ref(a,18)+ref(a,19))/210;d:ma(b,m);





条件(判断)语句

条件语句的语法如下:??引用:IF条件语句语法:IFcondTHENexpr1ELSEexpr2如果cond条件成立,则执行语句expr1,否则执行expr2语句。说明:1、在条件判断比较简单的情况下,ELSEexpr2子句可以省略。2、条件cond必须是单值变量,不能为序列变量。条件语句的语法比较简单,但使用时却容易出错,下面举若干示例。例1:修改成交量公式VOL,当流通盘不为零且当前周期为日以上周期时,显示换手率,代码参考如下(仿此,大家绕过指标模组,可以自行设计,“绑定”到周期、券种等的公式)??源码:[复制到剪贴板]??VOL,VOLSTICK;MA1:MA(VOL,M1);MA2:MA(VOL,M2);MA3:MA(VOL,M3);ifcapital>0andDATATYPE>=6then??换手率:vol/capital;//日以上周期及非指数个股,显示换手率当切换到60分钟及以下周期,或者切换到大盘(此时流通盘=0),会发现“换手率”指标线、名称及数值都不显示。以上是较简单的情况,没有使用ELSEexpr2子句。上面代码稍加改进,使用复合语句,使之适用于任意周期:例2,修改成交量公式,流通盘不为0时,显示换手率(60分钟及以下周期,计算当日最新的换手率),代码参考如下:??源码:[复制到剪贴板]??VOL,VOLSTICK;MA1:MA(VOL,M1);MA2:MA(VOL,M2);MA3:MA(VOL,M3);IFCAPITAL>0then//如果换手率>0,则??IFDATATYPE>=6then//如果周期为日及以上的较长周期,则??b:=VOL/CAPITAL100??else//否则??begin//复合语句开始,即以下3条语句,视为1条语句,end表示复合语句结束??tj:=DAY>REF(DAY,1)orBARSSINCE(CLOSE)=0;??ts:=BARSLAST(tj)+1;??b:=SUM(VOL,ts)/CAPITAL100;??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);{参数定义}IFn>0thenMA1:MA(CLOSE,P1);{如果n>=1则输出ma1指标线}IFn>1thenMA2:MA(CLOSE,P2);{如果n>=2则输出ma1指标线}IFn>2thenMA3:MA(CLOSE,P3);{如果n>=3则输出ma1指标线}IFn>3thenMA4:MA(CLOSE,P4);{如果n>=4则输出ma1指标线}在使用条件语句“IFcondTHEN”中,cond不能使用序列变量,这是最容易出错的地方,比如:??源码:[复制到剪贴板]??{下面的代码是错误的}fc:=close;fo:=open;iffc>fothen??//这里的fc、fo是序列变量,因此是错误的语法??xx:=1else??xx:=0;这里,iffc>fothen这种写法的本意是,“如果收盘价大于开盘价则”,是针对序列变量的每个数据(相当于数组的每个元素),在飞狐中,正确的写法应该是这样的:??源码:[复制到剪贴板]??//如果xx是单值变量,则代码参考如下fc:=close;fo:=open;fori=1todatacountdo//从第1根K线的位置,循环到最后1根K线的位置??iffc[i]>fo[i]then??//这里,fc[i]、fo[i]代表某一天的收盘、开盘价,是单值变量??xx:=1??else??xx:=0;y:xx;{以上代码,对单值变量xx有影响的部分仅是最后1根K线,因此上面的代码大多都进行了无效的计算。优化后的代码如下:}fc:=close;fo:=open;iffc[datacount]>fo[datacount]then??xx:=1else??xx:=0;y:xx;??源码:[复制到剪贴板]??//如果xx是序列变量,则代码参考如下fc:=close;fo:=open;fori=1todatacountdo??iffc[i]>fo[i]then??xx[i]:=1??//请注意这里跟上面代码的不同??else??xx[i]:=0;y:xx;练习:1、如果是日以下的分钟周期,则显示“30周期均价线”,否则显示“60周期均价线”,请设计代码。2、如果是日以下的分钟周期,则显示“30周期均价线”,否则如果是日周期则显示“60周期均价线”,比日更长的周期则显示“10周期均价线”请设计代码。3、以下代码正确吗?为什么?请改成正确的代码。??源码:[复制到剪贴板]??input:long(26,20,100),short(12,5,40),m(9,2,60);diff:ema(close,short)-ema(close,long);dea??:ema(diff,m);macd:2(diff-dea),colorstick;ifdiff>deathen??x:=1else??x:=0;y:x;



















国内外股票期货历史数据下载:http:/gpqh.net.cn



国内外股票期货历史数据下载:http://gpqh.net.cn







献花(0)
+1
(本文系hsy1775首藏)