下载MetaTrader 5
要添加评论,请登录注册
文章可以帮您巩固所学的知识。快来 阅读它们吧!
秋风踏浪
166
秋风踏浪 2010.01.06 14:32 
三个函数,前两个函数都能得到正确的数值结果,第三个函数是对第二个函数的结果再次平滑处理,但得不出结果,不知道问题出在哪里,请高手指教。代码如下:
extern int LimitOfBars=250; 

double funA54(int i)  //给A54赋值
{
    //A54:=((C-LLV(L,21))/(HHV(H,21)-LLV(L,21)))*100;
    //给A54赋值:(收盘价-21日最低价)/(21天最高价-21天最低价)的值乘以100,赋值给A54;
    double A54=0;
    A54 = 100*(iClose(NULL,0,i)-iLow(NULL,0,iLowest(NULL,0,MODE_LOW,21,i)))/
          (iHigh(NULL,0,iHighest(NULL,0,MODE_HIGH,21,i))-iLow(NULL,0,iLowest(NULL,0,MODE_LOW,21,i)));
          
    return(A54);
}

double funY(int i)  //第一个,六次平滑
{
   double Y;
   
   if(i == LimitOfBars)
      Y = (funA54(i)+funA54(i+1)+funA54(i+2)+funA54(i+3)+funA54(i+4)+funA54(i+5))/6;
   else
      Y = (funA54(i) + 5*funY(i+1))/6;
      
   return(Y);      
}

double funY51(int i)  //第二个,五次平滑
{
   double Y;
   
   if(i == LimitOfBars)
      Y = (funA54(i)+funA54(i+1)+funA54(i+2)+funA54(i+3)+funA54(i+4))/5;
   else
      Y = (funA54(i) + 4*funY51(i+1))/5;
      
   return(Y);      
}

double funY52(int i)  //第三个,五次平滑再平滑
{
   double Y;
   
   if(i == LimitOfBars)
      Y = (funY51(i)+funY51(i+1)+funY51(i+2)+funY51(i+3)+funY51(i+4))/5;
   else
      Y = (funY51(i) + 4*funY52(i+1))/5;
      
   return(Y);       
}
谢谢。
connect y2k
178
connect y2k 2010.01.07 02:36  

请问,当i=LimitOfBars时,funY52(i)如何计算?此时i+1=LimitOfBars+1,funY52(i+1)是不存在的。

建议使用系统缓冲区,或者自己定义一个一维的数组。

秋风踏浪
166
秋风踏浪 2010.01.07 07:41  
y2k_connect 写道 >>

请问,当i=LimitOfBars时,funY52(i)如何计算?此时i+1=LimitOfBars+1,funY52(i+1)是不存在的。

建议使用系统缓冲区,或者自己定义一个一维的数组。

谢谢指点。问题就在第三个函数里。我觉得您说的有道理。或许做一个一维数组是个好办法。

但是,现在我仍然没弄明白问题到底出在哪里。当i=LimitOfBars时,Y = (funY51(i)+funY51(i+1)+funY51(i+2)+funY51(i+3)+funY51(i+4))/5,只有当i<LimitOfBars时,才能够执行Y = (funY51(i) + 4*funY52(i+1))/5,这时候 i 的最大取值应该是LimitOfBars-1,那么i+1=(LimitOfBars-1)+1=LimitOfBars,此时funY52(i+1)=funY52(LimitOfBars), Y = (funY51(i)+funY51(i+1)+funY51(i+2)+funY51(i+3)+funY51(i+4))/5。

还是没想明白问题所在,期待各位指点。

connect y2k
178
connect y2k 2010.01.07 17:48  

按照mt4的规定,0#是第一个数,1#是第二个数,249#是第250个数。

因此,你的funY51()中,i取值范围[0..n],其中n = (250 - 1) - 6 + 1 = 254;funY52()中,i的取值范围[0..n],n = [(250 - 1) - 6] - 5 + 1 = 239。

秋风踏浪
166
秋风踏浪 2010.01.08 08:56  
y2k_connect 写道 >>

按照mt4的规定,0#是第一个数,1#是第二个数,249#是第250个数。

因此,你的funY51()中,i取值范围[0..n],其中n = (250 - 1) - 6 + 1 = 254;funY52()中,i的取值范围[0..n],n = [(250 - 1) - 6] - 5 + 1 = 239。

谢谢回复。开始怕贴上代码太多看着比较乱,所以少贴了一段代码。

int start()  
  {
   for(int i=LimitOfBars; i>=0; i--) 
      {     
        drCS[i]=funY52(i);    
      } 
      
   timeName = "LableTitle1";
        ObjectDelete(timeName);
        ObjectCreate("LableTitle1", OBJ_LABEL, 1, 0, 0);
        ObjectSetText("LableTitle1",""+funY52(10), 10, "Arial", Lime);
        ObjectSet("LableTitle1", OBJPROP_CORNER, 1);
        ObjectSet("LableTitle1", OBJPROP_XDISTANCE, 5);
        ObjectSet("LableTitle1", OBJPROP_YDISTANCE, 50);
             
   return(0);
  }

其实对于funY52(i)中的 i 取值范围为 LimitOfBars >= i >=0,而且是由funY52(i)调用funY51(i)。但根据您的回复,我觉得funY51(i)中的 i 的取值范围一定有问题。但是刚才我把funY51(i)中的 i 的取值范围改了一下,仍然得不到funY52(i) 计算出来的结果。看来主要问题还不在这里。

谢谢。

okwh
1630
okwh 2010.01.08 17:27  

小心!

MQL4可能没那么强大,这样多次递归调用,可能它做不到。

connect y2k
178
connect y2k 2010.01.09 01:57  

在start()的for循环中,输出调试信息i的值。看看在程序死掉的时候,i的值是什么。

不建议使用多次递归的方式计算,耗时太长。

建议用循环的方式。总共需要3次循环,就能够解决问题。funA54(),funY51(),funY52()各需要一次循环。

要知道,函数调用的开销,远远高于内存指针移动的开销。

秋风踏浪
166
秋风踏浪 2010.01.09 07:09  

三个函数使用递归,第一、第二两个函数很正常,第三个函数对第二个函数的结果再次递归运算就出现问题,看来多次使用递归确实有问题。按楼上二位的建议,用循环和数组做一下,或许能解决这个问题。

谢谢二位的指点。

秋风踏浪
166
秋风踏浪 2010.01.10 13:51  

调整了三个函数中 i 的取值范围,已经得到了第三个函数的值。谢谢二位的指点。

现在的问题是运行速度奇慢,看样子这三个函数仍然不能用,还得用其它的办法。

谢谢。

connect y2k
178
connect y2k 2010.01.10 20:59  
dmgy 写道 >>

调整了三个函数中 i 的取值范围,已经得到了第三个函数的值。谢谢二位的指点。

现在的问题是运行速度奇慢,看样子这三个函数仍然不能用,还得用其它的办法。

谢谢。

如果你使用数组的方法,速度应该是非常快的。

你这还只是2次循环,我做的4~6次循环也是非常快的。


再一个,你的start(),每次循环都重新计算n次。实际上,除了第一次运行start()时,需要计算所有的历史数据,以后每次循环时,都只需要计算最近1~2个值就可以了。

mt4客户端收到新的数据时,调用start()。一般情况下,一秒钟内,start()起码运行3~8次。而mt4的k线数据,没有低于1分钟的。因此,只需要计算最近1~2个值就可以了。

void func() {
	int i,j, n;

	n = IndicatorCounted();
	if (n > 0)
		n--;
	n = Bars - n;

	for (i=0; i < n; i++) {
		// 如果需要其它周期的k线数据, 启用变量j, 并用j代替i.
		// j = iBarShift(NULL, PERIOD_H1, Time[i], false);
	}
}
秋风踏浪
166
秋风踏浪 2010.01.12 14:20  

start()每运行一次,三个函数都要进行很多递归运算,这样做确实有问题。看来用数组是可行的办法,决定改用数组来做这段程序了。

谢谢各位指点。

/
要添加评论,请登录注册