Ajudar a escrever uma regressão linear - página 4

 
Como estamos falando de velocidade de cálculo e não da diferença no desempenho do algoritmo, devemos comparar funções simples. Os indicadores anexos ainda são indicadores, cuja validade do cálculo é o ponto de discórdia aqui. Devemos pegar uma função simples e implementá-la de duas maneiras - como um indicador personalizado e como uma função a ser chamada no código. Eu já fiz e escrevi sobre isso - Sobrea velocidade de cálculo dos indicadores na MQL4.

Aqui está o teste indicador.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);
  }
//+------------------------------------------------------------------+
Aqui está o roteiro que mede a velocidade de cálculo do algoritmo de teste

//+------------------------------------------------------------------+
//|                                             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);
  }
//+------------------------------------------------------------------+
através de iCustom() e através de chamada de teste().
 
Vejo duas diferenças nos exemplos: teste é chamado como uma função (ao invés de ser inserido diretamente no código) e o conteúdo do teste é mais pobre (sem manipulação de array). Portanto, a resposta à questão de se o iCustom deve ser usado ainda parece dependente da situação.
P.S. No meu exemplo não há uma diferença tão essencial no número de operações para duas variantes - "servir código" funciona uma vez, e os loops são os mesmos.
 
1. O estilo de programação processual está em segundo lugar apenas em relação à programação modular e orientada a objetos. Portanto, colocar o algoritmo de computação em uma função separada é um passo lógico.

E por que você deveria trabalhar com arrays em uma função integrada? Estamos falando da diferença no custo de chamar uma função personalizada embutida no código e uma função externa chamada através do iCustom().
 
Rosh:
1. O estilo de programação processual está em segundo lugar apenas em relação à programação modular e orientada a objetos. Portanto, colocar o algoritmo de computação em uma função separada é um passo lógico.

E por que você deveria trabalhar com arrays em uma função integrada? Estamos falando da diferença no custo de chamar uma função personalizada embutida no código e uma função externa chamada através do iCustom().

1. é exatamente a eficiência resultante para grandes projetos. É apenas inferior em termos de velocidade.
2. De forma semelhante. É a eficiência final que me interessa. No caso do MQL, geralmente é o tempo necessário para o desenvolvimento mais o tempo necessário para o teste no testador. Embora, os segundos extras de espera para o terminal carregar a conta real também possam ser muito caros. Quero dizer, nervosismo, nem todos têm a visão certa sobre o comércio :)
 
Aqui está um roteiro para verificar a diferença.
//+------------------------------------------------------------------+
//|                                        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);
  }
//+------------------------------------------------------------------+

E aqui estão os resultados do roteiro.





Como você pode ver, o uso de uma função separada é justificado - a diferença de tempo para um ciclo de um bilhão de passagens é de apenas um segundo. Mas é muito mais fácil desenvolver o código!
 
Aqui está mais sobre o assunto de encontrar parâmetros de regressão linear. Tirado daqui - Canal de Regressão Linear
 
Rosh:
Aqui está mais sobre como encontrar parâmetros de uma regressão linear. Tirado daqui - Canal de Regressão Linear

E aqui está uma função que implementa o algoritmo descrito (talvez alguém possa usá-lo):

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

A função é assim chamada:

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

Note que se nX[nI] são números de barra, então o incremento nI leva para trás! :)

Cumprimentos,

Volt

 

algo de errado no reino dinamarquês.

Tive que apagar meu posto anterior. Há um erro no algoritmo.

Sei que muitas pessoas usam este procedimento, mas .... não consegue encontrar a razão do erro AJUDA-ME.

Aqui está o roteiro. Os coeficientes A e B são calculados duas vezes.

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

O resultado é o seguinte

intercepção = -3,33333333 declive = 5,00000000

intercepção = -1102.16914108 declive = 0.00000091

E aqui é o mesmo, mas calculado no MathCad. Em azul os resultados correspondem, em vermelho eles não (.

No Mathcad estas são funções embutidas, portanto, muito provavelmente um erro no MT4, mas onde ?

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

algo de errado no reino dinamarquês.

Tive que apagar meu posto anterior. Há um erro no algoritmo.

Sei que muitas pessoas usam este procedimento, mas .... não consegue encontrar a razão do erro AJUDA-ME.

Aqui está o roteiro. Os coeficientes A e B são calculados duas vezes.

O resultado é o seguinte

intercepção = -3,33333333 declive = 5,00000000

intercepção = -1102.16914108 declive = 0.00000091

E aqui é o mesmo, mas calculado no MathCad. Em azul os resultados correspondem, em vermelho eles não (.

Esta é uma função integrada no Mathcad, portanto, muito provavelmente um erro no MT4, mas onde ?

Aqui está o que o Excel 2007 mostra




Portanto, talvez seja necessário verificar o Matcad.

 

Uma das implementações da regressão linear, o grau de polinômio é 20, o número de pontos de cálculo e o offset do ponto de partida é definido...

a saída é feita usando uma profundidade de canal é definida em pontos... a uma profundidade de 0 apenas a própria curva de regressão é de saída

Arquivos anexados: