//+------------------------------------------------------------------+
//|                                                    Color_RSI.mq5 |
//+------------------------------------------------------------------+

// группа информационных свойств.
#property copyright "TheXpert"
#property link      "theforexpert@gmail.com"

#property version   "1.00"

// описание индикатора -- суммарно не должно превышать 511 символов
// с учетом символов перевода строки
#property description "      "
#property description "Демонстрация построения индикатора"
#property description "на примере раскрашивания RSI"

// свойства непосредственно индикатора
#property indicator_separate_window // индикатор будет отображен в отдельном подокне

//#property indicator_minimum 0
//#property indicator_maximum 100

#property indicator_buffers 4       // количество используемых буферов
#property indicator_plots 2         // количество отображаемых буферов

#property indicator_color1 DarkSalmon, DeepSkyBlue // используем 2 цвета
#property indicator_type1 DRAW_COLOR_LINE          // и специальный цветной тип отображения

#property indicator_color2 DarkSalmon, DeepSkyBlue // используем 2 цвета
#property indicator_type2 DRAW_COLOR_LINE          // и специальный цветной тип отображения

//---- buffers
double Values[];                    // буфер значений
double ValuesPainting[];            // буфер индексов цветов
double SmoothedValues[];            // буфер сглаженных значений
double SmoothedValuesPainting[];    // буфер индексов цветов
double BufferForCopy[];

// входные параметры индикатора
input string               _1             = "Параметры для RSI";
input int                  RSIPeriod      = 5;
input int                  SmoothPeriod   = 5;
input ENUM_APPLIED_PRICE   AppliedPrice   = PRICE_CLOSE;
input string               _2             = "Настройки цветов";
input color                Down           = DarkSalmon;
input color                Up             = DeepSkyBlue;

// переменная, в которой будет содержаться хэндл индикатора
int RSIHandle;
int SmoothHandle;

// функция инициализации индикатора
int OnInit()
{
   // регистрируем индикаторные буферы
   // Values как буфер для отображения
   SetIndexBuffer(0, Values,                 INDICATOR_DATA);
   // ValuesPainting как буфер для хранения цветов
   SetIndexBuffer(1, ValuesPainting,         INDICATOR_COLOR_INDEX);
   
   // Values как буфер для отображения
   SetIndexBuffer(2, SmoothedValues,         INDICATOR_DATA);
   // ValuesPainting как буфер для хранения цветов
   SetIndexBuffer(3, SmoothedValuesPainting, INDICATOR_COLOR_INDEX);

   // Устанавливаем начало рисования буфера Values
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, RSIPeriod);
   // Устанавливаем начало рисования буфера Values
   PlotIndexSetInteger(2, PLOT_DRAW_BEGIN, RSIPeriod + SmoothPeriod);
   // Устанавливаем имя индикатора
   IndicatorSetString(INDICATOR_SHORTNAME, "Цветной RSI(" + string(RSIPeriod) + "," + string(SmoothPeriod) + ")");
   // Устанавливаем пустое значение для буфера Values
   PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   PlotIndexSetDouble(2, PLOT_EMPTY_VALUE, EMPTY_VALUE);
   // Устанавливаем цвета буфера
   PlotIndexSetInteger(0, PLOT_LINE_COLOR, 0, Down);
   PlotIndexSetInteger(0, PLOT_LINE_COLOR, 1, Up);
   PlotIndexSetInteger(2, PLOT_LINE_COLOR, 0, Down);
   PlotIndexSetInteger(2, PLOT_LINE_COLOR, 1, Up);

   RSIHandle = iRSI(NULL, 0, RSIPeriod, AppliedPrice);
   SmoothHandle = iMA(NULL, 0, SmoothPeriod, 0, MODE_EMA, RSIHandle);
   
   ArrayResize(BufferForCopy, 3);

   // Устанавливаем порядок индексации буферов
   ArraySetAsSeries(Values, true);
   ArraySetAsSeries(ValuesPainting, true);
   ArraySetAsSeries(SmoothedValues, true);
   ArraySetAsSeries(SmoothedValuesPainting, true);
   ArraySetAsSeries(BufferForCopy, true);

   return(0);
}

// функция расчета даных
// параметры функции _можно_ переименовывать
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 toCount = (int)MathMin(rates_total, rates_total - prev_calculated + 1);
   
   // "умное" копирование данных, чтобы не копировать каждый раз целиком
   if (toCount <= 3)
   {
      int copied = CopyBuffer(RSIHandle, 0, 0, toCount, BufferForCopy);
      if (copied == -1)
      {
         Print("Ошибка во время копирования данных №", GetLastError());
         return 0;
      }
      
      for (int i = toCount - 1; i >= 0; --i)
      {
         Values[i] = BufferForCopy[i];
      }

      copied = CopyBuffer(SmoothHandle, 0, 0, toCount, BufferForCopy);
      if (copied == -1)
      {
         Print("Ошибка во время копирования сглаженных данных №", GetLastError());
         return 0;
      }
      
      for (int i = toCount - 1; i >= 0; --i)
      {
         SmoothedValues[i] = BufferForCopy[i];
      }
   }
   else
   {
      int copied = CopyBuffer(RSIHandle, 0, 0, rates_total, Values);
      if (copied == -1)
      {
         Print("Ошибка во время копирования данных №", GetLastError());
         return 0;
      }

      copied = CopyBuffer(SmoothHandle, 0, 0, rates_total, SmoothedValues);
      if (copied == -1)
      {
         Print("Ошибка во время копирования данных №", GetLastError());
         return 0;
      }
   }
   
   // раскрашивание. Да, теперь оно стало таким простым
   for (int i = toCount - 2; i >= 0; --i)
   {
      
      if (Values[i + 1] != EMPTY_VALUE && 
          Values[i] > Values[i + 1])   ValuesPainting[i] = 1;
      else                             ValuesPainting[i] = 0;

      if (SmoothedValues[i + 1] != EMPTY_VALUE &&
          SmoothedValues[i] > SmoothedValues[i + 1])  SmoothedValuesPainting[i] = 1;
      else                                            SmoothedValuesPainting[i] = 0;
   }

   return rates_total;
}
