#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);
}
|