ArraySort

Сортирует многомерный числовой массив по возрастанию значений в первом измерении.

bool  ArraySort(
   void&  array[]      // массив для сортировки
   );

Параметры

array[]

[in][out]  Числовой массив для сортировки.

Возвращаемое значение

Возвращает true в случае успеха, иначе false.

Примечание

Массив всегда сортируется по возрастанию, независимо от значения флага AS_SERIES.

Функции ArraySort и ArrayBSearch принимают в качестве параметра массив любой размерности, при этом сортировка и поиск происходят только по первому (нулевому) измерению.

Пример:

#property description "Индикатор анализирует данные за последний месяц и раскрашивает все свечи с малыми"
#property description "и большими тиковыми объемами. Для определения таких свечей производится сортировка"
#property description "массива тиковых объемов. Свечи, объемы которых составляют первые InpSmallVolume"
#property description "процентов массива, считаются малыми. Свечи, тиковые объемы которых составляют "
#property description "последние InpBigVolume процентов массива, считаются большими."
//--- настройки индикатора
#property indicator_chart_window
#property indicator_buffers 5
#property indicator_plots   1
//--- plot
#property indicator_label1  "VolumeFactor"
#property indicator_type1   DRAW_COLOR_CANDLES
#property indicator_color1  clrDodgerBlue,clrOrange
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2
//--- предопределенная константа
#define INDICATOR_EMPTY_VALUE 0.0
//--- входные параметры
input int InpSmallVolume=15; // Процент малых объемов (<50)
input int InpBigVolume=80;   // Процент больших объемов (<50)
//--- время начала анализа (будет смещаться)
datetime ExtStartTime;
//--- индикаторные буферы
double   ExtOpenBuff[];
double   ExtHighBuff[];
double   ExtLowBuff[];
double   ExtCloseBuff[];
double   ExtColorBuff[];
//--- граничные значения объемов для отображения свечей
long     ExtLeftBorder=0;
long     ExtRightBorder=0;
//+------------------------------------------------------------------+
//| Получение значений границ для тиковых объемов                    |
//+------------------------------------------------------------------+
bool GetVolumeBorders(void)
  {
//--- переменные
   datetime stop_time;  // время окончания копирования
   long     buff[];     // буфер, куда будем копировать
//--- время окончания - текущее время
   stop_time=TimeCurrent();
//--- время начала - на месяц раньше от текущего
   ExtStartTime=GetStartTime(stop_time);
//--- получим значения тиковых объемов
   ResetLastError();
   if(CopyTickVolume(Symbol(),Period(),ExtStartTime,stop_time,buff)==-1)
     {
      //--- не удалось получить данные, вернем false для запуска команды на пересчет
      PrintFormat("Не удалось получить значения тикового объема. Код ошибки = %d",GetLastError());
      return(false);
     }
//--- вычислим размер массива
   int size=ArraySize(buff);
//--- отсортируем массив
   ArraySort(buff);
//--- определим значения левой и правой границы для тиковых объемов
   ExtLeftBorder=buff[size*InpSmallVolume/100];
   ExtRightBorder=buff[(size-1)*(100-InpBigVolume)/100];
//--- успешное выполнение
   return(true);
  }
//+------------------------------------------------------------------+
//| Получение даты на месяц меньше чем дата во входном параметре     |
//+------------------------------------------------------------------+
datetime GetStartTime(const datetime stop_time)
  {
//--- преобразуем время окончания к переменной структуры типа MqlDateTime
   MqlDateTime temp;
   TimeToStruct(stop_time,temp);
//--- получим дату на месяц меньше
   if(temp.mon>1)
      temp.mon-=1;  // текущий месяц не первый в году, значит номер предыдущего на один меньше
   else
     {
      temp.mon=12;  // текущий месяц первый в году, значит номер предыдущего равен 12
      temp.year-=1; // а номер года на один меньше
     }
//--- число дня будет не больше 28
   if(temp.day>28)
      temp.day=28;
//--- вернем полученную дату
   return(StructToTime(temp));
  }
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- проверка, удовлетворяют ли входные параметры условиям
   if(InpSmallVolume<0 || InpSmallVolume>=50 || InpBigVolume<0 || InpBigVolume>=50)
     {
      Print("Некорректные входные параметры");
      return(INIT_PARAMETERS_INCORRECT);
     }
//--- indicator buffers mapping
   SetIndexBuffer(0,ExtOpenBuff);
   SetIndexBuffer(1,ExtHighBuff);
   SetIndexBuffer(2,ExtLowBuff);
   SetIndexBuffer(3,ExtCloseBuff);
   SetIndexBuffer(4,ExtColorBuff,INDICATOR_COLOR_INDEX);
//--- зададим значение, которое не будет отображаться
   PlotIndexSetDouble(0,PLOT_EMPTY_VALUE,INDICATOR_EMPTY_VALUE);
//--- зададим надписи для индикаторных буферов
   PlotIndexSetString(0,PLOT_LABEL,"Open;High;Low;Close");
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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(prev_calculated<rates_total)
     {
      //--- получение новых значений левой и правой границы для объемов
      if(!GetVolumeBorders())
         return(0);
     }
//--- переменная начала для расчета баров
   int start=prev_calculated;
//--- если значения индикатора уже были рассчитаны на предыдущем тике, то работаем на последнем баре
   if(start>0)
      start--;
//--- установим прямое направление индексации в таймсериях
   ArraySetAsSeries(time,false);
   ArraySetAsSeries(open,false);
   ArraySetAsSeries(high,false);
   ArraySetAsSeries(low,false);
   ArraySetAsSeries(close,false);
   ArraySetAsSeries(tick_volume,false);
//--- цикл расчета значений индикатора
   for(int i=start;i<rates_total;i++)
     {
      //--- закрашиваем свечи, начиная с начальной даты
      if(ExtStartTime<=time[i])
        {
         //--- если значение не меньше правой границы, то закрашиваем свечу
         if(tick_volume[i]>=ExtRightBorder)
           {
            //--- получим данные для рисования свечи
            ExtOpenBuff[i]=open[i];
            ExtHighBuff[i]=high[i];
            ExtLowBuff[i]=low[i];
            ExtCloseBuff[i]=close[i];
            //--- цвет DodgerBlue
            ExtColorBuff[i]=0;
            //--- продолжаем цикл
            continue;
           }
         //--- если значение не больше левой границы, то закрашиваем свечу
         if(tick_volume[i]<=ExtLeftBorder)
           {
            //--- получим данные для рисования свечи
            ExtOpenBuff[i]=open[i];
            ExtHighBuff[i]=high[i];
            ExtLowBuff[i]=low[i];
            ExtCloseBuff[i]=close[i];
            //--- цвет Orange
            ExtColorBuff[i]=1;
            //--- продолжаем цикл
            continue;
           }
        }
      //--- для баров, не попавших в расчет, ставим пустое значение
      ExtOpenBuff[i]=INDICATOR_EMPTY_VALUE;
      ExtHighBuff[i]=INDICATOR_EMPTY_VALUE;
      ExtLowBuff[i]=INDICATOR_EMPTY_VALUE;
      ExtCloseBuff[i]=INDICATOR_EMPTY_VALUE;
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }

Смотри также

ArrayBsearch