Canal de régression linéaire

 

J'ai un indicateur de régression linéaire.

Comment intégrer son calcul dans l'EA et obtenir des données sur 0 barre ou sur 1.

J'ai essayé de faire comme ça :

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

Mais ça ne donne pas quelque chose...

Dossiers :
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++; } }
 
Même si vous n'utilisez pas la POO, je décomposerais le code en un certain nombre de fonctions pour qu'il ait un sens.
 

J'ai mis en œuvre un calcul de régression (pas seulement linéaire) sans aucun cycle. Plus précisément, un cycle n'est nécessaire qu'une seule fois pendant l'initialisation.
En conséquence, la vitesse de calcul est mille fois plus rapide.

Et le code est plus court.
Mais je suis désolé, je ne vais pas poster le code. C'est un secret.
Je dis juste que c'est réel.


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

J'ai implémenté le calcul de la régression (pas seulement linéaire) sans aucune boucle. Pour être plus exact, la boucle n'est nécessaire qu'une seule fois à l'initialisation.
En conséquence, la vitesse de calcul est mille fois plus rapide.

Et le code est plus court.
Mais je suis désolé, je ne vais pas poster le code. C'est un secret.
Je dis juste que c'est réel.

Le code est très simple. On ajoute les carrés actuels, on soustrait les carrés hors de l'intervalle. C'est tout. C'est tout le secret.)

Elle peut être encore plus intéressante, mais en suivant des principes différents.

 
Yuriy Asaulenko:

Le code est très simple. On ajoute les carrés actuels, on soustrait les carrés hors de l'intervalle. C'est tout. C'est le secret.)

drôle ))))
 
Nikolai Semko:
C'est drôle.)

Pour rendre la chose encore plus drôle, vous pourriez parler non pas de la chaîne, mais de la façon de faire une ligne de régression polynomiale sans cycles. Mais je ne vais certainement pas faire ça. Vous n'en avez pas besoin.

 
Nikolai Semko:

J'ai mis en œuvre un calcul de régression (pas seulement linéaire) sans aucun cycle. Plus précisément, le cycle n'est nécessaire qu'une seule fois à l'initialisation.
En conséquence, la vitesse de calcul est des milliers de fois plus rapide.

Et le code est plus court.
Mais je suis désolé, je ne vais pas poster le code. C'est un secret.
Je dis juste que c'est réel.

Des milliers de fois plus rapide, et sans boucle de valeurs d'entrée ? ??

Je n'y crois pas ! !!

Au minimum, une boucle des paramètres d'entrée est obligatoire !

 
Nikolai Semko:

J'ai mis en œuvre un calcul de régression (pas seulement linéaire) sans aucun cycle. Plus précisément, la boucle n'est nécessaire qu'une seule fois à l'initialisation.
En conséquence, la vitesse de calcul est mille fois plus rapide.

Et le code est plus court.
Mais je suis désolé, je ne vais pas poster le code. C'est un secret.
Je dis juste que c'est réel.


Et même sans une boucle de sommation x*y ? Et si x et y ne sont pas des lignes droites ?

 
Georgiy Merts:

Des milliers de fois plus rapide, et sans boucle de valeurs d'entrée ? ??

Je n'y crois pas ! !!

Au moins une boucle sur les paramètres d'entrée est obligatoire !

Dmitry Fedoseev:

Et même sans une boucle de sommation x*y ? Et si x et y ne sont pas des lignes droites ?

Ne le croyez pas pour ce qu'il vaut.
Rashid a laissé tomber les articles. Lisez-les attentivement. Il y a un lien vers un autre article :
https://www.mql5.com/ru/articles/270

Si vous vous creusez les méninges au niveau des maths de 7ème-8ème année, vous pouvez obtenir l'écart-type pour obtenir le canal, et pas seulement la moyenne glissante, d'une manière similaire sans cycle. Je l'ai implémenté pour un polynôme de n'importe quel degré, pas seulement du premier degré (régression linéaire). Vous pouvez le sentir dans la version de démonstration sur la place de marché.

HH j'ai écrit que la boucle est nécessaire une fois à l'initialisation.

Des milliers de fois plus rapide, y compris pour le calcul de l'écart-type (c'est-à-dire la largeur du canal).
Raison: