Принудительная отрисовка индикатора

 

Есть самописный индикатор.

Задача проста - по заложенной логике отображает стрелку на графике (точку входа).

Всё работает, за одним нюансом: после установки на график необходимо принудительно сделать ПКМ - refresh на графике. То же действие необходимо провести и при смене ТФ.

После обновления всё прекрасно работает.

В чем моя ошибка?

//+------------------------------------------------------------------+
//|                                            ArrowStoch.mq5 |
//+------------------------------------------------------------------+
#property copyright "Copyright"
#property link      "https://test"
#property version   "1.00"
#property indicator_chart_window
#property indicator_buffers 4
#property indicator_plots   2

//--- plot ArrowUP
#property indicator_label1  "ArrowUP"
#property indicator_type1   DRAW_ARROW
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot ArrowDN
#property indicator_label2  "ArrowDN"
#property indicator_type2   DRAW_ARROW
#property indicator_color2  clrBlue
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1

//--- input parameters
input uint     InpPeriodSlow     =  200;    // Slow length
input uint     InpPeriodFast     =  50;    // Fast length
//--- indicator buffers
double         BufferMA50[];
double         BufferMA200[];
double         BufferArrowUP[];
double         BufferArrowDN[];
//double         BufferStoch[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   SetIndexBuffer(0,BufferArrowUP,INDICATOR_DATA);
   SetIndexBuffer(1,BufferArrowDN,INDICATOR_DATA);
   SetIndexBuffer(2,BufferMA50,INDICATOR_DATA);
   SetIndexBuffer(3,BufferMA200,INDICATOR_DATA);

   PlotIndexSetInteger(0,PLOT_ARROW,234);
   PlotIndexSetInteger(1,PLOT_ARROW,233);

   IndicatorSetString(INDICATOR_SHORTNAME,"Test");
   IndicatorSetInteger(INDICATOR_DIGITS,Digits());

   ArraySetAsSeries(BufferMA50,true);
   ArraySetAsSeries(BufferMA200,true);
   ArraySetAsSeries(BufferArrowUP,true);
   ArraySetAsSeries(BufferArrowDN,true);

   ArrayInitialize(BufferMA50,EMPTY_VALUE);
   ArrayInitialize(BufferMA200,EMPTY_VALUE);
   ArrayInitialize(BufferArrowUP,EMPTY_VALUE);
   ArrayInitialize(BufferArrowDN,EMPTY_VALUE);

//---
   return(INIT_SUCCEEDED);
  }

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
     {
      //--- Проверка и расчёт количества просчитываемых баров
      if(rates_total<InpPeriodSlow)
        {
         return 0;
        }
      int limit=rates_total-prev_calculated;
      if(limit>1)
        {
         limit=rates_total-InpPeriodSlow-1;

        }
      //--- Установка массивов буферов как таймсерий
      ArraySetAsSeries(open,true);
      ArraySetAsSeries(high,true);
      ArraySetAsSeries(low,true);
      ArraySetAsSeries(close,true);
      ArraySetAsSeries(time,true);

      for(int i=limit; i>=0 && !IsStopped(); i--)
        {
         double MA50=MA(InpPeriodFast, i+1);
         double MA200=MA(InpPeriodSlow, i+1);
         double stochK = STOCH(i+1,0); //The buffer numbers: 0 - MAIN_LINE, 1 - SIGNAL_LINE.
         double stochD = STOCH(i+1,1); //The buffer numbers: 0 - MAIN_LINE, 1 - SIGNAL_LINE.

         double stochK2 = STOCH(i+2,0); //The buffer numbers: 0 - MAIN_LINE, 1 - SIGNAL_LINE.
         double stochD2 = STOCH(i+2,1); //The buffer numbers: 0 - MAIN_LINE, 1 - SIGNAL_LINE.

         bool Cross = (stochK2 < stochD2 && stochD > stochK) || (stochK2 > stochD2 && stochD < stochK);

         BufferArrowUP[i+1]=BufferArrowDN[i+1]=EMPTY_VALUE;
         if(close[i+1]>MA50 && close[i+1]>MA200 && MA50>MA200 && (stochK <=20 && stochD<=20 && Cross)) //for buy
           {
            BufferArrowDN[i+1]=low[i+1]-2*Point();
            BufferArrowUP[i+1]=EMPTY_VALUE;
           }
         if(close[i+1]<MA50 && close[i+1]<MA200 && MA50<MA200 && (stochK >=80 && stochD >=80 && Cross)) //for sell
           {
            BufferArrowUP[i+1]=high[i+1]+2*Point();
            BufferArrowDN[i+1]=EMPTY_VALUE;
           }
        }
     }

   return(rates_total);
  }
double MA(int period, int start)
  {
   double array[];
   double val=EMPTY_VALUE;
   ArraySetAsSeries(array,true);
   int ind=iMA(NULL, PERIOD_CURRENT, period,0, MODE_SMA, PRICE_CLOSE);
   int n=CopyBuffer(ind,0, start, 1, array);
   if(n<1)
      return(false);
   val=array[0]; // скопировали значение индикатора
   return val;

  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double STOCH(int start, int buf_number)
  {
   double array[];
   double val=EMPTY_VALUE;
   ArraySetAsSeries(array,true);
   int ind=iStochastic(NULL, PERIOD_CURRENT, 14,3,3,MODE_SMA, STO_LOWHIGH);
   int n=CopyBuffer(ind,buf_number, start, 1, array);
   if(n<1)
      return(false);
   val=array[0]; // скопировали значение индикатора
   return val;
  }
 

Эта конструкция не работает

   int expBars=0;
   if(expBars!=Bars(NULL, PERIOD_CURRENT))
     {
      expBars=Bars(NULL, PERIOD_CURRENT);
при каждом заходе в функцию переменная будет равна 0 и присваивание никчему. см. static
 
Sofiia Butenko:

Эта конструкция не работает

при каждом заходе в функцию переменная будет равна 0 и присваивание никчему. см. static

Тут согласен, переменную надо было вынести за пределы функции.

Но даже если убрать вообще вызов этой функции, ничего не изменится.

 
firsalex:

Тут согласен, переменную надо было вынести за пределы функции.

Но даже если убрать вообще вызов этой функции, ничего не изменится.

Вот в индикаторе "Новый бар"

   int limit=rates_total-prev_calculated;

   if(limit==0)
      return rates_total;
 

Коллеги, уберем функцию isNewBar, я ее исключил из кода. Проблемы это не решает.


Непонятно поведение индикатора. Суть простая - если Close выше/ниже двух МА (200 и 50) И показания стохастика в экстремальных зонах (есть пересечение) - рисуем стрелку. Это что касается "логики".

По коду - специально сравнивал с кодом встроенных индикаторов - везде также в OnInit идет SetIndexBuffer, PlotIndexSetInteger, ArraySetAsSeries, ArrayInitialize, то есть при инициализации (первичная, смена ТФ) создаются массивы, инициализируются и пошла "логика" в OnCalculate.

Не могу понять, в чем баг в коде...