海风机构研究报告会员

海风宏新内参合订会员

巴 菲 特:推荐3只暴涨股

即将拉升暴涨黑马已暴光

↑论坛黄金广告位招租↑

寻找炒股高手,提供融资

论坛版主招募中......

天天公开爆涨牛股请点击

3只暴涨牛股不看别后悔

提前布局3只暴涨黑马

扬百万:推荐3只新股!

专家推荐:今日暴涨牛股

最专业的股票理财网站

发新话题
打印

指标编制专用知识集

指标编制专用知识集

学编飞狐公式——F10资料查找



一、常用的函数——大多属于字符串函数类:

1.主要函数:2个

(1)F10FIND(S,N)——F10资料查找

将从当前股票的F10资料的第N个字符开始查找字符串S,返回找到的位置,返回-1表示未找到

(2)F10TEXT(N,M)——F10资料子字符串

将得到当前股票的F10资料中从第N个字符开使的M个字节长的字符串,M=0表示一直取到行尾

2.辅助函数:

(1)字符串截取:

①STRLEFT(STR,N)——字符串的左部,返回字符串STR的左边N个字符
②STRMID(STR,N,M)——字符串的中部,返回字符串STR的第N个字符开始的长度为M个字符的字符串,M为0则取到末尾
③STRRIGHT(STR,N)——字符串的右部,返回字符串STR的右边N个字符
④LTRIM(STR)——除去开始空格
⑤RTRIM(STR)——除去尾部空格

(2)字符串转换:

①STRTONUM(STR)——字符串转化为数字,将STR转化为数字
②NUMTOSTR(N,M)——数字转化为字符串,将N转化为字符串返回,精确到小数点后M位

3.显示函数:

(1)绘图函数类:
①DRAWTEXT(COND,PRICE,TEXT)——在图形上显示文字,当COND条件满足时,在PRICE位置书写文字TEXT,可用'\n'换行,可ALIGN0-5定义对齐方式。

②DRAWNUMBER(COND,PRICE,NUMBER,PRECISION)——在图形上显示数字,当COND条件满足时,在PRICE位置书写数字NUMBER(可以为常数或数组序列),PRECISION为小数显示位数(取值范围0-7),可ALIGN0-5定义对齐方式。

(2)解盘函数类:也是显示文字与显示数字两种。

二、公式的编写:

    由于此类公式是查找F10的资料,因此随着F10资料提供者的不同及其格式的改变,都会影响公式的使用,在编写中需要我们自己逐步进行查找、调试。

1.首先要根据自己所使用F10资料及准备查找的对象进行。假定是鹏博F10资料,准备制作查找“十大流通股东”的公式(下同):

第一步,打开F10资料,找到其所在位置,将其复制后,在公式中写下:GDW0:F10FIND('【十大流通股东】',200); 这一句的意思是找到【十大流通股东】所在位置;

注意函数中的参数S字符串要用半角字符的单引号括起来(下同),参数N可先预设一个,这里先取200。然后将公式编译保存后,选取一个新股或次新股(因其资料较少位置较为靠前,假定选择002047成霖股份)将指标调出来看一下所显示的数值,如果与前面所设的200相距较大,则在指标显示区点击右键,选中“修改指标公式”,打开公式编辑(下同),把参数调正一下,现在改为30000,这时这一句变成:

GDW0:F10FIND('【十大流通股东】',30000);

然后根据【十大流通股东】与所需资料的位置情况,再写:GDW1:F10FIND('1',GDW0+100); 这里查找的“1”是股东情况的序号,后面的参数GDW0+100是从GDW0向后加上一个估计数,然后再观察一下查找情况,如果没有问题则把第一句的冒号后面加上等号使其成为中间变量,在第二句的尾部加上,LINETHICK使其不显示在图中,然后进行下一步;

第二步,开始查找所需资料,写下:GDT1:=F10TEXT(GDW1,26); ——参数26的确定是数出一行有13个汉字,每个汉字占两个字节的位置。这一句的冒号后面一定要加上等号(因为这时变量中是字符串而非数值),否则会造成“输出数据类型非法”的提示,在用绘图函数写下一句临时语句:DRAWTEXT(SYSPARAM(2)=BARPOS,5,GDT1); 这样再保存后就可以在图中看到所取得的字符串。

第三步,调整所取的字符串:将第二步语句中的GDW1后移3个字节,改成GDT1:=F10TEXT(GDW1+3,26)后点击“应用于图”,可看到修改后的变化,如果仍不合适就再次调正,直到显示正确,至此第一家流通股东选取完毕。然后返回到GDW1下面,加上一行写下:GDW2:F10FIND('2',GDW1+75),LINETHICK; 在GDT1下面写下:GDT2:=F10TEXT(GDW2+3,26); 然后把DRAWTEXT(SYSPARAM(2)=BARPOS,5,GDT1)里面的GDT1改为GDT2,查看第二家股东的选取情况。

如果看到截取的流通股东名称并不完整,需要继续完善,添加语句如下:

W12:=GDW2-GDW1;
IF W12>120 THEN BEGIN
   W:=F10FIND('│',GDW1+75),LINETHICK;
   T:=F10TEXT(W+2,26);
   GDT1:=RTRIM(GDT1)+LTRIM(T);
END;

这里使用了去除尾部和开始空格的函数,目的是为了使字符串的衔接更加严密。

此时的公式语句为:

GDW0:=F10FIND('【十大流通股东】',30000);
GDW1:F10FIND('1',GDW0+100),LINETHICK;
GDW2:F10FIND('2',GDW1+75),LINETHICK;
W1:=GDW2-GDW1;
GDT1:='1.'+F10TEXT(GDW1+3,26);
GDT2:=F10TEXT(GDW2+3,26);
IF W12>120 THEN BEGIN
   W:=F10FIND('│',GDW1+75),LINETHICK;
   T:=F10TEXT(W+2,26);
   GDT1:=RTRIM(GDT1)+LTRIM(T);
END;
DRAWTEXT(SYSPARAM(2)=BARPOS,5,T);
DRAWTEXT(SYSPARAM(2)=BARPOS,4,GDT1);
0,COLORBLACK;

这时我们发现,如果十家流通股东的查找全部这样写,实际上有很多重复的语句,怎样简化呢?——可以使用循环语句。

在第一行前面写上VARIABLE:GDW[10]=0,GDT[10]='STR'; 将其中的部分变量设定为数组,前半部分为:

VARIABLE:GDW[10]=0,GDT[10]='STR';
GDW0:=F10FIND('【十大流通股东】',30000);
GDW[1]:=F10FIND('1',GDW0+100),LINETHICK;
GDT[1]:='1.'+F10TEXT(GDW[1]+3,26);
FOR j=2 TO 10 DO BEGIN
   XH:=RTRIM(LTRIM(NUMTOSTR(j,0)));//将j转换为字符的序号
   GDW[j]:=F10FIND(' '+XH+'│',GDW[1]+75);//取字符串所在位置
   IF j<10 THEN GDT[j]:=XH+'.'+F10TEXT(GDW[j]+4,26);//取字符串
END;

后面的补充字符串部分变为:

//补未取全的字符串
FOR i=1 TO 9 DO BEGIN
   WT:=GDW[i+1]-GDW;//计算前后股东位置的差
   IF WT>120 THEN BEGIN//当差超过一定标准时执行下面语句
      TW:=F10FIND('│',GDW+75),LINETHICK;//确定所差字符的起点位置
      T:=F10TEXT(TW+2,26);//截取所差字符
      GDT:=RTRIM(GDT)+LTRIM(T);//前后字符合并
   END;
END;

 并通过逐一改变DRAWTEXT(SYSPARAM(2)=BARPOS,4,GDT[10])显示语句中GDT下标的数值观察结果。

第四步,处理显示问题

将临时的显示语句改变一下,加上你喜欢的颜色标注,调正好显示的位置,一个公式就诞生了。全部公式如下:


{F10十大流通股东}

VARIABLE:GDW[10]=0,GDT[10]='STR';
GDW0:=F10FIND('【十大流通股东】',30000);
IF GDW0<0 THEN EXIT;
GDW[1]:=F10FIND('1',GDW0+100),LINETHICK;
GDT[1]:='1.'+F10TEXT(GDW[1]+3,26);
FOR j=2 TO 10 DO BEGIN
   XH:=RTRIM(LTRIM(NUMTOSTR(j,0)));//将j转换为字符的序号
   GDW[j]:=F10FIND(' '+XH+'│',GDW[1]+75);//取字符串所在位置
   IF j<10 THEN GDT[j]:=XH+'.'+F10TEXT(GDW[j]+4,26);//取字符串
END;
//补未取全的字符串
FOR i=1 TO 9 DO BEGIN
   WT:=GDW[i+1]-GDW;//计算前后股东位置的差
   IF WT>120 THEN BEGIN//当差超过一定标准时执行下面语句
      TW:=F10FIND('│',GDW+75),LINETHICK;//确定所差字符的起点位置
      T:=F10TEXT(TW+2,26);//截取所差字符
      GDT:=RTRIM(GDT)+LTRIM(T);//前后字符合并
   END;
END;
GDT[10]:='10.'+F10TEXT(GDW[10]+5,26);
DRAWTEXT(SYSPARAM(2)+2=BARPOS AND GDW[1]>1,10,GDT[1]),COLOR74AFFF;
DRAWTEXT(SYSPARAM(2)+2=BARPOS AND GDW[2]>1,8,GDT[2]),COLOR74AFFF;
DRAWTEXT(SYSPARAM(2)+2=BARPOS AND GDW[3]>1,6,GDT[3]),COLOR74AFFF;
DRAWTEXT(SYSPARAM(2)+2=BARPOS AND GDW[4]>1,4,GDT[4]),COLOR74AFFF;
DRAWTEXT(SYSPARAM(2)+2=BARPOS AND GDW[5]>1,2,GDT[5]),COLOR74AFFF;
DRAWTEXT(SYSPARAM(2)+55=BARPOS AND GDW[6]>1,10,GDT[6]),COLOR74AFFF;
DRAWTEXT(SYSPARAM(2)+55=BARPOS AND GDW[7]>1,8,GDT[7]),COLOR74AFFF;
DRAWTEXT(SYSPARAM(2)+55=BARPOS AND GDW[8]>1,6,GDT[8]),COLOR74AFFF;
DRAWTEXT(SYSPARAM(2)+55=BARPOS AND GDW[9]>1,4,GDT[9]),COLOR74AFFF;
DRAWTEXT(SYSPARAM(2)+55=BARPOS AND GDW[10]>1,2,GDT[10]),COLOR74AFFF;
0,COLORBLACK;




假如你需要将其显示在解盘中,可使用解盘函数:EXPLAIN(GDW[1]>1,GDT[1]),COLOR74AFFF;

你试一试,你也可以随心所欲地编写F10资料查找公式了。

TOP

关于筹码分布的几个有意思的概念



  筹码分布的两个函数:获利盘比率winner(x)=n%;和筹码分布cost(n)=x;互为反函数。
如果从不同的角度来描述,可以更清楚的看出它们的意义。
取X=C 即收盘价(当前价),则:
1、winner(c)=n%; 表达的是以收盘价C卖出,而能获利的最大筹码量为流通盘的N%;
2、反过来也同样成立,即:cost(n)=c; 表达的是:使流通盘的n%的筹码 完全获利的最低价为C;
  基于这样的理解,我们可以得出几个有意思的公式。这些公式对判断底部有一定的帮助。
一、区间集中度 cmj:(winner(c*(1+m%))-winner(c*(1-m%)))*100;
               cmj的含义是:收盘价C附近(上下各m%)的筹码量(%);
               M的取值范围一般为 2~10;

二、获利倍数 cmb:(cost(n)/cost(0)-1)*100;
             cmb的含义是:N%的筹码中的任意一部份,以当前价 卖出时所能得到的最大收益(%);
             N的取值范围一般为10~90;

三、盈亏幅度   ykf:(c/cost(n)-1)*100;
               ykf的含义是N%的筹码中的任意一部份 以 当前价 卖出时的最大盈亏幅度(%);
               N的取值范围一般为5~10;
  
    需要说明的是:筹码分布是一个统计概念,由于市场的千变万化,人们的交易行为不会只受到一种或几种思维方式的支配,因此不可能仅用一两种模式就能完整地描述市场的真实情况。也就是说 其必然存在着局限性。从实际的情况看这种局限性还非常严重。在使用时仅仅只能做为一种参考。。。。。。

[ 本帖最后由 lpfljlzy 于 2006-4-7 19:47 编辑 ]

TOP

未来数据的哲学意味



  首先,我们得确认未来数据是不是存在的.这个问题很有趣,它不是现有中的存在,而是未来的存在.否认它,就象否认明天的你一样.是的,明天的你也可能死翘翘了,但采用未来数据这样的函数的微妙之处是,它是根据你现在的状态来判断明天的你.如果你现在身体状态很好,它不会判断你第二天要死.当然,它和所有的预测一样,对意外不予理会.所以,采用了未来数据的函数其实是用现在的数据对未来做的一个推测.那么,用未来数据做的通道,其实就是表现了现在的一个猜测,表现了这个猜测出来的一种趋势.未来数据恰恰在说明,只有走出来之后的东西才是真实的. 它的哲学意味就在于它既承认现实,又承认由现实所可能(一定要注意,这里强调的是可能!)产生的变化.采用了未来数据的函数 和 普通的,只用已实在存在、已经产生的数据的函数之间的区别是:普通函数不对未来进行推测,而未来数据函数对未来进行推测.它们都有一个共同的基础--就是已经存在的实在数据.比如说一个上市十天的个股的十日均线,它反映的就是十天之和的平均收盘价.而(采用了未来数据的)傅立叶变换呢,则是根据每一天走出来的数据对前一天的推测做出修正的一个新的推测.所以,未来数据函数的意义就在这种推测本身,而不在以前的那些历史.那么,为什么人们都认为它是骗人的东西呢?因为持有这种看法的人是看它的历史,而不是看它的推测.是的.用未来数据函数做出来东西,回过头来看都非常准确.这是因为它对指标线(准确地说,应该是它对自己的原判断)做了修正.这种修正有没有用?非常有用!正是这种修正,使它推测的可靠性增加了.我们想一想,我们对大盘对个股的判断是不是总是一成不变的?是不是要根据每一个新的变化来修正我们的判断?未来数据函数正是这样,它不是一成不变地看待已经发生的历史,而是根据这个历史对它的下一个推测做出修正.我们再把普通函数和这种未来数据函数打个比方:普通函数好比是形式逻辑,未来数据函数则采用的是辨证逻辑,用的是辨证思维.

  所以,未来数据函数,是用其推测作用来帮助我们判断的,而不是用其修正过的历史数据去骗人的.

  由这个认识我们可以发现,在我们的日常思维逻辑中有许多的心理定式,它对我们的心理状态产生了极大的影响,使我们的心理无法保持那种新鲜感.以致很少对一些看似悖于常理的事物做细致的分析,甚至对它们去做感情上的取舍.感情上的取舍会破坏我们对事物的判断力,使我们无法理性地认识事物(当然也包括对股市的认识).

TOP

组合技术分析和相互验证原则



在利用不同的技术指标对证券市场进行分析时,有时也会产生相互矛盾结果。某些技术指标发出卖出信号,但另一些技术指标却发出买入信号;上升的技术形态但股价却下跌,而下降的技术形态但股价却上升。如何才能剔除虚假信号,把握住真正的变化趋势就是组合技术分析和相互验证原则。
  由于指标技术分析与形态技术分析都只是从单一方面对证券市场的状态进行分析,要想全面正确的分析证券市场就必须全方位研究证券市场。因此要将各种技术指标和技术形态组合在一起,利用相互验证的原理,才能对证券市场进行立体全方位分析。
  最基本的组合技术分析可以分成三类:
  1.不同时域技术指标的组合。
  2.不同类型技术指标间的组合。
  3.指标分析与形态分析的组合。

不同时域技术指标的组合

  所有的技术指标均要考虑时间因素,根据选取时间间隔的长短,技术指标分成短期技术指标、中期技术指标、长期技术指标三种。短期技术指标反应最为灵敏,但最容易发出虚假信号,长期技术指标反应最为迟钝,但发出的信号也最为准确。短期技术指标、中期技术指标、长期技术指标三者相结合,大势看长期技术指标,操作看中、短期技术指标。

不同类型技术指标间的组合

  技术分析指标一般分为四大类:趋势类、能量类、摆动类和其他类。
  从重要性来看趋势类指标最重要,能量类指标次之,摆动类指标居第三。
  可以从每类技术指标中各选出一个(或多个)技术指标,将这多个技术指标综合进行分析。根据相互验证原理,在它们同时出现买入(或卖出)信号比仅某一类技术指标出现买入(或卖出)信号时的准确性要高得多。

指标分析与形态分析的组合

  由于指标技术分析与形态技术分析都只是从单一方面对证券市场的状态进行分析,因此要将技术指标和技术形态组合在一起,利用相互验证、相互背离的原则把数量(指标分析)与图形(形态分析)结合一起,综合进行分析。
最重要也最常使用的指标分析与形态分析的组合分析方法就是相互背离,所谓背离就是技术指标和股价趋势的不一致。背离分成顶背离和底背离两种,出现背离现象时,一般是转势信号,而且准确性高。

相互验证和相互背离原则

  所谓相互验证,是指把所有技术信号(形态分析信号和技术指标信号)都进行对照,保证其中大部分技术信号相互吻合,指示的方向共同。
  在形态分析中,相互验证,意味着应当对同一市场的各种图表形态进行分析比较。在某一种图表上的看涨或看跌的形态,应该在其余图表上得到验证,以确保它们的相互一致。
  相互验证原则还要考察分析的结果是否与市场的大方向一致。如果市场总体上处于下降趋势中,那么,对任何个别市场的看涨分析,都需要把它的权重降低。因此,必须明确市场的总体环境到底是牛市、还是熊市。
  相互验证原则还要求在更长的周期图表上(例如周线图和月线图)得到验证。然后,把所有技术指标,例如移动平均线、摆动指数、趋势线、成交量等,也与分析的结果进行验证,以保证结果的一致性。
  总之,分析者关于市场的分析结论所拥有的技术证据越多,则越具信心,正确决策的把握就越大。
  相互背离原则与相互验证原则相反,相互背离原则是指在同一市场的不同图表或技术分析指标之间,其分析结果不能相互吻合的情形。相互背离原则在市场分析中极有价值,是趋势即将反转的较好的先期警讯之一。
  相互验证和相互背离原则具有极为重要的实际意义。

技术分析新发展

  1.对技术指标曲线的形态分析。与K线相同,技术指标曲线同样有各种形态,而且其指标的形态往往比K线的形态更加清晰。尤其是现代数学工具模糊数学和数值模拟的引入,使计算机实现形态分析成为可能,从而使其研判更加客观、可靠。

  2.在指标参数的选取方面,主张不同周期采用不同参数组合分别研判买卖信号。通过实证研究,人们发现如果始终运用同一参数组合来分别研判买卖信号,会使买卖信号的准确度有所不同,因而萌发了根据不同研判目的运用不同参数的想法。如吉拉?艾波(Gerald Appel)在对MACD指标进行研究时建议研判买入采用"8/17/9天EMA"的参数组合,但卖出信号采用"12/25/9天EMA"。这种参数的取定方法比较新颖的。通常人们认为市场上涨过程比较缓慢,而下跌过程比较迅速,所以很自然的认为卖出信号应取较短周期。但经过吉拉?艾波对美国股市近百年数据的实际测算得到的实际结果却与人们的这种推理背道而驰。

  3.对技术指标曲线进行拟合处理。用拟合线的趋势来预测技术指标曲线的走势,从而突破了就由技术中无法预测指标未来走势的屏障。

  4.引入全新的数学工具,从全新的视角对股市走势加以分析。例如,数学对于混沌和分形的研究。我们通常进行的指标分析的数学模型有很多都是建立在传统概率统计理论基础上的。它们假设各个事件都是独立事件。但是自然界中的实际事件却多数是非独立的,例如,今年某地区洪水泛滥,则该地区的地下水水位和日平均蒸发量均会上升,下一年洪水爆发的概率就相应增大。股市也同样如此。一段时间某只股票上涨,股东的平均成本就增加,人们对股票本身的心理定位也同时受到影响而上升。无论是自然界中还是股市,凭经验我们都知道现象之间是相互影响的,即事物之间是存在联系的。但对于其相关程度我们却缺乏精确的描述。正是针对这种现象,分形科学的Hurst指数被运用于股市的研判之中,来刻画本期趋势与未来一个时期趋势的相关程度:序列相关程度高,则说明趋势在一定程度上会延续,因而此时适于应用趋势类指标进行研判;序列相关程度低,则说明趋势可能发生变化,此时适于应用摆动类指标进行研判。

TOP

飞狐公式系统,循环、分支语句入门



序:
  飞狐内嵌的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];

TOP

再看一例“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:画一条从上市第1天开始的水平直线,其高度等于当前股票的历史最高价。
  练习4:画一条从上市第1天开始的水平直线,其高度位于当前股票历史最高、最低价的一半位置。
  练习5:当前股票,2003年最高价是多少?首次出现该最高价的日期是哪天?

-----------------------------

公式及注释如下,仿照试试成交量的情况:

tj:=year=2003; //定义一个序列变量,使之当年份为2003时返回1,否则返回0
cje:=amount*tj; //定义并计算序列变量cje,当年份为2003时返回成交额,否则返回0
cjeh:=hhv(cje,0);  //定义序列变量,返回上市以来的最高cje
最高成交额(03):cjeh[datacount];  //最后一天的最高cje,就是2003年的最高成交额


cje03:=if(year=2003,amount,cjeh[datacount]);
//如果为2003年返回成交额,否则返回2003年最高成交额

cjel:=llv(cje03,0);  //历史最低的cje03
最低成交额(03):cjel[datacount];  //最后一天的cje03

-------------------------------

[ 本帖最后由 lpfljlzy 于 2006-4-7 20:00 编辑 ]

TOP

介绍循环语句。


  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:=(fc[i-1]+fc)/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;  //定义序列变量为收盘价
for  i=2  to  datacount  do  ma2 : (fc[i-1]+fc)/2;
//从i=2到i=datacount循环执行ma2 : (fc[i-1]+fc)/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 : (fc[i-1]+fc)/2;

图4


//////////////////////////////////////////////////////

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

[ 本帖最后由 lpfljlzy 于 2006-4-7 19:47 编辑 ]
附件: 您所在的用户组无法下载或查看附件

TOP

现在有输出了,但仔细观察,还有点问题,第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;
for i=datacount downto 2 do ma2:(fc[i-1]+fc)/2;

图6


/////////////////////////////////////////////////////

  这个结果就对了!但大家可能会有疑问了,在前面递增循环中,ma2同样没有事先定义,结果却是正确的,这是为什么?回顾一下前面递增循环的代码:
  fc:=close;  //定义序列变量为收盘价
  for  i=2  to  datacount  do  ma2 : (fc[i-1]+fc)/2;

  这里ma2是从前面往后面计算的,对于这种情况,即如果是前面往后计算,则第1次遇到ma2时,就默认把ma2定义成是序列变量,并把首次计算ma2的位置作为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;  //定义一个临时的单值变量a,保存中间计算结果
    ma2 : a/2;
    end;
  
  这段代码,就是由2行代码组成的复合语句,被循环执行若干次。为了代码容易分辨,我们特别把复合语句中的2行代码,都向右缩了4格,表明这是2行复合语句,是被循环语句所控制的。以前对于这类分层次的语句,都要进行缩格,便于看懂代码,特别是复杂的代码,如果不进行缩格,时间久了,恐怕连自己都很难看懂,大家一开始就要养成好习惯。
  有人会问,书写代码不缩格行吗?不缩格公式会不会出错?答案是,缩格书写代码,仅仅是为了方便看清程序代码的逻辑层次,对公式的运行没有影响。
  有了复合语句,循环的功能就更加强大了,可以轻松实现多重循环,即循环中套循环。在计算N日的平均价时会用到,如果事先不知道N是多少,就要用到二重循环。对于循环中要执行的语句,如果重复太多,也可以使用多重循环来简化。以二重循环为例,大致结构如下:
  for i=n1 to n2 do
  begin
    语句;
    …
      for j=m1 to n2 do
      begin
          语句;
          …
      end;
      语句;
      …
  end;
  不举具体的例子了,留在练习中,让大家练习。
  小结:
1、 今天学习了FOR循环,包括递增循环、递减循环,其中包括序列变量的概念
2、 学习了设置序列变量下界的语句,即setlbound()函数。
3、 讲学习了复合语句begin…end;
4、 初步了解了多重循环

[ 本帖最后由 lpfljlzy 于 2006-4-7 19:52 编辑 ]
附件: 您所在的用户组无法下载或查看附件

TOP

介绍条件(判断)语句。


  条件语句的语法如下:


QUOTE:
IF条件语句
语法:IF cond THEN expr1 ELSE expr2
如果 cond 条件成立,则执行语句 expr1,否则执行 expr2 语句。
说明:
  1、在条件判断比较简单的情况下,ELSE expr2 子句可以省略。
  2、条件 cond 必须是单值变量,不能为序列变量。
  条件语句的语法比较简单,但使用时却容易出错,下面举若干示例。

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


CODE:[Copy to clipboard]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分钟及以下周期,计算当日最新的换手率),代码参考如下:


CODE:[Copy to clipboard]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,控制调整均线数,代码参考如下:


CODE:[Copy to clipboard]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 不能使用序列变量,这是最容易出错的地方,比如:


CODE:[Copy to clipboard]{下面的代码是错误的}
fc:=close;
fo:=open;
if fc>fo then  //这里的fc、fo是序列变量,因此是错误的语法
  xx:=1
else
  xx:=0;
  这里,if fc>fo then 这种写法的本意是,“如果收盘价大于开盘价则”,是针对序列变量的每个数据(相当于数组的每个元素),在飞狐中,正确的写法应该是这样的:


CODE:[Copy to clipboard]//如果xx是单值变量,则代码参考如下
fc:=close;
fo:=open;
for i=1 to datacount do //从第1根K线的位置,循环到最后1根K线的位置
  if fc>fo then  //这里,fc、fo代表某一天的收盘、开盘价,是单值变量
    xx:=1
  else
    xx:=0;
y:xx;

{以上代码,对单值变量xx有影响的部分仅是最后1根K线,因此上面的代码大多都进行了无效的计算。优化后的代码如下:}
fc:=close;
fo:=open;
if fc[datacount]>fo[datacount] then
  xx:=1
else
  xx:=0;
y:xx;



CODE:[Copy to clipboard]//如果xx是序列变量,则代码参考如下
fc:=close;
fo:=open;
for i=1 to datacount do
  if fc>fo then
    xx:=1  //请注意这里跟上面代码的不同
  else
    xx:=0;
y:xx;
练习:
1、如果是日以下的分钟周期,则显示“30周期均价线”,否则显示“60周期均价线”,请设计代码。
2、如果是日以下的分钟周期,则显示“30周期均价线”,否则如果是日周期则显示“60周期均价线”,比日更长的周期则显示“10周期均价线”请设计代码。
3、以下代码正确吗?为什么?请改成正确的代码。


CODE:[Copy to clipboard]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;
if diff>dea then
  x:=1
else
  x:=0;
y:x;

TOP

飞狐dll文件数学例子



以下全部精采内容:
----------------------------------------------------------------------------------------------
飞狐dll文件数学例子

这是飞狐接口的标准C++引入档,Foxfunc.h,可在飞博廷站下载
这几行需修改MYMACLOSE, SMOOTH, MYBBI是宣告外部DLL函数

__declspec(dllexport) int WINAPI MYMACLOSE(CALCINFO* pData);
__declspec(dllexport) int WINAPI SMOOTH(CALCINFO* pData);
__declspec(dllexport) int WINAPI MYBBI(CALCINFO* pData);

-------------------------------------------------------------------------------------------------
公式开始:
-------------------------------------------------------------------------------------------------
#ifndef __FOXFUNC_H_INCLUDE
#define __FOXFUNC_H_INCLUDE

/*
///////////////////////////////////////////////////////////////////////////
飞狐交易师“C语言接口”扩展程序调用接口规范V3.0
1.本规范适用于飞狐交易师V3.x公式系统.
2.扩展函数用于实现系统函数不能实现的特殊算法.
3.扩展函数用windows 32位动态连接库实现,建议使用Microsoft Visual C++编程.
4.调用时在公式编辑器中写"动态库名称@函数名称"(参数表)即可,例如下面函数可以写为"FOXFUNC@MYMACLOSE"(5)
5.动态连接库名称和函数名称可以自己定义.
6.使用时必须将动态库拷贝到飞狐交易师安装目录下的FmlDLL子目录下使用.
*/

#ifdef __cplusplus
extern "C"
{
#endif //__cplusplus

///////////////////////////////////////////////////////////////////////////
//分析周期
enum DATA_TYPE
{
        TICK_DATA=2,                                //分笔成交
        MIN1_DATA,                                        //1分钟线
        MIN5_DATA,                                        //5分钟线                                       
        MIN15_DATA,                                        //15分钟线
        MIN30_DATA,                                        //30分钟线
        MIN60_DATA,                                        //60分钟线
        DAY_DATA,                                        //日线
        WEEK_DATA,                                        //周线
        MONTH_DATA,                                        //月线
        YEAR_DATA,                                        //年线
        MULTIDAY_DATA,                                //多日线
        MULTIMIN_DATA                                //多分钟线
};

///////////////////////////////////////////////////////////////////////////


//基本数据

typedef struct tagSTKDATA        
{
        time_t        m_time;                        //时间,UCT
        float        m_fOpen;                //开盘
        float        m_fHigh;                //最高
        float        m_fLow;                        //最低
        float        m_fClose;                //收盘
        float        m_fVolume;                //成交量
        float        m_fAmount;                //成交额
        WORD        m_wAdvance;                //上涨家数        仅大盘有效
        WORD        m_wDecline;                //下跌家数        仅大盘有效
} STKDATA;

////////////////////////////////////////////////////////////////////////////
//扩展数据,用于描述分笔成交数据的买卖盘

typedef union tagSTKDATAEx
{
        struct
        {
                float m_fBuyPrice[3];                //买1--买3价
                float m_fBuyVol[3];                        //买1--买3量
                float m_fSellPrice[3];                //卖1--卖3价        
                float m_fSellVol[3];                //卖1--卖3量
        };
        float m_fDataEx[12];
} STKDATAEx;

////////////////////////////////////////////////////////////////////////////
//除权数据

typedef struct tagSPLITDATA        
{
        time_t        m_time;                        //时间,UCT
        float        m_fHg;                        //红股
        float        m_fPg;                        //配股
        float        m_fPgj;                        //配股价
        float        m_fHl;                        //红利
} SPLITDATA;


/////////////////////////////////////////////////////////////////////////////
/*财务数据顺序(m_pfFinData内容)

        序号        内容

        0        总股本(万股),
        1        国家股,
        2        发起人法人股,
        3        法人股,
        4        B股,
        5        H股,
        6        流通A股,
        7        职工股,
        8        A2转配股,
        9        总资产(千元),
        10        流动资产,
        11        固定资产,
        12        无形资产,
        13        长期投资,
        14        流动负债,
        15        长期负债,
        16        资本公积金,
        17        每股公积金,
        18        股东权益,
        19        主营收入,
        20        主营利润,
        21        其他利润,
        22        营业利润,
        23        投资收益,
        24        补贴收入,
        25        营业外收支,
        26        上年损益调整,
        27        利润总额,
        28        税后利润,
        29        净利润,
        30        未分配利润,
        31        每股未分配,
        32        每股收益,
        33        每股净资产,
        34        调整每股净资,
        35        股东权益比,
        36        净资收益率
*/

/////////////////////////////////////////////////////////////
//调用参数项结构
typedef struct tagCALCPARAM
{
        union
        {
                const float*        m_pfParam;                                //序列参数,指向一个浮点型数组        
                const float                m_fParam;                                //数值参数        
        };
        const int                        m_nParamStart;                        //序列参数有效起始位置
}CALCPARAM;


/////////////////////////////////////////////////////////////////////////////
//调用接口信息数据结构
typedef struct tagCALCINFO
{
        const DWORD                        m_dwSize;                                //结构大小
        const DWORD                        m_dwVersion;                        //调用软件版本(V2.10 : 0x210)
        const DWORD                        m_dwSerial;                                //调用软件序列号
        const char*                        m_strStkLabel;                        //股票代码
        const BOOL                        m_bIndex;                                //大盘

        const int                        m_nNumData;                                //数据数量(pData,pDataEx,pResultBuf数据数量)
        const STKDATA*                m_pData;                                //常规数据,注意:当m_nNumData==0时可能为 NULL
        const STKDATAEx*        m_pDataEx;                                //扩展数据,分笔成交买卖盘,注意:可能为 NULL

        const int                        m_nParam1Start;                        //参数1有效起始位置
        const float*                m_pfParam1;                                //调用参数1        
        const float*                m_pfParam2;                                //调用参数2
        const float*                m_pfParam3;                                //调用参数3
        const float*                m_pfParam4;                                //调用参数3

        float*                                m_pResultBuf;                        //结果缓冲区
        const DWORD                        m_dataType;                                //数据类型
        const float*                m_pfFinData;                        //财务数据

//以上与分析家兼容,所以沿用其结构和名称

//以下为飞狐交易师扩展

        const DWORD                        m_dwReserved;                        // 保留

        const int                        m_nNumParam;                        // 调用参数数量
        const CALCPARAM*        m_pCalcParam;                        // 调用参数数组

        const DWORD                        m_dwReservedEx[4];                // 保留

        char*                                m_strStkName;                        //股票名称

        SPLITDATA*                        m_pSplitData;                        //除权数据
        int                                        m_nNumSplitData;                //除权次数

} CALCINFO;

/*
注1: (与分析家兼容)
        1.函数调用参数由m_pfParam1--m_pfParam4带入,若为NULL则表示该参数无效.
        2.当一个参数无效时,则其后的所有参数均无效.
                如:m_pfParam2为NULL,则m_pfParam3,m_pfParam4一定为NULL.
        3.参数1可以是常数参数或序列数参数,其余参数只能为常数参数.
        4.若m_nParam1Start<0, 则参数1为常数参数,参数等于*m_pfParam1;
        5.若m_nParam1Start>=0,则参数1为序列数参数,m_pfParam1指向一个浮点型数组,
                数组大小为m_nNumData,数据有效范围为 m_nParam1Start 至 m_nNumData-1.
                在时间上m_pData[x] 与 m_pfParam1[x]是一致的

注2: (飞狐交易师扩展)
        1.该扩展结构使调用参数在技术上可以是无限数目的,且每个参数都可为数值或序列,由公式中实际的调用参数决定。
        2.CALCPARAM结构用于带入参数信息和实际数据,m_pCalcParam数组大小为m_nNumParam,数据有效范围为 0 至 m_nNumParam-1.
        3.按参数的顺序,m_pCalcParam[0]为第一个参数的数据,m_pCalcParam[1]为第二个参数的数据...,为了保持兼容,原m_nParam1Start、m_pfParam1等5个属性依然有赋值。
        4.若 i位置的参数为数值,取用m_pCalcParam.m_fParam.
        5.若 i位置的参数为序列,取用m_pCalcParam.m_pfParam,数组大小为m_nNumData,数据有效范围为m_pCalcParam.m_nParamStart 至 m_nNumData-1. 若m_pCalcParam.m_nParamStart<0, 则此数组中无有效数据。
        6.由于可以调用多个序列,许多序列的计算可以先在公式中进行,然后作为调用的参数即可。
        7.经此扩展,对分析家的DLL依然可以调用、兼容。

*/


///////////////////////////////////////////////////////////////////////////////////
/* 函数输出

__declspec(dllexport) int xxxxxxxx(CALCINFO* pData);

1.函数名称需全部大写.
2.函数必须以上述形式声明,请用实际函数名称替代xxxxxxxx;
        对于C++程序还需包括在 extern "C" {   } 括号中.
3.函数计算结果用pData->m_pResultBuf带回.
4.函数返回-1表示错误或全部数据无效,否则返回第一个有效值位置,即:
        m_pResultBuf[返回值] -- m_pResultBuf[m_nNumData-1]间为有效值.
5.函数名称长度不能超过15字节,动态连接库文件名不能超过9字节(不包括扩展名),动态库名称不能叫SYSTEM,EXPLORER

*/

//示例函数,使用时用实际名称替换
__declspec(dllexport) int WINAPI MYMACLOSE(CALCINFO* pData);
__declspec(dllexport) int WINAPI SMOOTH(CALCINFO* pData);
__declspec(dllexport) int WINAPI MYBBI(CALCINFO* pData);

#ifdef __cplusplus
}
#endif //__cplusplus


#endif //__FOXFUNC_H_INCLUDE

-------------------------------------------------------------------------------------------------
/公式結束
-------------------------------------------------------------------------------------------------

TOP

编写公式的基础(飞弧用)



公式平台--C语言基础  (李济安)

    公式平台包含一个C语言编译器,可以通用函数与C语言混写,在创作公式的时候,可以在一个公式中对多个周期的数据、其他股票的数据同时进行操作,具有丰富、全面的内部函数和操盘指令。 所以本软件的公式平台可以支持非常复杂的公式创造,任何想法、思想都可以实现。 希望大家应用C语言这种目前最为成熟强大的编程语言,进入技术分析的高境界。

    变量及常量

    创作一个公式,也就是将我们的想法表达出来。在这个过程中,我们免不了要记录一些状态,记录这些状态,我们就需要"变量"这个概念。比如,我们要求近十天的收盘价的平均值,需要10个数相加,这时候,我们需要一个计数器,这个计数器,我们就可以用一个整数变量来表示;又需要一个存放累加和的地方,因为累加和可能存在小数,我们就不能再用整形变量表示,就要使用浮点数来表示了。这个过程我们可以表达如下:

float sum = 0.0; //申请一个浮点变量,并赋初值0
for(int i=0; i < 10; i++) //循环10次,i就是计数器, 在这里被表示成一个整形变量。
{
if(i > DataLen) //数据不够了,终止
break;
sum += 收盘价[DataLen-i];
}
float ret = 0; //存放结果的浮点变量,赋初值0
if(i>0)
ret = sum/i;

    这个过程现在看不懂,没有关系,在这里,我们只要了解到变量的意义就可以了。每声明一个变量,计算机就会为这个变量申请一个存储空间。更具变量的类型不同,计算机将为他申请不同的空间,并使用不同的存储方法。我们可以总结说:变量就是在计算的过程中用来存放我们一些状态和结果的地方。那么,有哪些变量的类型呢?我们常见的有以下几种:

    1.整形:只能记整数,比如-1、-100、0、1、100等。这样的变量计算机将申请4字节(计算机最基本的存储单位)空间,不能表示小数,数的表示范围可以从-2147483648~2147483647。表达方式:int. 比如我们需要声明一个叫做A 的整形变量,可以用下面方式表达:
int A;

    最后的':'代表这个声明的结束,在C语言中,';'总是代表一个语句的结束。如果我们希望一下声明多个整形变量,我们在每个变量之间需要用','隔开,比如,我们希望声明两个分别加A和B的整形变量,可以用下面方式表达:
int A,B;

注意,','以及';'不能是中文的。

    很多时候,我们希望在变量声明的时候付给他初值,这时候,我们可以这样来表达:
int A =1,B=100;

    2.浮点型:可以记小数,比如-1.5、-100.123、0.001、1.29、100.667等。这样的变量计算机将申请4字节(计算机最基本的存储单位)空间,数的表示范围可以从3.4x10-38E~3.4x10+38E。表达方式:float. 如果我们需要声明一个叫做A 的整形变量,可以用下面方式表达:
float A;

    浮点型在运算过程中和整形相比较慢,但是计数的范围却大大增大了。

    数据类型还有很多种,我们列表如下:

名称 描述 所占空间(BYTE) 范围 特点
整形 int 4 -2147483648~2147483647 整数,有符号(可正可负)
浮点型 float 4 3.4x10-38E~3.4x10+38E 可记小数,有符号(可正可负)
双精度浮点型 double 8 小数点后位数更长,有符号(可正可负)
布尔类型 Bool 4 0-1 只有TRUE(1)和FALSE(0)两个值
字符型 char 1 -128~127 整数,有符号(可正可负)
无符号字符型 byte 1 0-255 整数,无符号(无负数)
短整形 short 2 -32768~32767 整数,有符号(可正可负)
无符号短整形 word 2 0-65535 整数,无符号(无负数)
无符号整形 dword 4 0~4294967295 整数,无符号(无负数)


    还有很多数据类型, 鉴于简明的需要,不再赘述.

    所谓常量,也就是不变的量.这些量和变量一样可以参与运算.比如0、5.5等都叫做常量。常量也有数据类型,比如布尔常量我们就两个: TRUE 或者 FALSE, 前者代表'真',后者代表'假'.不同的常量付给相同类型的变量,比如:
BOOL A = TRUE; //将TRUE付给变量A;

    常量的表达方式很多,我们简单举例说明两种。

    十进制常量, 可以用我们的常用习惯苏书写,比如0.5, 0.8等等,这种常量可以非给int,float,等类型。

    十六进制常量,需要在数字前面添加0x,比如0xff00ff, 这在我们平台中表达颜色的时候有用,比如 两点棒线扩展(V1,V2,C,C1,C2,W,F) 这个函数需要我们制定两个颜色,而颜色需要一个三字节的16进制的常量表示,0xAABBCC 的AA,BB,CC分别代表红色的亮度、绿色的亮度、蓝色的亮度。
运算及赋值

    我们创造公式,离不开运算。比如 a = b*c+20/d 就表示了将b和c的乘积加上20除以d所得到的商,赋值给变量a.其中*、+、/都是运算符号,告诉计算机进行什么操作。

    运算符非常主要分为三大类: 算术运算符, 关系运算符与逻辑运算符, 按位运算符。除此之外, 还有一些用于完成特殊任务的运算符。下面分别进行介绍其中的三类。

    1.算术运算符

操作符 作用
+ 加, 一目取正
- 减, 一目取负
* 乘
/ 除
% 取模
-- 减1
++ 加1


    一目和二目操作
一目操作是指对一个操作数进行操作。例如: -a是对a进行一目负操作。
二目操作(或多目操作)是指两个操作数(或多个操作数)进行操作。
加、减、乘、除、取模的运算容易理解。需要注意的是除法和取模运算。
例如:
15/2 是15除以2商的整数部分7
15%2 是15除以2的余数部分1
对于取模运算符"%", 不能用于浮点数。

    增量运算
有两个很有用的运算符,那就是增1和减1运算符"++"和"--", 运算符"++"是操作数加1, 而"--" 则是操作数减1。
例如:
x=x+1 可写成x++, 或++x
x=x-1 可写成x--, 或--x
x++(x--)与++x(--x)在上例中没有什么区别, 但x=m++和x=++m却有很大差别。
x=m++ 表示将m的值赋给x后, m加1。
x=++m 表示m先加1后, 再将新值赋给x。

    2.逻辑运算符
逻辑运算符是指用形式逻辑原则来建立数值间关系的符号。

    操作符 作用
&& 逻辑与
|| 逻辑或
! 逻辑非


    3.关系运算符
关系运算符是比较两个操作数大小的符号。

操作符 作用
> 大于
> = 大于等于
< 小于
< = 小于等于
== 等于
!= 小不等于

    关系运算符和逻辑运算符的关键是真(true)和假(false)的概念。true可以是不为0的任何值, 而false则为0。 使用关系运算符和逻辑运算符表达式时, 若表达式为真(即true)则返回1, 否则, 表达式为假(即false), 则返回0。
例如:
100>99 返回1
10>(2+10) 返回0
!1&&0 返加0
    对上例中表达式!1&&0, 先求!1和先求1&&0将会等于出不同的结果, 那么何者优先呢? 这在Turbo C中是有规定的。 有关运算符的优先级本节后面将会讲到。

    联合操作
C中有一特殊的简写方式, 它用来简化一种赋值语句, 适用于所有的双目运算符。其一般形式为:
< 变量 >=< 变量 >< 操作数 >< 表达式 >
相当于
< 变量 >< 操作数 >=< 表达式 >
例如:
a=a+b 可写成 a+=b
a=a&b 可写成 a&=b
a=a/(b-c) 可写成 a/=b-c

    C运算符的优先级
C规定了运算符的优先次序即优先级。 当一个表达式中有多个运算符参加运算时, 将按下表所规定的优先级进行运算。表中优先级从上往下逐渐降低, 同一行优先级相同。
例如:
表达式 10>4&&!(100 < 99)||3 < =5 的值为1
表达式 10>4&&!(100 < 99)&&3 < =5 的值为0

    表达式 优先级 从高到低排列
()(小括号) [](数组下标) .(结构成员) ->(指针型结构成员) 最高
!(逻辑非) .(位取反) -(负号) ++(加1) --(减1) &(变量地址) ↑
*(指针所指内容) type(函数说明) sizeof(长度计算) │
*(乘) /(除) %(取模) │
+(加) -(减) │
<<(位左移) >>(位右移) │
<(小于) <=(小于等于) >(大于) >=(大于等于) │
==(等于) !=(不等于) │
&(位与) │
^(位异或) │
|(位或) │
&&(逻辑与) │
||(逻辑或) │
表达式) │
= += -=(联合操作) │
,(逗号运算符) 最低


    常用语句语法

    平台中的C语法可以简单概括为以下几个特点:

代码一般用小写字母书写;
大多数语句结尾必须要用";"作为终止符, 否则C不认为该语句结束;
一个较完整的程序大致包括:变量定义、控制流程语句语句等;
注释部分包含在"/*"和"*/"之间, 单行的注释可以用//开始.
变量在使用之前必须先定义其数据类型,未经定义的变量被当成浮点数组使用。定义变量类型可在任意位置,一旦定义,后面的语句都可使用.
大、小写字母是有区别的, 相同字母的大、小写代表不同的变量。
书写格式非常灵活, 没有严格限制。
条件语句
条件语句的一般形式为:
if(表达式)
语句1;
else
语句2;

    上述结构表示: 如果表达式的值为非0(TURE)即真, 则执行语句1, 执行完语句1从语句2后开始继续向下执行; 如果表达式的值为0(FALSE)即假, 则跳过语句1而执行语句2。所谓表达式是指关系表达式和逻辑表达式的结合式, 关于表达式前面已作过介绍, 这是不再重复。

    注意:

    1. 条件执行语句中"else 语句2;"部分是选择项, 可以缺省, 此时条件语句变成:
if(表达式) 语句1;
表示若表达式的值为非0则执行语句1 , 否则跳过语句1继续执行。

    2. 如果语句1或语句2有多于一条语句要执行时, 必须使用"{"和"}" 把这些语句包括在其中, 此时条件语句形式为:
if(表达式)
{
语句体1;
}
else
{
语句体2;
}

    3. 条件语句可以嵌套, 也就是语句体中还可以包含条件语句。
    例如:
if(x>20||x < -10)

int a;
if(y < =100&&y >x)
a = 1;
else
a = 0;


    4. 可用阶梯式if-else-if结构。
阶梯式结构的一般形式为:
if(表达式1)
语句1;
else if(表达式2)
语句2;
else if(表达式3)
语句3;
.
.
.
else
语句n;

    这种结构是从上到下逐个对条件进行判断, 一旦发现条件满点足就执行与它 有关的语句, 并跳过其它剩余阶梯; 若没有一个条件满足, 则执行最后一个else 语句n。最后这个else常起着"缺省条件"的作用。

    同样, 如果每一个条件中有多于一条语句要执行时, 必须使用"{"和"}"把这些语句包括在其中。

    循环语句
C提供三种基本的循环语句: for语句、while语句和do-while语句。

    1.for循环
for循环是开界的。它的一般形式为:
for(< 初始化 >; < 条件表过式 >; < 增量 >)
语句;
初始化总是一个赋值语句, 它用来给循环控制变量赋初值; 条件表达式是一个关系表达式, 它决定什么时候退出循环; 增量定义循环控制变量每循环一次后按什么方式变化。这三个部分之间用";"分开。
例如:
for(i=1; i< =10; i++)
语句;

    上例中先给i赋初值1, 判断i是否小于等于10, 若是则执行语句, 之后值增加1。再重新判断, 直到条件为假, 即i>10时, 结束循环。

    注意:
1. for循环中语句可以为语句体, 但要用"{"和"}"将参加循环的语句括起来。
2. for循环中的"初始化"、"条件表达式"和"增量"都是选择项, 即可以缺省,但";"不能缺省。省略了初始化, 表示不对循环控制变量赋初值。 省略了条件表达式, 则不做其它处理时便成为死循环。省略了增量, 则不对循环控制变量进行操作, 这时可在语句体中加入修改循环控制变量的语句。
3. for循环可以有多层嵌套。
例:
int i, j, k,sum=0;
printf("i j k\n");
for (i=0; i< 2; i++)
for(j=0; j< 2; j++)
for(k=0; k< 2; k++)
sum++;

while循环
while循环的一般形式为:
while(条件)
语句;
while循环表示当条件为真时, 便执行语句。直到条件为假才结束循环。并继续执行循环程序外的后续语句。
例:
int i = 0;
while(i< 10) /*等于10结束循环*/
i++;
    上例中, while循环是以检查i是否小于10, 因其事先被初始化为0, 所以条件为真, 进入循环累加i一旦大于等于10, 条件为假, 循环便告结束。
与for循环一样, while循环总是在循环的头部检验条件, 这就意味着循环可能什么也不执行就退出。
    注意:
1. 在while循环体内也允许空语句。
例如:
while(i < 10);
当然,如果没有其他线程为i赋值,这个语句将导致死循环。
2. 可以有多层循环嵌套。
3. 语句可以是语句体, 此时必须用"{"和"}"括起来。

do-while 循环
do-while 循环的一般格式为:
do
语句;
while(条件);
    这个循环与while循环的不同在于: 它先执行循环中的语句, 然后再判断条件是否为真, 如果为真则继续循环; 如果为假, 则终止循环。因此, do-while循环至少要执行一次循环语句。
同样当有许多语句参加循环时, 要用"{"和"}"把它们括起来。

    开关语句(分支语句)
在编写程序时, 经常会碰到按不同情况分转的多路问题, 这时可用嵌套if-else-fi语句来实现, 但if-else-if语句使用不方便, 并且容易出错。对这种情况, C提供了一个开关语句。开关语句格式为:
switch(变量)
{
case 常量1:
语句1或空;
case 常量2:
语句2或空;
.
.
.
case 常量n;
语句n或空;
default:
语句n+1或空;
}
    执行switch开关语句时, 将变量逐个与case后的常量进行比较, 若与其中一 个相等, 则执行该常量下的语句, 若不与任何一个常量相等, 则执行default 后 面的语句。
    注意:
1. switch中变量可以是数值, 也可以是字符。
2. 可以省略一些case和default。
3. 每个case或default后的语句可以是语句体, 但不需要使用"{"和"}"括起 来。
下例的switch中变量为整数型。
例:
int test;
for(test=0; test< =10; test++)
{
switch(test) /*变量为整型数的开关语句*/
{
case 1:
...;
break; /*退出开关语句*/
case 2:
... ;
break;
case 3:
... ;
break;
default:
...;
break;
}
}
}

    break语句
break语句通常用在循环语句和开关语句中。当break用于开关语句switch中时, 可使程序跳出switch而执行switch以后的语句; 如果没有break语句, 则将成为一个死循环而无法退出。break在switch 中的用法已在前面介绍开关语句时的例子中碰到, 这里不再举例。

    当break语句用于do-while、for、while循环语句中时, 可使程序终止循环而执行循环后面的语句, 通常break语句总是与if语句联在一起。 即满足条件时便跳出循环。
例:
int i=0;
while(1) /*设置循环*/
{
i++;
if(i==13)
break;
}
这个例子实际上执行13次就结束了
    注意:
1. break语句对if-else的条件语句不起作用。
2. 在多层循环中, 一个break语句只向外跳一层。

    continue 语句
continue语句的作用是跳过循环本中剩余的语句而强行执行下一次循环。continue语句只用在for、while、do-while等循环体中, 常与if条件语句一起使用, 用来加速循环。
例:
int i=0,j=0;
while(i< 18)
{
i++;
if(i == 10)
continue; //等于10的时候,不再执行下面语句,直接执行下一个循环.
j++;
}
执行的结果j将等于17.

TOP

编写一条最简单的指标线


    通过前几课的学习,我们今天开始使用软件的公式编辑功能编写我们自己的第一条指标线。
    其实不难,你应该对自己有信心!
按照主菜单-工具-公式管理-选择-“技术指标”-点击“新建”,然后在公式编辑器中留下你的第一行脚印吧!
点击:“确认”,现在看一下我们第一条指标线。
这条指标线与你的想法相符吗?
    总结与补充:
1、如果选择:“主图叠加”,我们的指标线会与K线图显示在同一个图形框中,现在我们的指标线显示在其下方,即“副图”中;
2、参数可以有,也可以没有,但是鼓励大家设置参数,这是非常好的习惯;
3、一个句子完了,别忘了以分号结尾;
你的公式写得对不对,可以通过“测试公式”来检查,如果错了,它会告诉你错在哪里。

    编写最常用的均量和均价线
均价线,不就是那个“移动平均线MA”什么的吗?不过,话说回来,听说10个人里面有11个人都在使用,我可得学习学习!
原理是??
5日平均线=(今天收盘价+昨天收盘价+.....--5天前的收盘价)/5;
10日平均线=(今天收盘价+昨天收盘价+......+10天前的收盘价)/10;
150日平均线=(今天收盘价+昨天收盘价+......+150天前的收盘价)/150;
200日平均线......不是这么麻烦吧?难道我每天都要写这么多得数才得到一条平均线????
你有什么办法?
MA1=MA(CLOSE,5);
MA2=MA(CLOSE,10);
MA3=MA(CLOSE,50);
......
当然是有简单的方法了!你把我在上面说过的话写下来,按照前面几课讲的,写在公式的编辑栏当中就可以了!
注意:
“MA”表示的就是计算平均值。
在括号内写上计算的对象和计算的时间长度。
MA1,MA2,MA3......是好几条指标线,别忘记了用分号把它们分开。
最后呢?电脑自己会把它们一起画出来。
均量线???
均价线都有了,照着葫芦画瓢,把收盘价CLOSE换成成交量VOL就行了!
MA1:MA(VOL,5);
MA2:MA(VOL,10);
MA3:MA(VOL,150);
MA4:MA(VOL,200);
    今天有几只发生MA金叉?