Aiuta a scrivere una regressione lineare - pagina 4

 
Dato che stiamo parlando della velocità di calcolo e non della differenza di prestazioni dell'algoritmo, dovremmo confrontare funzioni semplici. Gli indicatori allegati sono ancora indicatori, la cui validità di calcolo è il punto del contendere qui. Dovremmo prendere una semplice funzione e implementarla in due modi: come indicatore personalizzato e come funzione da chiamare nel codice. Ho già fatto e scritto su questo - Sullavelocità di calcolo degli indicatori in MQL4.

Ecco l'indicatore 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);
  }
//+------------------------------------------------------------------+
Ecco lo script che misura la velocità di calcolo dell'algoritmo di prova

//+------------------------------------------------------------------+
//|                                             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);
  }
//+------------------------------------------------------------------+
attraverso iCustom() e attraverso la chiamata test().
 
Vedo due differenze negli esempi: test è chiamato come una funzione (piuttosto che inserito direttamente nel codice) e il contenuto di test è più povero (nessuna gestione di array). Quindi, la risposta alla domanda se iCustom debba essere usato sembra ancora dipendente dalla situazione.
P.S. Nel mio esempio non c'è una differenza così essenziale nel numero di operazioni per due varianti - il "codice di servizio" funziona una volta sola, e i cicli sono gli stessi.
 
1. Lo stile di programmazione procedurale è secondo solo alla programmazione modulare e orientata agli oggetti. Quindi, mettere l'algoritmo di calcolo in una funzione separata è un passo logico.

E perché dovreste lavorare con gli array in una funzione integrata? Stiamo parlando della differenza nel costo della chiamata di una funzione personalizzata incorporata nel codice e una funzione esterna chiamata attraverso iCustom().
 
Rosh:
1. Lo stile di programmazione procedurale è secondo solo alla programmazione modulare e orientata agli oggetti. Quindi, mettere l'algoritmo di calcolo in una funzione separata è un passo logico.

E perché dovreste lavorare con gli array in una funzione integrata? Stiamo parlando della differenza nel costo della chiamata di una funzione personalizzata incorporata nel codice e una funzione esterna chiamata attraverso iCustom().

1. è esattamente l'efficienza risultante per i grandi progetti. È solo inferiore in termini di velocità.
2. Allo stesso modo. È l'efficienza finale che mi interessa. In caso di MQL, di solito è il tempo necessario per lo sviluppo più il tempo necessario per i test nel tester. Anche se i secondi extra di attesa del terminale per caricare il conto reale possono essere molto costosi. Voglio dire che i nervi, non tutti hanno la giusta visione del trading :)
 
Ecco uno script per verificare la differenza.
//+------------------------------------------------------------------+
//|                                        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);
  }
//+------------------------------------------------------------------+

Ed ecco i risultati dello script.





Come potete vedere, l'uso di una funzione separata è giustificato - la differenza di tempo per un ciclo di miliardi di passaggi è solo un secondo. Ma è molto più facile sviluppare il codice!
 
Qui c'è altro sul tema della ricerca dei parametri della regressione lineare. Preso da qui - Canale di regressione lineare
 
Rosh:
Qui c'è di più su come trovare i parametri di una regressione lineare. Preso da qui - Canale di regressione lineare

Ed ecco una funzione che implementa l'algoritmo descritto (forse qualcuno può 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 funzione si chiama così:

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

Si noti che se nX[nI] sono numeri a barre, allora l'incremento nI porta all'indietro! :)

Saluti,

Volt

 

C'èqualcosa che non va nel regno danese.

Ho dovuto cancellare il mio post precedente. C'è un errore nell'algoritmo.

So che molte persone usano questa procedura ma .... non riesce a trovare il motivo dell'errore AIUTATEMI.

Ecco lo script. I coefficienti A e B sono calcolati due volte.

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

Il risultato è il seguente

intercetta = -3.33333333 pendenza = 5.00000000

intercetta = -1102.16914108 pendenza = 0.00000091

Ed ecco lo stesso, ma calcolato in MathCad. In blu i risultati corrispondono, in rosso no (.

In Mathcad queste sono funzioni integrate, quindi molto probabilmente un errore in MT4, ma dove?

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

C'èqualcosa che non va nel regno danese.

Ho dovuto cancellare il mio post precedente. C'è un errore nell'algoritmo.

So che molte persone usano questa procedura ma .... non riesce a trovare il motivo dell'errore AIUTATEMI.

Ecco lo script. I coefficienti A e B sono calcolati due volte.

Il risultato è il seguente

intercetta = -3.33333333 pendenza = 5.00000000

intercetta = -1102.16914108 pendenza = 0.00000091

Ed ecco lo stesso, ma calcolato in MathCad. In blu i risultati corrispondono, in rosso no (.

Questa è una funzione integrata in Mathcad, quindi molto probabilmente un errore in MT4, ma dove?

Ecco cosa mostra Excel 2007




Quindi, potrebbe essere necessario controllare Matcad.

 

Una delle implementazioni di regressione lineare, il grado del polinomio è 20, il numero di punti di calcolo e l'offset del punto di partenza è impostato...

l'uscita è fatta usando un canale la cui profondità è impostata in punti... ad una profondità di 0 viene emessa solo la curva di regressione stessa

File: