Ayuda para escribir una regresión lineal - página 4

 
Como estamos hablando de la velocidad de cálculo y no de la diferencia en el rendimiento del algoritmo, deberíamos comparar funciones simples. Los indicadores adjuntos siguen siendo indicadores, cuya validez de cálculo es el punto de controversia aquí. Debemos tomar una función simple e implementarla de dos maneras: como un indicador personalizado y como una función que se llame en el código. Ya he hecho y escrito sobre ello - Sobrela velocidad de cálculo de los indicadores en MQL4.

Aquí está el indicador 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);
  }
//+------------------------------------------------------------------+
Este es el script que mide la velocidad de cálculo del algoritmo de prueba

//+------------------------------------------------------------------+
//|                                             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);
  }
//+------------------------------------------------------------------+
a través de iCustom() y a través de la llamada a test().
 
Veo dos diferencias en los ejemplos: el test se llama como una función (en lugar de insertarse directamente en el código) y el contenido del test es más pobre (no hay manejo de arrays). Por tanto, la respuesta a la pregunta de si se debe utilizar iCustom sigue pareciendo depender de la situación.
P.D. En mi ejemplo no hay una diferencia tan esencial en el número de operaciones para dos variantes - el "código de servicio" funciona una vez, y los bucles son los mismos.
 
1. El estilo de programación procedimental sólo es superado por la programación modular y la orientada a objetos. Por lo tanto, poner el algoritmo de cálculo en una función separada es un paso lógico.

¿Y por qué hay que trabajar con arrays en una función incorporada? Estamos hablando de la diferencia en el coste de llamar a una función personalizada incrustada en el código y a una función externa llamada a través de iCustom().
 
Rosh:
1. El estilo de programación procedimental sólo es superado por la programación modular y la orientada a objetos. Por lo tanto, poner el algoritmo de cálculo en una función separada es un paso lógico.

¿Y por qué hay que trabajar con arrays en una función incorporada? Estamos hablando de la diferencia en el coste de llamar a una función personalizada incrustada en el código y a una función externa llamada a través de iCustom().

1. es exactamente la eficacia resultante para los grandes proyectos. Sólo es inferior en términos de velocidad.
2. De manera similar. Lo que me interesa es la eficacia final. En el caso de MQL, suele ser el tiempo necesario para el desarrollo más el tiempo necesario para las pruebas en el probador. Aunque los segundos extra de espera para que el terminal cargue la cuenta real también pueden ser muy costosos. Me refiero a los nervios, no todo el mundo tiene la visión correcta sobre el comercio :)
 
Aquí hay un script para comprobar la diferencia.
//+------------------------------------------------------------------+
//|                                        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);
  }
//+------------------------------------------------------------------+

Y aquí están los resultados del guión.





Como puede ver, el uso de una función separada está justificado: la diferencia de tiempo para un ciclo de mil millones de pases es de sólo un segundo. Pero es mucho más fácil desarrollar el código.
 
Aquí hay más información sobre el tema de la búsqueda de parámetros de regresión lineal. Tomado de aquí - Canal de Regresión Lineal
 
Rosh:
Aquí tienes más información sobre cómo encontrar los parámetros de una regresión lineal. Tomado de aquí - Canal de Regresión Lineal

Y aquí hay una función que implementa el algoritmo descrito (tal vez alguien pueda usarla):

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 función se llama así:

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

Tenga en cuenta que si nX[nI] son números de barra, ¡el incremento de nI lleva hacia atrás! :)

Saludos,

Volt

 

Algo anda mal en el reino danés.

He tenido que borrar mi post anterior. Hay un error en el algoritmo.

Sé que mucha gente utiliza este procedimiento, pero .... no puede encontrar la razón del error AYUDA a mí.

Aquí está el guión. Los coeficientes A y B se calculan dos veces.

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

El resultado es el siguiente

intercepción = -3,33333333 pendiente = 5,00000000

intercepción = -1102,16914108 pendiente = 0,00000091

Y aquí está lo mismo, pero calculado en MathCad. En azul los resultados coinciden, en rojo no (.

En Mathcad estas son funciones incorporadas, por lo que lo más probable es un error en MT4, pero ¿dónde?

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

Algo anda mal en el reino danés.

He tenido que borrar mi post anterior. Hay un error en el algoritmo.

Sé que mucha gente utiliza este procedimiento, pero .... no puede encontrar la razón del error AYUDA a mí.

Aquí está el guión. Los coeficientes A y B se calculan dos veces.

El resultado es el siguiente

intercepción = -3,33333333 pendiente = 5,00000000

intercepción = -1102,16914108 pendiente = 0,00000091

Y aquí está lo mismo, pero calculado en MathCad. En azul los resultados coinciden, en rojo no (.

Esta es una función incorporada en Mathcad, por lo que lo más probable es un error en MT4, pero ¿dónde?

Esto es lo que muestra Excel 2007




Por lo tanto, puede ser necesario comprobar Matcad.

 

Una de las implementaciones de regresión lineal, el grado del polinomio es 20, el número de puntos de cálculo y el desplazamiento del punto de partida se establece...

la salida se realiza mediante un canal cuya profundidad se establece en puntos... a una profundidad de 0 sólo se emite la propia curva de regresión

Archivos adjuntos: