El lienzo es genial. - página 20

 
Anatoli Kazharski:

Hay una limitación. Se pueden hacer hasta 512 topes indicadores >>>https://www.mql5.com/ru/docs/indicators

Gracias.
Sí, además de la longitud del código, cientos de búferes de indicadores serían un terrible desperdicio de memoria. Mi variante utiliza un array con dimensión: número de barras en la pantalla + periodo máximo.
 
Nikolai Semko:

Un indicador ultrarrápido de cientos de medias móviles, implementado en Canvas.

100 líneas MA (paso de periodo 10) - tiempo de cálculo y visualización en pantalla - 4-7 milisegundos


1000 líneas MA (paso de periodo 1) - tiempo de cálculo y visualización - 20-30 milisegundos.


No he probado demasiado el código. Puede haber errores. Implementado sólo para barras de un píxel de grosor (se fuerza a esta escala). También la tasa de refresco de la pantalla no está optimizada. Todas las líneas se calculan y se emiten completamente en cada tic.

Como se entiende la media es simple? Ahora haría lo mismo con el exponencial.

 
Dmitry Fedoseev:

¿Cómo sabes que la media es simple? ¿Ahora harías lo mismo con una exponencial?

Esto es sólo un ejemplo de demostración. Se pueden aplicar todos los tipos de AM. Todo lo que necesitas es tu deseo y necesidad. El código se volverá un poco más complejo con el expotencial. Le sugiero que lo pruebe.
 

Para ilustrar la velocidad...

Cambio de dos parámetros a través del puntero del ratón

X - cambios en el periodo máximo de MA

Y - paso del cambio de periodo MA


#include <Canvas\iCanvas.mqh> //https://www.mql5.com/ru/code/22164
#property indicator_chart_window

double  Close[];
long Total;
int Ma=0;
int stepMa=0;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
int OnInit()
  {
   ChartSetInteger(0,CHART_SCALE,0,0);
   ChartSetInteger(0,CHART_FOREGROUND,true);
   CopyClose(_Symbol,_Period,(int)W.Right_bar,W.BarsInWind+Ma-1,Close);
   Total=SeriesInfoInteger(_Symbol,_Period,SERIES_BARS_COUNT);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,const int prev_calculated,const int begin,const double &price[])
  {
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| ChartEvent function                                              |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
                  const long &lparam,
                  const double &dparam,
                  const string &sparam)
  {
   static int MaOld=-1,stepMaOld=-1;
   Ma=W.MouseX+100;
   stepMa=W.MouseY;
   if(stepMa<=0) stepMa=1;
   stepMa=1+stepMa/10;
   if(stepMa>Ma) stepMa=Ma-1;
   if(id==CHARTEVENT_CHART_CHANGE || MaOld!=Ma || stepMaOld!=stepMa)
     {
      ChartSetInteger(0,CHART_SCALE,0,0);
      CopyClose(_Symbol,_Period,(int)W.Right_bar,W.BarsInWind+Ma-1,Close);
      nMA();
      MaOld=Ma; stepMaOld=stepMa;
     }
  }
//+------------------------------------------------------------------+

void nMA()
  {
   int preY=0;
   Canvas.Erase();
   double S=0;
   for(int i=0;i<Ma; i++) S+=Close[i];

   for(int Per=Ma;Per>0;)
     {
      double s=S;
      uint Clr=Grad((double)Per/Ma);
      for(int x=0; x<W.BarsInWind;x++)
        {
         int Y=(int)(Canvas.Y(s/Per)-0.5);
         if(x>0) if(fabs(Y-preY)>1) Canvas.Line(x-1,preY,x,Y,Clr);
         else Canvas.PixelSet(x,Y,Clr);
         if((Ma+x)<ArraySize(Close)) s=s-Close[x+Ma-Per]+Close[Ma+x]; else break;
         preY=Y;
        }
      for(int j=0; j<stepMa; j++) if(Per>0) {S=S-Close[Ma-Per]; Per--;} else break;
     }
   Canvas.Update();
  }
//+------------------------------------------------------------------+
uint Grad(double p)
  {
   static uint Col[6]={0xFF0000FF,0xFFFF00FF,0xFFFF0000,0xFFFFFF00,0xFF00FF00,0xFF00FFFF};
   if(p>0.9999) return Col[5];
   if(p<0.0001) return Col[0];
   p=p*5;
   int n=(int)p;
   double k=p-n;
   argb c1,c2;
   c1.clr=Col[n];
   c2.clr=Col[n+1];
   return ARGB(255,c1.c[2]+uchar(k*(c2.c[2]-c1.c[2])+0.5),
                   c1.c[1]+uchar(k*(c2.c[1]-c1.c[1])+0.5),
                   c1.c[0]+uchar(k*(c2.c[0]-c1.c[0])+0.5));
  }
//+------------------------------------------------------------------+
Archivos adjuntos:
MultiMA.mq5  8 kb
 
Nikolai Semko:

Para ilustrar la velocidad...

Cambio de dos parámetros a través del puntero del ratón

X - cambios en el periodo máximo de MA

Y - cambio de paso del periodo MA


Bonito, pero el compilador explota

can't open "..\MQL5\Include\Canvas\iCanvas.mqh" include file    MultiMA.mq5     9       11
 
Aleksey Vyazmikin:

Es hermoso, pero el compilador está luchando

La biblioteca debe estar instalada, por supuesto. Hay un enlace a esta biblioteca en el código.
 
Nikolai Semko:
La biblioteca debe estar instalada, por supuesto. Hay un enlace a esta biblioteca en el código.

Gracias. ¡Todo está funcionando!

¿Cómo puedo hacer que el indicador se redibuje/desplace cuando el gráfico se redibuja/desplaza?

 
Aleksey Vyazmikin:

Gracias. ¡Todo está funcionando!

¿Cómo consigo que el indicador se redibuje/desplace cuando el gráfico se redibuja/desplaza?

Es la forma en que funciona.
 
Nikolai Semko:
Así es como funciona la redistribución.

El mío sólo funciona cuando el ratón está en movimiento.

 
Aleksey Vyazmikin:

El mío sólo funciona cuando muevo el ratón.

Sí, había un pequeño error. Lo he arreglado.

Gracias por eso.