帮助写一个线性回归 - 页 4

 
由于我们讨论的是计算速度,而不是算法性能的差异,所以我们应该比较简单的函数。所附指标仍然是指标,其计算的有效性是这里争论的焦点。我们应该采取一个简单的函数,并以两种方式实现它--作为一个自定义指标和作为一个在代码中被调用的函数。我已经做了,并且写了 - 关于MQL4中指标的计算速度

这里是指标test.mq4

//+------------------------------------------------------------------+
//|                                                         Test.mq4 |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net/ru/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net/ru/"
 
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Red
 
extern int val=5;
//---- buffers
double ExtMapBuffer1[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   SetIndexStyle(0,DRAW_LINE);
   SetIndexBuffer(0,ExtMapBuffer1);
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
//----
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int    counted_bars=IndicatorCounted();
//----
   int    res_int=0,i;
   double res_double=0;
//----
   for(i=0;i<=10000000;i++)
     {
      res_int+=i*i;
      res_int++;
      res_double+=i*i;
      res_double++;
     }
   ExtMapBuffer1[0]=res_double;      
//----
   return(0);
  }
//+------------------------------------------------------------------+
以下是测量测试算法计算速度的脚本

//+------------------------------------------------------------------+
//|                                             CheckCustomSpeed.mq4 |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                        https://www.metaquotes.net/ru/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net/ru/"
 
#property show_inputs
 
 
//+------------------------------------------------------------------+
//|  implemented Test functiom                                       |
//+------------------------------------------------------------------+
double test()
   {
   int    res_int=0,i;
   double res_double=0;
//----
   for(i=0;i<=10000000;i++)
     {
      res_int+=i*i;
      res_int++;
      res_double+=i*i;
      res_double++;
     }
   return(res_double);
   }
 
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
  double Impl=test();
  double Custom=iCustom(NULL,0,"Test",5,0,0);
//----
   Print("Implemented retuns ",Impl,",   iCustom returns ",Custom,", diiff=",Impl-Custom);
   
//----
   int i,start,stop;
   //Measuring time for test function
   start=GetTickCount();
   for (i=0;i<100;i++) test();
   stop=GetTickCount();
   int testTime=(stop-start)/1000.0;
 
   //Measuring time for Custom function
   start=GetTickCount();
   for (i=0;i<100;i++) Custom=iCustom(NULL,0,"Test",i,0,0);
   stop=GetTickCount();
   int customTime=(stop-start)/1000.0;
   string text=StringConcatenate("Time for implemented function test() is ",testTime,"  seconds");
   text=StringConcatenate(text,"\n Time for custom function iCustom(\"test\") is ",customTime,"  seconds");
   Comment(text);
 
//----
   return(0);
  }
//+------------------------------------------------------------------+
通过iCustom() 和test()调用。
 
我在例子中看到两个不同之处:test是作为一个函数调用的(而不是直接插入到代码中),test的内容比较差(没有数组处理)。所以,对于是否应该使用iCustom的 问题,答案看起来还是要视情况而定。
P.S. 在我的例子中,两种变体的操作数量并无本质区别--"服务代码 "只工作一次,循环也是如此。
 
1.程序化编程风格仅次于模块化和面向对象编程。因此,将计算算法放入一个单独的函数是一个合乎逻辑的步骤。

而你为什么要在内置函数中处理数组?我们谈论的是调用嵌入到代码中的自定义函数和通过iCustom()调用外部函数的成本差异。
 
Rosh:
1.程序化编程风格仅次于模块化和面向对象编程。因此,将计算算法放入一个单独的函数是一个合乎逻辑的步骤。

而你为什么要在内置函数中处理数组?我们谈论的是调用嵌入到代码中的自定义函数和通过iCustom()调用外部函数的成本差异。

1.这正是大型项目的结果效率。它只是在速度方面比较逊色。
2.类似地。我感兴趣的是最后的效率。在MQL的情况下,通常是开发所需的时间加上在测试器中测试所需的时间。虽然,等待终端加载真实账户的额外几秒钟也可能是非常昂贵的。我的意思是神经,不是每个人都对交易有正确的看法 :)
 
这里有一个检查差异的脚本。
//+------------------------------------------------------------------+
//|                                        CheckCalculationSpeed.mq4 |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net/ru/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net/ru/"
 
#property show_inputs
 
 
//+------------------------------------------------------------------+
//|  implemented Test functiom                                       |
//+------------------------------------------------------------------+
double test()
   {
   int    res_int=0,i;
   double res_double=0;
//----
   for(i=0;i<=10000000;i++)
     {
      res_int+=i*i;
      res_int++;
      res_double+=i*i;
      res_double++;
     }
   return(res_double);
   }
 
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
  double Impl=test();
  double Custom=iCustom(NULL,0,"Test",5,0,0);
//----
   Print("Implemented retuns ",Impl,",   iCustom returns ",Custom,", diiff=",Impl-Custom);
   
//----
   int i,start,stop;
   //Measuring time for test function
   start=GetTickCount();
   for (i=0;i<100;i++) test();
   stop=GetTickCount();
   int testTime=(stop-start)/1000.0;
 
   //Measuring time for direct calculation
   int    res_int=0,j;
   double res_double=0;
 
   start=GetTickCount();
   for (j=0;j<100;j++) 
      {
      for(i=0;i<=10000000;i++)
        {
         res_int+=i*i;
         res_int++;
         res_double+=i*i;
         res_double++;
        }
     }     
   stop=GetTickCount();
   int customTime=(stop-start)/1000.0;
   string text=StringConcatenate("Time for implemented function test() is ",testTime,"  seconds");
   text=StringConcatenate(text,"\n Time for direct Calculation block  is ",customTime,"  seconds");
   Comment(text);
 
//----
   return(0);
  }
//+------------------------------------------------------------------+

而这里是脚本的结果。





正如你所看到的,使用一个单独的函数是合理的--10亿次循环的时间差只有一秒钟。 但是,开发代码要容易得多!
 
这里有更多关于寻找线性回归参数的话题。摘自这里--线性回归 频道
 
Rosh:
这里有更多关于如何寻找线性回归的参数。摘自这里--线性回归频道

而这里有一个实现所述算法的函数(也许有人可以使用它)。

void fLinearRegr(int nX[], double dY[], int nN, double& dA, double& dB)
{ //*************************************************************************
  //  Аппроксимация до прямой:
  //
  //  dY[nI] = dA + dB * nX[nI] - общая формула прямой
  //  
  //  dB = (nN*dSumXY - dSumX*dSumY) / (nN*dSumX2 - dSumX*dSumX)
  //
  //  dA = (dSumY - dB*dSumX) / nN
  //
  //  dSumXY = nX[0]*dY[0] + nX[1]*dY[1] + ... + nX[nN-1]*dY[nN-1]
  //
  //  dSumX  = nX[0] + nX[1] + ... + nX[nN-1]
  //  
  //  dSumY  = dY[0] + dY[1] + ... + dY[nN-1]  
  //  
  //  dSumX2 = nX[0]*nX[0] + nX[1]*nX[1] + ... + nX[nN-1]*nX[nN-1]
  //    
  //  Функция  вычисляет  коэффициенты  аппроксимирующей прямой.     
  //  
  //  Входные параметры:
  //      nX  -   массив  целых чисел с нумерацией элементов от 0 до N-1.
  //              Содержит набор абсцисс, в которых известны значения функции.
  //      dY   -  массив  вещественных  чисел с нумерацией элементов от 0 до N-1.
  //              Содержит набор значений функции.
  //      nN   -  число точек. N>=1
  //                                  
  //  Выходные параметры:
  //      dA, dB - коэффициенты аппроксимирующей прямой y=a+b*x
  //
  //  Реализация функции: Volt ( voltair@inbox.ru ) 
  //*************************************************************************/
  double dSumXY=0.0, dSumX=0.0, dSumY=0.0, dSumX2=0.0;
  for (int nI=0; nI<nN; nI++)
  { // вычисляем dSumXY
    dSumXY = dSumXY + nX[nI]*dY[nI];
    // вычисляем dSumX
    dSumX  = dSumX  + nX[nI];
    // вычисляем dSumY
    dSumY  = dSumY  + dY[nI];
    // вычисляем dSumX2
    dSumX2 = dSumX2 + nX[nI]*nX[nI];
  }
  // вычисляем dB
  dB = (nN*dSumXY - dSumX*dSumY) / (nN*dSumX2 - dSumX*dSumX);
  // вычисляем dA
  dA = (dSumY - dB*dSumX) / nN;
}

该函数是这样调用的。

  int nX[5];
  double dY[5];
  // . . .
  nX[0] = nBar;
  dY[0] = High[nBar]; 
  // . . .
  nX[4] = nBar+4;
  dY[4] = High[nBar+4]; 
  // . . .
  fLinearRegr(nX, dY, 5, dA, dB);

请注意,如果nX[nI]是条形数字,那么递增nI就会导致倒退!:)

注意到。

伏特

 

丹麦王国出了点问题。

我不得不删除我之前的帖子。算法中存在一个错误。

我知道很多人都在使用这个程序,但....,找不到错误的原因HELP我。

这里是剧本。A和B 的系数要计算两次。

//+------------------------------------------------------------------+
//|                                                       LinReg.mq4 |
//|                                                    Привалов С.В. |
//|                                             Skype -> privalov-sv |
//+------------------------------------------------------------------+
#property copyright "Привалов С.В."
#property link      "Skype -> privalov-sv"

//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
//----
   int      N=6;                 // Размер массива
   double   Y[],X[],A=0,B=0;
   
  ArrayResize(X,N);
  ArrayResize(Y,N);
      
    for ( int i = 0; i < N; i ++ )
    {
    // массивы Y и X для проверки работоспособности
    // intercept = -3.33333333 slope = 5.00000000

    X[i]=i;
    Y[i]=i*i;
    }
  LinearRegr(X, Y, N, A, B);
  
  Print("intercept = ", DoubleToStr(A,8)," slope = ",DoubleToStr(B,8));
// вторая проверка
    X[0]=1216640160;
    X[1]=1216640100;
    X[2]=1216640040;
    X[3]=1216639980;
    X[4]=1216639920;
    X[5]=1216639860;
    
    Y[0]=1.9971;
    Y[1]=1.9970;    
    Y[2]=1.9967;
    Y[3]=1.9969;    
    Y[4]=1.9968;    
    Y[5]=1.9968;
    
    A=0;
    B=0;
    
  LinearRegr(X, Y, N, A, B);
  
  Print("intercept = ", DoubleToStr(A,8)," slope = ",DoubleToStr(B,8));
           
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| y(x)=A+B*x                                                       |
//| используються формулы https://forum.mql4.com/ru/10780/page4       |
//+------------------------------------------------------------------+

void LinearRegr(double X[], double Y[], int N, double& A, double& B)
{
      double sumY = 0.0, sumX = 0.0, sumXY = 0.0, sumX2 = 0.0;
      
    for ( int i = 0; i < N; i ++ )
    {
        sumY   +=Y[i];
        sumXY  +=X[i]*Y[i];
        sumX   +=X[i];
        sumX2  +=X[i]*X[i];
    }
   B=(sumXY*N-sumX*sumY)/(sumX2*N-sumX*sumX);
   A=(sumY-sumX*B)/N;
}

结果如下

截距=-3.33333333 斜率=5.00000000

截距 = -1102.16914108 斜率 = 0.00000091

这里是同样的,但在MathCad 中计算。蓝色的结果相符,红色的结果不相符(。

在Mathcad中,这些都是内置函数,所以很可能是MT4中的错误,但在哪里?

附加的文件:
scripts.rar  15 kb
 
Prival писал (а)>>

丹麦王国出了点问题。

我不得不删除我之前的帖子。算法中存在一个错误。

我知道很多人都在使用这个程序,但....,找不到错误的原因HELP我。

这里是剧本。A和B 的系数要计算两次。

结果如下

截距=-3.33333333 斜率=5.00000000

截距 = -1102.16914108 斜率 = 0.00000091

这里是同样的,但在MathCad 中计算。蓝色的结果相符,红色的结果不相符(。

这是Mathcad中的一个内置函数,所以很可能是MT4中的一个错误,但在哪里?

以下是Excel 2007显示的情况




因此,可能有必要检查一下Matcad。

 

其中一个线性回归的实施方案,多项式的度数为20,计算点的数量和起点的偏移量设...

输出是通过一个以点为单位的通道深度来完成的......在深度为0时,只有回归曲线本身被输出。

附加的文件: