Canvas - это круто! - страница 20

Nikolai Semko
8291
Nikolai Semko  
Anatoli Kazharski:

Ограничение есть. До 512 индикаторных буфера можно сделать >>> https://www.mql5.com/ru/docs/indicators

Спасибо.
Да, через сотни индикаторных буферов еще кроме длины кода еще будет жуткая расточительность памяти. В моем варианте же используется один массив размерностью: кол-бар на экране + макс. период.
Dmitry Fedoseev
62783
Dmitry Fedoseev  
Nikolai Semko:

Сверхбыстрый индикатор из сотен скользящих средних, реализованный на Canvas.

100 линий MA(шаг периода 10) - время расчета и вывода на экран - 4-7 миллисекунд


1000 линий MA(шаг периода 1) - время расчета и вывода на экран - 20-30 миллисекунд


код сильно не тестировал. Могут быть баги. Реализовано только для бара в толщину один пиксель (переводится принудительно в такой масштаб). Также не оптимизированна частота обновления экрана. Все линии расчитываются и полностью выводятся при каждом тике. 

Как понял средняя простая? А вот теперь бы тоже самое для экспоненциальной

Nikolai Semko
8291
Nikolai Semko  
Dmitry Fedoseev:

Как понял средняя простая? А вот теперь бы тоже самое для экспоненциальной. 

Это только демонстрационеый пример. Можно все типы МА реализовать. Нужно только желание и потребность. С экспотенциальной код слегка усложнится. Предлагаю Вам попробовать.
Nikolai Semko
8291
Nikolai Semko  

Для наглядности скорости...

Изменение двух параметров через указатель мыши 

X - меняется максимальный период МА

Y - шаг изменения периода МА


#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));
  }
//+------------------------------------------------------------------+
Файлы:
MultiMA.mq5  8 kb
Aleksey Vyazmikin
17792
Aleksey Vyazmikin  
Nikolai Semko:

Для наглядности скорости...

Изменение двух параметров через указатель мыши 

X - меняется максимальный период МА

Y - шаг изменения периода МА


Красиво, но компилятор ругается

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

Красиво, но компилятор ругается

библу нужно установить конечно. В коде ссылка на эту библиотеку есть.
Aleksey Vyazmikin
17792
Aleksey Vyazmikin  
Nikolai Semko:
библу нужно установить конечно. В коде ссылка на эту библиотеку есть.

Спасибо! Всё заработало!

А как сделать, что бы при перерисовке/сдвиге чарта происходило перерисовка индикатора?

Nikolai Semko
8291
Nikolai Semko  
Aleksey Vyazmikin:

Спасибо! Всё заработало!

А как сделать, что бы при перерисовке/сдвиге чарта происходило перерисовка индикатора?

Так работает же перерисовка. 
Aleksey Vyazmikin
17792
Aleksey Vyazmikin  
Nikolai Semko:
Так работает же перерисовка. 

У меня работает только при движении мышью.

Nikolai Semko
8291
Nikolai Semko  
Aleksey Vyazmikin:

У меня работает только при движении мышью.

Да, был маленький косячок. Исправил.

Спасибо.