indicator working so slow, how to fix

 
//+------------------------------------------------------------------+
//|                                                   VWRSI.mq4      |
//|                        Пользовательский индикатор для MT4        |
//+------------------------------------------------------------------+
#property indicator_separate_window
#property indicator_minimum 0
#property indicator_maximum 100
#property indicator_buffers 1
#property indicator_color1 Blue

// Временные буферы для индикатора
double VWRSIBuffer[];

// Входные параметры индикатора
input int period = 14; // Период RSI

//+------------------------------------------------------------------+
//| Инициализация индикатора                                         |
//+------------------------------------------------------------------+
int OnInit()
  {
   SetIndexBuffer(0, VWRSIBuffer); // Устанавливаем буфер для вывода индикатора
   SetIndexStyle(0, DRAW_LINE);    // Рисуем линию
   IndicatorShortName("VWRSI("+IntegerToString(period)+")");

   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[])
  {
   // Объявляем необходимые переменные
   int start = (prev_calculated > period) ? prev_calculated - 1 : period;
   double gain, loss, weighted_gain, weighted_loss, vol_sum;
   
   // Цикл расчета индикатора
   for(int i = 0; i < rates_total - 1; i++) // -1 чтобы избежать выхода за пределы массива
   {
      gain = 0.0;
      loss = 0.0;
      weighted_gain = 0.0;
      weighted_loss = 0.0;
      vol_sum = 0.0;

      // Расчет прироста и убытков
      for(int j = 0; j < period; j++)
      {
         double price_change = close[i + j] - close[i + j + 1]; // Изменение цены между текущим и предыдущими барами
         double volume_tick = tick_volume[i + j]; // Объем

         if(price_change > 0)
         {
            gain += price_change;
            weighted_gain += price_change * volume_tick; // Взвешенный объем
         }
         else
         {
            loss -= price_change;
            weighted_loss -= price_change * volume_tick; // Взвешенный объем
         }

         vol_sum += volume_tick;
      }

      // Расчет взвешенного RSI на основе объема
      double avg_gain = weighted_gain / vol_sum;
      double avg_loss = weighted_loss / vol_sum;

      if(avg_loss == 0)
         VWRSIBuffer[i] = 100;
      else
         VWRSIBuffer[i] = 100 - (100 / (1 + avg_gain / avg_loss));
   }

   return(rates_total);
  }
//+------------------------------------------------------------------+

is there a way to fix it?

 
How about looking at the starting point of your for loops
 
Gerard Willia G J B M Dinh Sy #:
How about looking at the starting point of your for loops

so yeah, that's the issue, trying to fix it for 2 days. It calculates for whole history in every tick. I was trying to fix it but got another issue. I have a shift for indicator equals amount of periods

 
Look in codebase for any indicator code. What you're looking for is very simple
 
Gerard Willia G J B M Dinh Sy #:
Look in codebase for any indicator code. What you're looking for is very simple

was looking for that. haven't find it. needed volume weighted rsi. there no in codebase

 

in this case, what do you mean by slow? I just tried it on MT4, there is no lag problem at all, and no slowness seen in the strategy tester


If you mean that the plot is not up to the current bar, then just make a decremental loop instead and it will fix that problem



//+-------------------------------------------------------------------+ 
//|                                                  VWRSI
//|                     
//+-------------------------------------------------------------------+ 
#property indicator_separate_window 
#property indicator_minimum  0 
#property indicator_maximum  100 
#property indicator_buffers  1 
#property indicator_color1 clrSkyBlue
#property indicator_level1     30.0
#property indicator_level2     70.0
#property indicator_levelcolor clrSilver
#property indicator_levelstyle STYLE_DOT


double VWRSIBuffer[];


input  int period = 14 ; // RSI period


int  OnInit ()
  {
   SetIndexBuffer ( 0 , VWRSIBuffer); // Set the buffer for indicator output 
   SetIndexStyle( 0 , DRAW_LINE );     // Draw the line 
     
   IndicatorShortName( "VWRSI(" + IntegerToString (period)+ ")" );

   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[])
  {

    double gain, loss, weighted_gain, weighted_loss, vol_sum;
   
   // Indicator calculation loop 
   for ( int i = rates_total-1 ; i >= 0 ; i--) // -1 to avoid array overrun
   {
      gain = 0.0;
      loss = 0.0;
      weighted_gain = 0.0;
      weighted_loss = 0.0;
      vol_sum = 0.0;

      for ( int j = 0 ; j < period; j++)
      {
         double price_change = close[i + j] - close[i + j + 1 ]; // Price change between current and previous bars 
         double volume_tick = tick_volume[i + j]; // Volume

         if(price_change > 0)
         {
            gain += price_change;
            weighted_gain += price_change * volume_tick; // Weighted volume
         }
         else
         {
            loss -= price_change;
            weighted_loss -= price_change * volume_tick; // Weighted volume
         }

         vol_sum += volume_tick;
      }

      double avg_gain = weighted_gain / vol_sum;
       double avg_loss = weighted_loss / vol_sum;

      if(avg_loss == 0)
         VWRSIBuffer[i] = 100;
      else
         VWRSIBuffer[i] = 100 - (100 / (1 + avg_gain / avg_loss));
   }

   return(rates_total);
  }


you can do this for the main loop (as optimization)

  for ( int i = start; i >= 0 ; i--)