Canvas is cool! - page 20

 
Anatoli Kazharski:

There is a limitation. Up to 512 indicator buffers can be made >>>https://www.mql5.com/ru/docs/indicators

Thank you.
Yes, in addition to the code length, hundreds of indicator buffers would be an awful waste of memory. My variant uses one array with dimension: number of bars on the screen + max. period.
 
Nikolai Semko:

An ultra-fast indicator of hundreds of moving averages, implemented on Canvas.

100 MA lines (period step 10) - time of calculation and displaying on the screen - 4-7 milliseconds


1000 MA lines (period step 1) - time for calculation and display - 20-30 milliseconds.


I haven't tested the code too much. There may be bugs. Implemented only for one pixel thick bar (it is forced to this scale). Also screen refresh rate is not optimized. All lines are calculated and completely output at every tick.

As understood the average is simple? Now would do the same for exponential.

 
Dmitry Fedoseev:

How do you know the average is simple? Now would you do the same for an exponential?

This is just a demo example. All types of MA can be implemented. All you need is your desire and necessity. The code will become a bit more complex with expotential. I suggest you give it a try.
 

To illustrate the speed...

Changing two parameters via the mouse pointer

X - maximum MA period changes

Y - step of MA period change


#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));
  }
//+------------------------------------------------------------------+
Files:
MultiMA.mq5  8 kb
 
Nikolai Semko:

To illustrate the speed...

Changing two parameters via the mouse pointer

X - maximum MA period changes

Y - step of period of MA


Pretty, but the compiler blows up

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

It's beautiful, but the compiler is fighting

The library needs to be installed, of course. There is a link to this library in the code.
 
Nikolai Semko:
The library needs to be installed, of course. There is a link to this library in the code.

Thank you! It's all working!

How do I make the indicator red raw/shift when the chart is redrawn/shifted?

 
Aleksey Vyazmikin:

Thank you! It's all working!

How do I get the indicator to redraw/shift when the chart is redrawn/shifted?

It's the way it works.
 
Nikolai Semko:
That's how redrawing works.

Mine only works when the mouse is moving.

 
Aleksey Vyazmikin:

Mine only works when I move the mouse.

Yes, there was a little bug. Fixed it.

Thanks for that.