Canal de regresión lineal

 

Tengo un indicador de regresión lineal.

Cómo construir su cálculo en el EA y obtener datos en 0 bar o en 1.

Intenté hacerlo así:

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

Pero no da algo...

Archivos adjuntos:
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++; } }
 
Incluso si usted no utiliza la POO - yo dividiría el código en una serie de funciones para que tenga sentido.
 

He implementado el cálculo de regresión (no sólo lineal) sin ciclos en absoluto. Más concretamente, sólo se necesita un ciclo durante la inicialización.
Como resultado, la velocidad de cálculo es mil veces más rápida.

Y el código es más corto.
Pero lo siento, no voy a publicar el código. Es un secreto.
Sólo digo que es real.


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

He implementado el cálculo de la regresión (no sólo lineal) sin ningún tipo de bucle. Para ser más exactos, el bucle sólo se necesita una vez en la inicialización.
Como resultado, la velocidad de cálculo es mil veces más rápida.

Y el código es más corto.
Pero lo siento, no voy a publicar el código. Es un secreto.
Sólo digo que es real.

El código es muy sencillo. Sumamos los cuadrados actuales, restamos los cuadrados fuera del intervalo. Eso es todo. Ese es todo el secreto).

Puede ser aún más interesante, pero siguiendo principios diferentes.

 
Yuriy Asaulenko:

El código es muy sencillo. Sumamos los cuadrados actuales, restamos los cuadrados fuera del intervalo. Eso es todo. Ese es el secreto).

divertido )))
 
Nikolai Semko:
Es gracioso ))

Para hacerlo aún más divertido, podrías contar no sobre el canal, sino sobre cómo hacer una línea de regresión polinómica sin ciclos. Pero definitivamente no voy a hacer eso. No lo necesitas.

 
Nikolai Semko:

He implementado el cálculo de regresión (no sólo lineal) sin ciclos en absoluto. En concreto, el ciclo es necesario sólo una vez en la inicialización.
Como resultado, la velocidad de cálculo es miles de veces más rápida.

Y el código es más corto.
Pero lo siento, no voy a publicar el código. Es un secreto.
Sólo digo que es real.

Miles de veces más rápido, y sin un bucle de valores de entrada...

¡¡¡No me lo creo!!!

Como mínimo, es obligatorio un bucle de parámetros de entrada.

 
Nikolai Semko:

He implementado el cálculo de regresión (no sólo lineal) sin ciclos en absoluto. Más concretamente, el bucle sólo se necesita una vez en la inicialización.
Como resultado, la velocidad de cálculo es mil veces más rápida.

Y el código es más corto.
Pero lo siento, no voy a publicar el código. Es un secreto.
Sólo digo que es real.


E incluso sin un bucle de suma x*y? ¿Y si x e y no son líneas rectas?

 
Georgiy Merts:

Miles de veces más rápido, y sin un bucle de valores de entrada...

¡¡¡No me lo creo!!!

¡Al menos un bucle sobre los parámetros de entrada es obligatorio!

Dmitry Fedoseev:

E incluso sin un bucle de suma x*y ? ¿Y si x e y no son líneas rectas?

No te lo creas a pies juntillas.
Rashid dejó caer los artículos. Léalos con atención. Allí hay un enlace a otro artículo:
https://www.mql5.com/ru/articles/270

Si te devanas los sesos al nivel de las matemáticas de 7º-8º grado, puedes obtener la desviación estándar para obtener el canal, no sólo la media deslizante, de forma similar sin un ciclo. Lo tengo implementado para un polinomio de cualquier grado, no sólo del primer grado (regresión lineal). Puedes sentirlo en la versión demo en el mercado.

HH escribí que el bucle es necesario una vez en la inicialización.

Miles de veces más rápido: esto incluye el cálculo de la desviación estándar (es decir, la anchura del canal)