Canale di regressione lineare

 

Ho un indicatore di regressione lineare.

Come costruire il suo calcolo nell'EA e ottenere dati su 0 bar o su 1.

Ho cercato di fare così:

enum ENUM_Polynomial
  {
   linear=1,      // linear 
   parabolic=2,   // parabolic 
   Third_power=3, // third-power 
  };
input ENUM_Polynomial degree=linear;
input double kstd=2.0;
input int bars=250;
input int shift=0;

double Ask,Bid;
double h,l;
double sqh_buffer[];
double fx_buffer[];
double sql_buffer[];
double close[];

double ai[10,10],b[10],x[10],sx[20];
double sum;
int p,n,f;
double qq,mm,tt;
int ii,jj,kk,ll,nn;
double sq;

int i0=0;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   
   ArrayResize(fx_buffer,1000);
   ArrayResize(sqh_buffer,1000);
   ArrayResize(sql_buffer,1000);
   
   ArraySetAsSeries(fx_buffer,true);
   ArraySetAsSeries(sqh_buffer,true);
   ArraySetAsSeries(sql_buffer,true);
   
   ArrayResize(close,1000);
   ArraySetAsSeries(close,false);
   
   
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlTick Tick;
   SymbolInfoTick(_Symbol,Tick);

   Ask = Tick.ask;
   Bid = Tick.bid;
   
   
   iStdev
   for (int i =0; i<1000;i++)
   {
     // Print (i, "   ",ArraySize(close)); 
    close[i] = iClose(_Symbol,0,0);
   }
   
  // ArraySetAsSeries(close,true);
   int mi;
   p=bars;
   sx[1]=p+1;
   nn=degree+1;
   
   //--- sx 
   for(mi=1;mi<=nn*2-2;mi++)
     {
      sum=0;
      for(n=i0;n<=i0+p;n++)
        {
         sum+=MathPow(n,mi);
        }
      sx[mi+1]=sum;
     }
//--- syx 
   for(mi=1;mi<=nn;mi++)
     {
      sum=0.00000;
      for(n=i0;n<=i0+p;n++)
        {
         if(mi==1)
            sum+=close[n];
         else
            sum+=close[n]*MathPow(n,mi-1);
        }
      b[mi]=sum;
     }
//--- Matrix 
   for(jj=1;jj<=nn;jj++)
     {
      for(ii=1; ii<=nn; ii++)
        {
         kk=ii+jj-1;
         ai[ii,jj]=sx[kk];
        }
     }
//--- Gauss 
   for(kk=1; kk<=nn-1; kk++)
     {
      ll=0;
      mm=0;
      for(ii=kk; ii<=nn; ii++)
        {
         if(MathAbs(ai[ii,kk])>mm)
           {
            mm=MathAbs(ai[ii,kk]);
            ll=ii;
           }
        }
     
      if(ll!=kk)
        {
         for(jj=1; jj<=nn; jj++)
           {
            tt=ai[kk,jj];
            ai[kk,jj]=ai[ll,jj];
            ai[ll,jj]=tt;
           }
         tt=b[kk];
         b[kk]=b[ll];
         b[ll]=tt;
        }
      for(ii=kk+1;ii<=nn;ii++)
        {
         qq=ai[ii,kk]/ai[kk,kk];
         for(jj=1;jj<=nn;jj++)
           {
            if(jj==kk)
               ai[ii,jj]=0;
            else
               ai[ii,jj]=ai[ii,jj]-qq*ai[kk,jj];
           }
         b[ii]=b[ii]-qq*b[kk];
        }
     }
   x[nn]=b[nn]/ai[nn,nn];
   for(ii=nn-1;ii>=1;ii--)
     {
      tt=0;
      for(jj=1;jj<=nn-ii;jj++)
        {
         tt=tt+ai[ii,ii+jj]*x[ii+jj];
         x[ii]=(1/ai[ii,ii])*(b[ii]-tt);
        }
     }
//---
   for(n=i0;n<=i0+p;n++)
     {
      sum=0;
      for(kk=1;kk<=degree;kk++)
        {
         sum+=x[kk+1]*MathPow(n,kk);
        }
      fx_buffer[n]=x[1]+sum;
     }
//--- Std 
   sq=0.0;
   for(n=i0;n<=i0+p;n++)
     {
      sq+=MathPow(close[n]-fx_buffer[n],2);
     }
   sq=MathSqrt(sq/(p+1))*kstd;

   for(n=i0;n<=i0+p;n++)
     {
      sqh_buffer[n]=fx_buffer[n]+sq;
      sql_buffer[n]=fx_buffer[n]-sq;
     }
     
     h = sqh_buffer[
0];
     l = sql_buffer[0];

Ma non dà qualcosa...

File:
i-Regr.mq5  12 kb
 
void calcPolynomialRegression(double &PricesArray[],double &RegressionArray[], int power) {
 ArrayResize(RegressionArray, ArraySize(PricesArray)); ArraySetAsSeries(RegressionArray,ArrayGetAsSeries(PricesArray));
 double summ_x_value[21],summ_y_value[11],constant[11],matrix[11][11];
 ArrayInitialize(summ_x_value,0); ArrayInitialize(summ_y_value,0);
 ArrayInitialize(constant,0); ArrayInitialize(matrix,0);

 double summ=0,summ_x=0,summ_y=0;
 int pos=ArraySize(PricesArray)-1;
 summ_x_value[0]=ArraySize(PricesArray);
 for(int exp_n=1; exp_n<=2*power; exp_n++) {
  summ_x=0;
  summ_y=0;
  for(int k=1; k<=ArraySize(PricesArray); k++) {
   summ_x+=MathPow(k,exp_n);
   if(exp_n==1) summ_y+=PricesArray[pos-k+1];
   else if(exp_n<=power+1) summ_y+=PricesArray[pos-k+1]*MathPow(k,exp_n-1); }
  summ_x_value[exp_n]=summ_x;
  if(summ_y!=0) summ_y_value[exp_n-1]=summ_y; }

 for(int row=0; row<=power; row++)
  for(int col=0; col<=power; col++)
    matrix[row][col]=summ_x_value[row+col];

 int initial_row=1;
 int initial_col=1;
 for(int i=1; i<=power; i++) {
  for(int row=initial_row; row<=power; row++) {
   summ_y_value[row]=summ_y_value[row]-(matrix[row][i-1]/matrix[i-1][i-1])*summ_y_value[i-1];
   for(int col=initial_col; col<=power; col++)
     matrix[row][col]=matrix[row][col]-(matrix[row][i-1]/matrix[i-1][i-1])*matrix[i-1][col]; }
   initial_col++;
   initial_row++; }
   
 int j=0;
 for(int i=power; i>=0; i--) {
  if(j==0) constant[i]=summ_y_value[i]/matrix[i][i];
  else {
   summ=0;
   for(int k=j; k>=1; k--) summ+=constant[i+k]*matrix[i][i+k];
   constant[i]=(summ_y_value[i]-summ)/matrix[i][i]; }
  j++; }
  
 int k=1;
 for(int i=ArraySize(PricesArray)-1; i>=0; i--) {
  summ=0;
  for(int n=0; n<=power; n++) summ+=constant[n]*MathPow(k,n);
  RegressionArray[i]=summ;
  k++; } }
 
Anche se non usi OOP - romperei il codice in un certo numero di funzioni per dare un senso.
 

Ho implementato il calcolo della regressione (non solo lineare) senza cicli. Più precisamente, un ciclo è necessario solo una volta durante l'inizializzazione.
Di conseguenza, la velocità di calcolo è mille volte più veloce.

E il codice è più corto.
Ma mi dispiace, non posterò il codice. È un segreto.
Sto solo dicendo che è reale.


 
Пример разработки спредовой стратегии на фьючерсах Московской биржи
Пример разработки спредовой стратегии на фьючерсах Московской биржи
  • www.mql5.com
MetaTrader 5 позволяет разрабатывать и тестировать роботов, торгующих одновременно на нескольких инструментах. Встроенный в платформу тестер стратегий автоматически скачивает с торгового сервера брокера тиковую историю и учитывает спецификацию контрактов  —  разработчику ничего не нужно делать руками. Это позволяет легко и максимально...
 
Nikolai Semko:

Ho implementato il calcolo della regressione (non solo lineare) senza cicli. Per essere più precisi, il ciclo è necessario solo una volta all'inizializzazione.
Di conseguenza, la velocità di calcolo è mille volte più veloce.

E il codice è più corto.
Ma mi dispiace, non posterò il codice. È un segreto.
Sto solo dicendo che è reale.

Il codice è molto semplice. Aggiungiamo i quadrati attuali, sottraiamo i quadrati fuori dall'intervallo. Questo è tutto. Questo è tutto il segreto).

Può essere ancora più interessante, ma seguendo principi diversi.

 
Yuriy Asaulenko:

Il codice è molto semplice. Aggiungiamo i quadrati attuali, sottraiamo i quadrati fuori dall'intervallo. Questo è tutto. Questo è il segreto).

divertente )))
 
Nikolai Semko:
Questo è divertente ))

Per renderlo ancora più divertente, si potrebbe raccontare non del canale, ma di come fare una linea di regressione polinomiale senza cicli. Ma sicuramente non lo farò. Non ne hai bisogno.

 
Nikolai Semko:

Ho implementato il calcolo della regressione (non solo lineare) senza cicli. Più precisamente il ciclo è necessario solo una volta all'inizializzazione.
Di conseguenza, la velocità di calcolo è migliaia di volte più veloce.

E il codice è più corto.
Ma mi dispiace, non posterò il codice. È un segreto.
Sto solo dicendo che è reale.

Migliaia di volte più veloce, e senza un ciclo di valori di input?

Non ci credo!!!

Come minimo, un ciclo di parametri di input è obbligatorio!

 
Nikolai Semko:

Ho implementato il calcolo della regressione (non solo lineare) senza cicli. Più precisamente, il ciclo è necessario solo una volta all'inizializzazione.
Di conseguenza, la velocità di calcolo è mille volte più veloce.

E il codice è più corto.
Ma mi dispiace, non posterò il codice. È un segreto.
Sto solo dicendo che è reale.


E anche senza un ciclo di somma x*y? E se x e y non sono linee rette?

 
Georgiy Merts:

Migliaia di volte più veloce, e senza un ciclo di valori di input?

Non ci credo!!!

Almeno un ciclo sui parametri di ingresso è obbligatorio!

Dmitry Fedoseev:

E anche senza un ciclo di somma x*y ? E se x e y non sono linee rette?

Non crederci per tutto il suo valore.
Rashid ha fatto cadere gli articoli. Leggeteli attentamente. Lì c'è un link ad un altro articolo:
https://www.mql5.com/ru/articles/270

Se vi scervellate a livello di matematica di 7°-8° grado, potete ottenere la deviazione standard per ottenere il canale, non solo la media scorrevole, in un modo simile senza un ciclo. Ho implementato questo per un polinomio di qualsiasi grado, non solo il primo grado (regressione lineare). Lo si può sentire nella versione demo sul mercato.

HH ho scritto che il ciclo è necessario una volta all'inizializzazione.

Migliaia di volte più veloce - questo include il calcolo della deviazione standard (cioè la larghezza del canale)
Motivazione: