Aide à la rédaction d'une régression linéaire - page 4

 
Puisque nous parlons de la vitesse de calcul et non de la différence de performance des algorithmes, nous devons comparer des fonctions simples. Les indicateurs joints restent des indicateurs, dont la validité du calcul est le point de discorde ici. Nous devons prendre une fonction simple et l'implémenter de deux manières : comme un indicateur personnalisé et comme une fonction à appeler dans le code. J'ai déjà fait et écrit à ce sujet - Aboutthe Calculation Speed of Indicators in MQL4.

Voici l'indicateur 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);
  }
//+------------------------------------------------------------------+
Voici le script qui mesure la vitesse de calcul de l'algorithme de test

//+------------------------------------------------------------------+
//|                                             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);
  }
//+------------------------------------------------------------------+
par l'intermédiaire de iCustom() et de l'appel test().
 
Je vois deux différences dans les exemples : test est appelé comme une fonction (plutôt que d'être inséré directement dans le code) et le contenu de test est plus pauvre (pas de manipulation de tableau). La réponse à la question de savoir s'il faut utiliser iCustom dépend donc toujours de la situation.
P.S. Dans mon exemple, il n'y a pas de différence essentielle dans le nombre d'opérations pour les deux variantes - le "code de service" fonctionne une fois, et les boucles sont les mêmes.
 
1. Le style de programmation procédurale est le second après la programmation modulaire et la programmation orientée objet. Il est donc logique de placer l'algorithme de calcul dans une fonction distincte.

Et pourquoi travailler avec des tableaux dans une fonction intégrée ? Nous parlons de la différence entre le coût de l'appel d'une fonction personnalisée intégrée au code et celui d'une fonction externe appelée par iCustom().
 
Rosh:
1. Le style de programmation procédurale est le second après la programmation modulaire et la programmation orientée objet. Il est donc logique de placer l'algorithme de calcul dans une fonction distincte.

Et pourquoi travailler avec des tableaux dans une fonction intégrée ? Nous parlons de la différence entre le coût de l'appel d'une fonction personnalisée intégrée dans le code et celui d'une fonction externe appelée par iCustom().

1. c'est exactement l'efficacité résultante pour les grands projets. Il est juste inférieur en termes de vitesse.
2. de la même manière. C'est l'efficacité finale qui m'intéresse. Dans le cas de MQL, il s'agit généralement du temps nécessaire au développement plus le temps nécessaire aux tests chez le testeur. Cependant, les secondes supplémentaires d'attente pour que le terminal charge le compte réel peuvent également être très coûteuses. Je veux dire les nerfs, tout le monde n'a pas la bonne vision du commerce :)
 
Voici un script pour vérifier la différence.
//+------------------------------------------------------------------+
//|                                        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);
  }
//+------------------------------------------------------------------+

Et voici les résultats du script.





Comme vous pouvez le constater, l'utilisation d'une fonction distincte est justifiée - la différence de temps pour un cycle d'un milliard de passages n'est que d'une seconde. Mais il est beaucoup plus facile de développer le code !
 
Voici d'autres informations sur la recherche des paramètres de régression linéaire. Tiré d'ici - Canal de régression linéaire
 
Rosh:
Voici plus d'informations sur la façon de trouver les paramètres d'une régression linéaire. Tiré d'ici - Canal de régression linéaire

Et voici une fonction qui implémente l'algorithme décrit (peut-être que quelqu'un peut l'utiliser) :

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

La fonction est appelée comme ceci :

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

Notez que si nX[nI] sont des nombres barres, alors l'incrémentation de nI mène à l'envers ! :)

Regards,

Volt

 

Il y aquelque chose qui ne va pas dans le royaume du Danemark.

J'ai dû supprimer mon message précédent. Il y a une erreur dans l'algorithme.

Je sais que beaucoup de personnes utilisent cette procédure mais .... ne trouve pas la raison de l'erreur HELP me.

Voici le script. Les coefficients A et B sont calculés deux fois.

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

Le résultat est le suivant

intercept = -3.33333333 pente = 5.00000000

intercept = -1102.16914108 slope = 0.00000091

Et voici la même chose, mais calculée dans MathCad. En bleu les résultats correspondent, en rouge ils ne correspondent pas (.

Dans Mathcad, ce sont des fonctions intégrées, donc probablement une erreur dans MT4, mais où ?

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

Il y aquelque chose qui ne va pas dans le royaume du Danemark.

J'ai dû supprimer mon message précédent. Il y a une erreur dans l'algorithme.

Je sais que beaucoup de gens utilisent cette procédure mais .... ne trouve pas la raison de l'erreur HELP me.

Voici le script. Les coefficients A et B sont calculés deux fois.

Le résultat est le suivant

intercept = -3.33333333 pente = 5.00000000

intercept = -1102.16914108 slope = 0.00000091

Et voici la même chose, mais calculée dans MathCad. En bleu les résultats correspondent, en rouge ils ne correspondent pas (.

Il s'agit d'une fonction intégrée dans Mathcad, donc très probablement une erreur dans MT4, mais où ?

Voici ce que montre Excel 2007




Il peut donc être nécessaire de vérifier Matcad.

 

Une des mises en oeuvre de la régression linéaire, le degré du polynôme est de 20, le nombre de points de calcul et le décalage du point de départ sont fixés...

la sortie est faite en utilisant un canal dont la profondeur est définie en points... à une profondeur de 0, seule la courbe de régression elle-même est sortie.

Dossiers :