发新话题
打印

制指标的专用知识集

TOP

学编飞狐公式——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[i];//计算前后股东位置的差
   IF WT>120 THEN BEGIN//当差超过一定标准时执行下面语句
      TW:=F10FIND('│',GDW[i]+75),LINETHICK;//确定所差字符的起点位置
      T:=F10TEXT(TW+2,26);//截取所差字符
      GDT[i]:=RTRIM(GDT[i])+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[i];//计算前后股东位置的差
   IF WT>120 THEN BEGIN//当差超过一定标准时执行下面语句
      TW:=F10FIND('│',GDW[i]+75),LINETHICK;//确定所差字符的起点位置
      T:=F10TEXT(TW+2,26);//截取所差字符
      GDT[i]:=RTRIM(GDT[i])+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资料查找公式了。

[[i] 本帖最后由 南山 于 2005-11-23 09:14 编辑 [/i]]

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;
  
    需要说明的是:筹码分布是一个统计概念,由于市场的千变万化,人们的交易行为不会只受到一种或几种思维方式的支配,因此不可能仅用一两种模式就能完整地描述市场的真实情况。也就是说 其必然存在着局限性。从实际的情况看这种局限性还非常严重。在使用时仅仅只能做为一种参考。。。。。。

http://www.li20.net/viewthread.p ... ge=1&highlight=

TOP

未来数据的哲学意味


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

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

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

http://www.li20.net/viewthread.p ... ge=1&highlight=

TOP

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


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

不同时域技术指标的组合

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

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

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

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

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

相互验证和相互背离原则

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

技术分析新发展

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

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

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

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


http://www.li20.net/viewthread.p ... ge=1&highlight=

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];


  再看一例“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

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

下面介绍在飞狐中,怎样学习和研究公式代码的方法,怎样分析得到结果。比如想分析我上面的公式代码思路,可以这样(为了直观,我删除了上面的注释):

1、如图所示,把所有的输出都加上“=”,即变成了临时变量,不会输出
2、把第1行定义中的“=”删掉
3、鼠标左键点公式编辑器的按钮“应用于图”,使之立即输出tj这个序列的结果,而不必点“确定”退出公式编辑器后才能看到结果。
4、从图中立即可以看出,序列变量tj的结果是,当年份为2003时,结果为1,否则结果为0


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

请教南客高手,飞狐中有没有“当前日期”这一函数?相当于Excel的TODAY()

有啊,参考如下:
别名: 计算时的当前日期
所属类别: 常数函数  参数数量: 0
计算时的当前日期
用法:
CURRENTDATE,返回计算时的日期,该日期是从1900年开始的天数,例如2003年8月1日表示为1030801
注意:该函数返回常数

http://www.li20.net/viewthread.p ... ghlight=&page=1

[ 本帖最后由 创幻指标版 于 2005-11-23 08:15 编辑 ]

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[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;  //定义序列变量为收盘价
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

  在飞狐中新建一个主图叠加公式,如下图所示,正是我们所需要的结果:

[img]http://www.li20.net/attachments/month_0401/Jb9P_Snap1.gif[/img]

[[i] 本帖最后由 南山 于 2005-11-23 09:09 编辑 [/i]]

TOP

  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;
  
  新建一个公式,输入上面代码,验证一番,结果如下图:


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


[ 本帖最后由 南山 于 2005-11-23 09:10 编辑 ]

TOP

  这个结果就对了!但大家可能会有疑问了,在前面递增循环中,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是多少,就要用到二重循环。对于循环中要执行的语句,如果重复太多,也可以使用多重循环来简化。以二重循环为例,大致结构如下:
  for i=n1 to n2 do
  begin
    语句;
    …
      for j=m1 to n2 do
      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;
For i=2 to datacount do
Begin
    Hh[i]:=max(Hh[i-1],Hh[i]);
End;
Hh;
  练习6:LLV(LOW,0);意思是求出上市以来的最低价,请用循环语句写出相同的代码来替换这行代码。

  练习7:下面代码,可以用循环语句来写吗?
a:=(3*c+l+o+h)/6;
b:(20*a+19*ref(a,1)+18*ref(a,2)+17*ref(a,3)+16*ref(a,4)+15*ref(a,5)+14*ref(a,6)
+13*ref(a,7)+12*ref(a,8)+11*ref(a,9)+10*ref(a,10)+9*ref(a,11)+8*ref(a,12)
+7*ref(a,13)+6*ref(a,14)+5*ref(a,15)+4*ref(a,16)+3*ref(a,17)+2*ref(a,18)+
ref(a,19))/210;
d:ma(b,m);


http://www.li20.net/viewthread.php?tid=79830&fpage=1&highlight=

[[i] 本帖最后由 南山 于 2005-11-23 09:11 编辑 [/i]]

TOP

  上一讲《飞狐内置循环、判断等控制语句入门二》中,我们介绍了飞狐内置循环,这一讲,介绍条件(判断)语句。
  条件语句的语法如下:
引用:
IF条件语句
语法:IF cond THEN expr1 ELSE expr2
如果 cond 条件成立,则执行语句 expr1,否则执行 expr2 语句。
说明:
  1、在条件判断比较简单的情况下,ELSE expr2 子句可以省略。
  2、条件 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 不能使用序列变量,这是最容易出错的地方,比如:
复制内容到剪贴板
代码:
{下面的代码是错误的}
fc:=close;
fo:=open;
if fc>fo then  //这里的fc、fo是序列变量,因此是错误的语法
  xx:=1
else
  xx:=0;
  这里,if fc>fo then 这种写法的本意是,“如果收盘价大于开盘价则”,是针对序列变量的每个数据(相当于数组的每个元素),在飞狐中,正确的写法应该是这样的:
复制内容到剪贴板
代码:
//如果xx是单值变量,则代码参考如下
fc:=close;
fo:=open;
for i=1 to datacount do //从第1根K线的位置,循环到最后1根K线的位置
  if fc[i]>fo[i] then  //这里,fc[i]、fo[i]代表某一天的收盘、开盘价,是单值变量
    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;
复制内容到剪贴板
代码:
//如果xx是序列变量,则代码参考如下
fc:=close;
fo:=open;
for i=1 to datacount do
  if fc[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;
if diff>dea then
  x:=1
else
  x:=0;
y:x;
http://www.li20.net/viewthread.php?tid=181357&fpage=1&highlight=

[ 本帖最后由 南山 于 2005-11-23 09:06 编辑 ]

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[i].m_fParam.
        5.若 i位置的参数为序列,取用m_pCalcParam[i].m_pfParam,数组大小为m_nNumData,数据有效范围为m_pCalcParam[i].m_nParamStart 至 m_nNumData-1. 若m_pCalcParam[i].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

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



这是DLL程序的主体,其中这句提醒已忘记用在那里了
“””””””””””””//        !!!!!!!! use "C" for Microsoft visual C++ compiler”””””””””””””
-------------------------------------------------------------------------------------------------
公式開始:
-------------------------------------------------------------------------------------------------
// FoxFunc.cpp : Defines the entry point for the DLL application.
//
#include <string.h>
#include <stdio.h>
#include <io.h>
#include <math.h>
#include <iostream.h>

#include "stdafx.h"
#include "FoxFunc.h"

float y[15000];
float yy[15000];

BOOL APIENTRY DllMain( HANDLE hModule,
                       DWORD  ul_reason_for_call,
                       LPVOID lpReserved
                                         )
{
    switch (ul_reason_for_call)
        {
                case DLL_PROCESS_ATTACH:
                case DLL_THREAD_ATTACH:
                case DLL_THREAD_DETACH:
                case DLL_PROCESS_DETACH:
                        break;
    }
    return TRUE;
}

//计算收盘价的均价,一个常数参数,表示计算周ヽ
//调用方法:
//        "FOXFUNC@MYMACLOSE"(5)


float smoothb(int ,int );
float realft(int, int );
int fourit(int , int );

//        !!!!!!!! use "C" for Microsoft visual C++ compiler
//        !!!!!!!! use "C" for Microsoft visual C++ compiler
//        !!!!!!!! use "C" for Microsoft visual C++ compiler
//        !!!!!!!! use "C" for Microsoft visual C++ compiler
//        !!!!!!!! use "C" for Microsoft visual C++ compiler

__declspec(dllexport) int WINAPI SMOOTH(CALCINFO* pData)
{
        if(pData->m_pfParam1 && pData->m_pfParam2 &&         //参数1,2有效
                pData->m_nParam1Start>=0 &&                                        //参数1为序列数
                pData->m_pfParam3==NULL)                                        //有2个参数
        {
                const float*  pValue = pData->m_pfParam1;        //参数1
                int nFirst = pData->m_nParam1Start;                        //有效值お始位
                float fParam = *pData->m_pfParam2;                        //参数2
                int nPeriod = (int)fParam;                        
        
        int nndata =pData->m_nNumData;
        float aa=(float)0.0;


                if( nFirst >= 0 && nPeriod > 0 )
                {   
                //        float fTotal;
                        int i;

   
                        for ( i =nFirst; i < pData->m_nNumData; i++ )
                        {
                                y[i+1] = pValue[i];    //Ⅸ均
                        }
      
            for ( i = 0; i <15000; i++ )
                        {
                                yy[i+1]=(float)0.0;
                        }


              aa=smoothb(nndata,nPeriod);


            for ( i =nFirst; i < pData->m_nNumData; i++ )
                        {
                                pData->m_pResultBuf[i]=y[i+1];    //Ⅸ均
                //   pData->m_pResultBuf[i]=aa;    //Ⅸ均
            //    pData->m_pResultBuf[i]=nndata;  
                        }

                        return 0;
                }
        }
        return -1;
}

[[i] 本帖最后由 南山 于 2005-11-23 10:33 编辑 [/i]]

TOP

//计算均价,2个参数,参数1为待А均线的数据,参数2表示计算周ヽ
//调用方法:
//        "FOXFUNC@MYMAVAR"(CLOSE-OPEN,5)


float smoothb(int ma,int pts)
{   int  m,n,k,j,n1,nmin,mo2,no2;
   float y1,yn,rn1,fac,cnst,aa,bb;
   
   
   
   m=2;
   n=ma;
   nmin=n*2+(pts*2+1);
   while (m < nmin) {
      m=m*2;
      }
   
   cnst=((float)pts/(float)m);

//!!!!!!!!! don't use cnst=pts/m;
//!!!!!!!!! don't use cnst=(double)(pts/m);
   bb=cnst;
  //  cnst= cnst*(float)pts/(float)n;
     cnst=cnst*cnst;
   
   y1=y[1];
   yn=y[n];
   rn1=(float)1.0/((float)n-(float)1.0);
   j=1;
      while (j<= n) {
         
          y[j]=y[j]-(y1*((float)n-(float)j)+yn*((float)j-(float)1))*rn1;

      j=j+1;
      }
   n1=2*ma;
//     yy=zeros(n1,1);
//   j=1;
//   while (j<=n1) {
//           yy[j]=0.0;
//       }
   

   j=1;
   while (j <= n) {
       yy[2*j-1]=y[j];
       j=j+1;
       }
   //  e=zeros(m-n1,1);yy=yy|e;


//   j=n1+1;
//   while (j<=m)
//       {
//       yy[j]=0.0;
//        }
//!!!!!!!!! yy=[n1+(m-n1),1]
//!!!!!!!!! yy=[n1+(m-n1),1]
//!!!!!!!!! yy=[n1+(m-n1),1]
//!!!!!!!!! yy=[n1+(m-n1),1]
//!!!!!!!!! yy=[n1+(m-n1),1]

   mo2=m/2;
   no2=(n/2);
   
   aa=realft(m,1);
         

   yy[1]=yy[1]/(float)mo2;
    fac=((float)1.05-(float)0.25*(float)pts*(float)pts)/(float)mo2;

    if  (fac < (float)0)
      { fac=(float)0; }
   
    yy[2]=yy[2]*fac;

   fac=(float)1.0;
   j=1;

   while (j < mo2)
   {   k=2*j+1;
      if  (fac != (float)0)
        {   fac=((float)1.05- cnst*(float)j*(float)j)/(float)mo2;
             if (fac <(float) 0)
               {fac=(float)0;}
         
            yy[k]=yy[k]*fac;
            yy[k+1]=yy[k+1]*fac;
          }
       else
            {  yy[k]=0;
               yy[k+1]=0;   }
       j=j+1;
     }


    aa=realft(m,-1);
   

    j=1;          /* even is image of complex */
    while (j <= n)
      {    y[j]=yy[j*2-1];
            j=j+1;
            }      
   
    j=1;
   while (j<= n)
      {     y[j]=y[j]+(y1*((float)n-(float)j)+yn*((float)j-(float)1))*rn1;
             j=j+1;
             }
   
//  retp(y);
return bb;
}

/*
** Purpose:    To get fourier transform of a real data array,
**             transform rows(y)/2 obs.
**
** Format:     y = realft(y,isign);
**
** Input:      y  -- vector, real data array.
**             isign -- 1, Fourier Transform of real data array.
**                      -1, Inverse Fourier Transform of complex
**                       data array.
**
** Output:     y=realft(y,isign);
**             y  -- vector, real data array.
**
** Note:       call fourit(data,1);
** Globals:    None
*/

float realft(int ma,int isign)
{
     int  n,m,i,i1,i2,i3,i4,np3,aa;
     float    h1r,c1,c2,h1i,h2r,h2i,wr,wi,wpr,wpi,wtemp,theta;
     

     m=ma;
     n=m/2;
     c1=(float)0.5;
     theta=(float)3.141592653589793/(float)n;

     

     if (isign == 1)
          {    c2=(float)-0.5;

              
                aa=fourit(m,1);

               
                }

     


     else
           {    c2=(float)0.5;
                 theta=-theta;
                 }
     
     wtemp=(float)sin((float)0.5*theta);
     wpr=(float)-2.0*wtemp*wtemp;
     wpi=(float)sin(theta);
     wr=(float)1.0+wpr;
     wi=wpi;
     np3=m+3;
     i=2;
     while (i <= m/4)
     {
        i1=i+i-1;
        i2=i+i1;
        i3=np3-i2;
        i4=1+i3;
        h1r=c1*(yy[i1]+yy[i3]);
        h1i=c1*(yy[i2]-yy[i4]);
        h2r=-c2*(yy[i2]+yy[i4]);
        h2i=c2*(yy[i1]-yy[i3]);
        yy[i1]=h1r+wr*h2r-wi*h2i;
        yy[i2]=h1i+wr*h2i+wi*h2r;
        yy[i3]=h1r-wr*h2r+wi*h2i;
        yy[i4]=-h1i+wr*h2i+wi*h2r;
        wtemp=wr;
        wr=wtemp*wpr-wi*wpi+wr;
        wi=wi*wpr+wtemp*wpi+wi;
        i=i+1;
         }

     if  (isign == 1)
         {     h1r=yy[1];
               yy[1]=h1r+yy[2];
               yy[2]=h1r-yy[2];
                }
     else
         {     h1r=yy[1];
                yy[1]=c1*(h1r+yy[2]);
                yy[2]=c1*(h1r-yy[2]);
               

                 aa=fourit(m,-1);

               
                  }

//     retp(data);
return 1;
}

/*
** Purpose:    To do Fourier Transform of a real data array
**             by decimation-in-time or Cooley-Tukey FFT.
**
** Format:     y = fourit(data,isign);
**
** Input:      data  -- vector, real data array.
**             isign -- 1, Fourier Transform of real data array.
**                         transform rows(data)/2.
**                      -1, Inverse Fourier Transform of complex
**                       data array.
**
** Output: