Hilfe beim Schreiben einer linearen Regression - Seite 4

 
Da es hier um die Rechengeschwindigkeit und nicht um den Unterschied in der Leistung des Algorithmus geht, sollten wir einfache Funktionen vergleichen. Bei den beigefügten Indikatoren handelt es sich nach wie vor um Indikatoren, deren Berechnungsgültigkeit hier umstritten ist. Wir sollten eine einfache Funktion nehmen und sie auf zwei Arten implementieren - als benutzerdefinierten Indikator und als eine Funktion, die im Code aufgerufen wird. Ich habe bereits getan und schrieb über sie - Über dieBerechnungsgeschwindigkeit von Indikatoren in MQL4.

Hier ist der Indikator 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);
  }
//+------------------------------------------------------------------+
Hier ist das Skript, das die Berechnungsgeschwindigkeit des Testalgorithmus misst

//+------------------------------------------------------------------+
//|                                             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);
  }
//+------------------------------------------------------------------+
durch iCustom() und durch test()-Aufruf.
 
Ich sehe zwei Unterschiede in den Beispielen: test wird als Funktion aufgerufen (und nicht direkt in den Code eingefügt) und der Inhalt von test ist schlechter (keine Array-Behandlung). Die Antwort auf die Frage, ob iCustom verwendet werden sollte, ist also immer noch situationsabhängig.
P.S. In meinem Beispiel gibt es keinen so wesentlichen Unterschied in der Anzahl der Operationen für zwei Varianten - "Serving Code" arbeitet einmal, und die Schleifen sind gleich.
 
1. Der prozedurale Programmierstil ist nach der modularen und objektorientierten Programmierung der zweitwichtigste. Daher ist es ein logischer Schritt, den Berechnungsalgorithmus in eine eigene Funktion zu integrieren.

Und warum sollten Sie mit Arrays in einer integrierten Funktion arbeiten? Es geht um den Unterschied zwischen den Kosten für den Aufruf einer in den Code eingebetteten benutzerdefinierten Funktion und einer externen Funktion, die über iCustom() aufgerufen wird.
 
Rosh:
1. Der prozedurale Programmierstil ist nach der modularen und objektorientierten Programmierung der zweitwichtigste. Daher ist es ein logischer Schritt, den Berechnungsalgorithmus in eine eigene Funktion zu integrieren.

Und warum sollten Sie mit Arrays in einer integrierten Funktion arbeiten? Es geht um den Unterschied zwischen den Kosten für den Aufruf einer in den Code eingebetteten benutzerdefinierten Funktion und einer externen Funktion, die über iCustom() aufgerufen wird.

1. Es ist genau die resultierende Effizienz für große Projekte. Er ist nur in Bezug auf die Geschwindigkeit unterlegen.
2. Ähnlich. Es ist die endgültige Effizienz, die mich interessiert. Bei MQL ist es in der Regel die Zeit, die für die Entwicklung benötigt wird, plus die Zeit, die für das Testen im Prüfgerät benötigt wird. Allerdings können die zusätzlichen Sekunden, die man warten muss, bis das Terminal das echte Konto geladen hat, auch sehr teuer sein. Ich meine die Nerven, nicht jeder hat die richtige Einstellung zum Handel :)
 
Hier ist ein Skript, um den Unterschied zu überprüfen.
//+------------------------------------------------------------------+
//|                                        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);
  }
//+------------------------------------------------------------------+

Und hier sind die Ergebnisse des Skripts.





Wie Sie sehen können, ist die Verwendung einer separaten Funktion gerechtfertigt - der Zeitunterschied für einen Zyklus von einer Milliarde Durchläufen beträgt nur eine Sekunde. Aber es ist viel einfacher, den Code zu entwickeln!
 
Hier finden Sie weitere Informationen über die Ermittlung von Parametern für lineare Regressionen. Entnommen von hier - Linearer Regressionskanal
 
Rosh:
Hier erfahren Sie mehr darüber, wie man die Parameter einer linearen Regression findet. Entnommen von hier - Linearer Regressionskanal

Und hier ist eine Funktion, die den beschriebenen Algorithmus implementiert (vielleicht kann sie jemand verwenden):

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

Die Funktion wird wie folgt aufgerufen:

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

Beachten Sie, dass, wenn nX[nI] Balkennummern sind, die Inkrementierung von nI rückwärts führt! :)

Herzliche Grüße,

Volt

 

Im dänischen Königreich ist etwas faul.

Ich musste meinen vorherigen Beitrag löschen. Es liegt ein Fehler im Algorithmus vor.

Ich weiß, dass viele Leute dieses Verfahren verwenden, aber .... kann den Grund für den Fehler nicht finden HELP me.

Hier ist das Skript. Die Koeffizienten A und B werden zweimal berechnet.

//+------------------------------------------------------------------+
//|                                                       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;
}

Das Ergebnis lautet wie folgt

Achsenabschnitt = -3,33333333 Steigung = 5,00000000

Achsenabschnitt = -1102,16914108 Steigung = 0,00000091

Und hier ist das Gleiche, aber in MathCad berechnet. In Blau stimmen die Ergebnisse überein, in Rot nicht (.

In Mathcad sind dies eingebaute Funktionen, also höchstwahrscheinlich ein Fehler in MT4, aber wo?

Dateien:
scripts.rar  15 kb
 
Prival писал (а) >>

Im dänischen Königreich ist etwas faul.

Ich musste meinen vorherigen Beitrag löschen. Es liegt ein Fehler im Algorithmus vor.

Ich weiß, dass viele Leute dieses Verfahren verwenden, aber .... kann den Grund für den Fehler nicht finden HELP me.

Hier ist das Skript. Die Koeffizienten A und B werden zweimal berechnet.

Das Ergebnis lautet wie folgt

Achsenabschnitt = -3,33333333 Steigung = 5,00000000

Achsenabschnitt = -1102,16914108 Steigung = 0,00000091

Und hier ist das Gleiche, aber in MathCad berechnet. In Blau stimmen die Ergebnisse überein, in Rot nicht (.

Dies ist eine eingebaute Funktion in Mathcad, also höchstwahrscheinlich ein Fehler in MT4, aber wo?

Excel 2007 zeigt Folgendes an




Es kann also notwendig sein, Matcad zu überprüfen.

 

Eine der Implementierungen der linearen Regression, der Grad des Polynoms ist 20, die Anzahl der Berechnungspunkte und der Offset des Startpunktes ist festgelegt...

die Ausgabe erfolgt über einen Kanal, dessen Tiefe in Punkten angegeben wird. Bei einer Tiefe von 0 wird nur die Regressionskurve selbst ausgegeben

Dateien: