Article-13824-MQL5-Multi-Sy.../TestMSTFAlligator.mq5

368 lines
36 KiB
MQL5

//+------------------------------------------------------------------+
//| TestMSTFAlligator.mq5.mq5 |
//| Copyright 2023, MetaQuotes Ltd. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2023, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#property indicator_chart_window
#property indicator_buffers 6
#property indicator_plots 6
//--- enums
//--- plot Jaws1
#property indicator_label1 "Jaws1"
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrDodgerBlue
#property indicator_width1 1
//--- plot Teeth1
#property indicator_label2 "Teeth1"
#property indicator_type2 DRAW_LINE
#property indicator_color2 clrOrangeRed
#property indicator_width2 1
//--- plot Lips1
#property indicator_label3 "Lips1"
#property indicator_type3 DRAW_LINE
#property indicator_color3 clrLime
#property indicator_width3 1
//--- plot Jaws2
#property indicator_label4 "Jaws2"
#property indicator_type4 DRAW_LINE
#property indicator_color4 clrBlue
#property indicator_width4 1
//--- plot Teeth2
#property indicator_label5 "Teeth"
#property indicator_type5 DRAW_LINE
#property indicator_color5 clrRed
#property indicator_width5 1
//--- plot Lips2
#property indicator_label6 "Lips"
#property indicator_type6 DRAW_LINE
#property indicator_color6 clrLimeGreen
#property indicator_width6 1
//--- includes
#include "IndMSTF.mqh"
#include "Dashboard.mqh"
//--- input parameters
input string InpSymbol = NULL; /* Symbol */ // Символ скользящей средней
input ENUM_TIMEFRAMES InpTimeframe = PERIOD_CURRENT; /* Timeframe */ // Таймфрейм скользящей средней
input int InpJawsPeriod = 13; /* Jaws Period */ // Период расчёта челюстей
input int InpJawsShift = 8; /* Jaws Shift */ // Сдвиг челюстей
input int InpTeethPeriod = 8; /* Teeth Period */ // Период расчёта зубов
input int InpTeethShift = 5; /* Teeth Shift */ // Сдвиг зубов
input int InpLipsPeriod = 5; /* Lips Period */ // Период расчёта губ
input int InpLipsShift = 3; /* Lips Shift */ // Сдвиг губ
input ENUM_MA_METHOD InpMethod = MODE_SMMA; /* Method */ // Метод расчёта
input ENUM_APPLIED_PRICE InpPrice = PRICE_MEDIAN; /* Applied Price */ // Используемая цена для расчёта
input uchar InpLineWidth1 = 2; /* Senior period Line Width */ // Толщина линии для старшего периода
input uchar InpLineWidth2 = 1; /* Junior period Line Width */ // Толщина линии для младшего периода
input bool InpAsSeries = true; /* As Series flag */ // Флаг серийности массивов буферов индикатора
//--- indicator buffers
double BufferJaws1[];
double BufferTeeth1[];
double BufferLips1[];
double BufferJaws2[];
double BufferTeeth2[];
double BufferLips2[];
//--- global variables
int handle_alligator1;
int handle_alligator2;
CMSTFIndicators indicators; // Экземпляр объекта коллекции индикаторов
//--- переменные для панели
CDashboard *panel=NULL; // Указатель на объект панели
int mouse_bar_index; // Индекс бара, с которого берутся данные
//+------------------------------------------------------------------+
//| Custom indicator initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
//--- Устанавливаем таймер с периодичностью в 1 секунду
EventSetTimer(1);
//--- Назначаем рисуемым буферам 0, 1 и 2 массивы BufferBandsUp1, BufferBandsDn1 и BufferBandsMd1 соответственно
SetIndexBuffer(0,BufferJaws1,INDICATOR_DATA);
SetIndexBuffer(1,BufferTeeth1,INDICATOR_DATA);
SetIndexBuffer(2,BufferLips1,INDICATOR_DATA);
//--- Назначаем рисуемым буферам 3, 4 и 5 массивы BufferBandsUp2, BufferBandsDn2 и BufferBandsMd2 соответственно
SetIndexBuffer(3,BufferJaws2,INDICATOR_DATA);
SetIndexBuffer(4,BufferTeeth2,INDICATOR_DATA);
SetIndexBuffer(5,BufferLips2,INDICATOR_DATA);
//--- Устанавливаем ширину линий
int w1=0,w2=0;
if(InpTimeframe>Period())
{
w1=InpLineWidth2;
w2=InpLineWidth1;
}
else
{
w1=InpLineWidth1;
w2=InpLineWidth2;
}
PlotIndexSetInteger(0,PLOT_LINE_WIDTH,w1);
PlotIndexSetInteger(1,PLOT_LINE_WIDTH,w1);
PlotIndexSetInteger(2,PLOT_LINE_WIDTH,w1);
PlotIndexSetInteger(3,PLOT_LINE_WIDTH,w2);
PlotIndexSetInteger(4,PLOT_LINE_WIDTH,w2);
PlotIndexSetInteger(5,PLOT_LINE_WIDTH,w2);
//--- Устанавливаем флаги серийности массивам буферов индикатора (для теста, чтобы видно было отсутствие разницы)
ArraySetAsSeries(BufferJaws1,InpAsSeries);
ArraySetAsSeries(BufferTeeth1,InpAsSeries);
ArraySetAsSeries(BufferLips1,InpAsSeries);
ArraySetAsSeries(BufferJaws2,InpAsSeries);
ArraySetAsSeries(BufferTeeth2,InpAsSeries);
ArraySetAsSeries(BufferLips2,InpAsSeries);
//--- Создаём два индикатора одного типа
//--- Первый рассчитывается на текущих символе/периоде графика, а второй - на тех, что заданы в настройках
handle_alligator1=indicators.AddNewAlligator(NULL,PERIOD_CURRENT,InpJawsPeriod,InpJawsShift,InpTeethPeriod,InpTeethShift,InpLipsPeriod,InpLipsShift,InpMethod,InpPrice);
handle_alligator2=indicators.AddNewAlligator(InpSymbol,InpTimeframe,InpJawsPeriod,InpJawsShift,InpTeethPeriod,InpTeethShift,InpLipsPeriod,InpLipsShift,InpMethod,InpPrice);
//--- Если не удалось создать хэндлы индикаторов - возвращаем ошибку инициализации
if(handle_alligator1==INVALID_HANDLE || handle_alligator2==INVALID_HANDLE)
return INIT_FAILED;
//--- Устанавливаем описания линий индикатора из описаний буферов расчётной части созданных индикаторов
indicators.SetPlotLabelFromBuffer(0,handle_alligator1,0);
indicators.SetPlotLabelFromBuffer(1,handle_alligator1,1);
indicators.SetPlotLabelFromBuffer(2,handle_alligator1,2);
indicators.SetPlotLabelFromBuffer(3,handle_alligator2,0);
indicators.SetPlotLabelFromBuffer(4,handle_alligator2,1);
indicators.SetPlotLabelFromBuffer(5,handle_alligator2,2);
//--- Устанавливаем смещения линиям индикатора
indicators.SetPlotShift(0,InpJawsShift);
indicators.SetPlotShift(1,InpTeethShift);
indicators.SetPlotShift(2,InpLipsShift);
indicators.SetPlotShift(3,InpJawsShift);
indicators.SetPlotShift(4,InpTeethShift);
indicators.SetPlotShift(5,InpLipsShift);
//--- Панель
//--- Создаём панель
int width=321;
panel=new CDashboard(1,20,20,width,264);
if(panel==NULL)
{
Print("Error. Failed to create panel object");
return INIT_FAILED;
}
//--- Устанавливаем параметры шрифта
panel.SetFontParams("Calibri",9);
//--- Отображаем панель с текстом в заголовке "Символ, Описание таймфрейма"
panel.View(Symbol()+", "+StringSubstr(EnumToString(Period()),7));
//--- Создаём таблицу с идентификатором 0 для отображения в ней данных бара
panel.CreateNewTable(0);
//--- Рисуем таблицу с идентификатором 0 на фоне панели
panel.DrawGrid(0,2,20,6,2,18,width/2-2);
//--- Создаём таблицу с идентификатором 1 для отображения в ней данных индикатора 1
panel.CreateNewTable(1);
//--- Получаем координату Y2 таблицы с идентификатором 0 и
//--- устанавливаем координату Y1 для таблицы с идентификатором 1
int y1=panel.TableY2(0)+22;
//--- Рисуем таблицу с идентификатором 1 на фоне панели
panel.DrawGrid(1,2,y1,2,2,18,width/2-2);
//--- Создаём таблицу с идентификатором 2 для отображения в ней данных индикатора 2
panel.CreateNewTable(2);
//--- Получаем координату Y2 таблицы с идентификатором 1 и
//--- устанавливаем координату Y1 для таблицы с идентификатором 2
int y2=panel.TableY2(1)+3;
//--- Рисуем таблицу с идентификатором 2 на фоне панели
panel.DrawGrid(2,2,y2,3,2,18,width/2-2);
//--- Инициализируем переменную с индексом бара указателя мышки
mouse_bar_index=0;
//--- Выводим на панель данные текущего бара
DrawData(mouse_bar_index,TimeCurrent());
//--- Успешная инициализация
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- Уничтожаем таймер
EventKillTimer();
//--- Если объект панели существует - удаляем его
if(panel!=NULL)
delete panel;
//--- Стираем все комментарии
Comment("");
}
//+------------------------------------------------------------------+
//| 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[])
{
//--- Количество баров для расчёта
int limit=rates_total-prev_calculated;
//--- Если limit > 1, значит это первый расчёт, либо изменение в истории
if(limit>1)
{
//--- указываем для просчёта всю доступную историю
limit=rates_total-1;
/*
// Если в индикаторе есть какие-либо буферы, в которых отображены другие расчёты (не мульти- индикаторы),
// то здесь их нужно инициализировать "пустым" значением, установленным для этих буферов
*/
}
//--- Рассчитываем все созданные мультисимвольные мультипериодные индикаторы
if(!indicators.Calculate())
return 0;
//--- Выводим на панель данные бара под курсором (либо текущий бар, если курсор за пределами графика)
DrawData(mouse_bar_index,time[mouse_bar_index]);
//--- Из буферов рассчитанных индикаторов выводим данные в индикаторные буферы
if(!indicators.DataToBuffer(NULL,PERIOD_CURRENT,handle_alligator1,0,0,limit,BufferJaws1))
return 0;
if(!indicators.DataToBuffer(NULL,PERIOD_CURRENT,handle_alligator1,1,0,limit,BufferTeeth1))
return 0;
if(!indicators.DataToBuffer(NULL,PERIOD_CURRENT,handle_alligator1,2,0,limit,BufferLips1))
return 0;
if(!indicators.DataToBuffer(NULL,PERIOD_CURRENT,handle_alligator2,0,0,limit,BufferJaws2))
return 0;
if(!indicators.DataToBuffer(NULL,PERIOD_CURRENT,handle_alligator2,1,0,limit,BufferTeeth2))
return 0;
if(!indicators.DataToBuffer(NULL,PERIOD_CURRENT,handle_alligator2,2,0,limit,BufferLips2))
return 0;
//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
//| Timer function |
//+------------------------------------------------------------------+
void OnTimer()
{
//--- Вызываем таймер коллекции индикаторов
indicators.OnTimer();
}
//+------------------------------------------------------------------+
//| ChartEvent function |
//+------------------------------------------------------------------+
void OnChartEvent(const int id,
const long &lparam,
const double &dparam,
const string &sparam)
{
//--- Работа с панелью
//--- Вызываем обработчик событий панели
panel.OnChartEvent(id,lparam,dparam,sparam);
//--- Если курсор перемещается или щелчок по графику
if(id==CHARTEVENT_MOUSE_MOVE || id==CHARTEVENT_CLICK)
{
//--- Объявляем переменные для записи в них координат времени и цены
datetime time=0;
double price=0;
int wnd=0;
//--- Если координаты курсора преобразованы в дату и время
if(ChartXYToTimePrice(ChartID(),(int)lparam,(int)dparam,wnd,time,price))
{
//--- записываем индекс бара, где расположен курсор в глобальную переменную
mouse_bar_index=iBarShift(Symbol(),PERIOD_CURRENT,time);
//--- Выводим данные бара под курсором на панель
DrawData(mouse_bar_index,time);
}
}
//--- Если получили пользовательское событие - выводим об этом сообщение в журнал
if(id>CHARTEVENT_CUSTOM)
{
//--- Здесь может быть обработка щелчка по кнопке закрытия на панели
PrintFormat("%s: Event id=%ld, object id (lparam): %lu, event message (sparam): %s",__FUNCTION__,id,lparam,sparam);
}
}
//+------------------------------------------------------------------+
//| Выводит данные с указанного индекса таймсерии на панель |
//+------------------------------------------------------------------+
void DrawData(const int index,const datetime time)
{
//--- Объявляем переменные для получения в них данных
MqlRates rates[1];
//--- Если данные бара по указанному индексу получить не удалось - уходим
if(CopyRates(Symbol(),PERIOD_CURRENT,index,1,rates)!=1)
return;
//--- Устанавливаем параметры шрифта для заголовков данных бара и индикатора
int size=0;
uint flags=0;
uint angle=0;
string name=panel.FontParams(size,flags,angle);
panel.SetFontParams(name,9,FW_BOLD);
panel.DrawText("Bar data ["+(string)index+"]",3,panel.TableY1(0)-16,clrMaroon,panel.Width()-6);
panel.DrawText("Indicators data ["+(string)index+"]",3,panel.TableY1(1)-16,clrGreen,panel.Width()-6);
//--- Устанавливаем параметры шрифта для данных бара и индикатора
panel.SetFontParams(name,9);
//--- Выводим на панель данные указанного бара в таблицу 0
panel.DrawText("Date", panel.CellX(0,0,0)+2, panel.CellY(0,0,0)+2); panel.DrawText(TimeToString( rates[0].time,TIME_DATE), panel.CellX(0,0,1)+2, panel.CellY(0,0,1)+2,clrNONE,90);
panel.DrawText("Time", panel.CellX(0,1,0)+2, panel.CellY(0,1,0)+2); panel.DrawText(TimeToString( rates[0].time,TIME_MINUTES), panel.CellX(0,1,1)+2, panel.CellY(0,1,1)+2,clrNONE,90);
panel.DrawText("Open", panel.CellX(0,2,0)+2, panel.CellY(0,2,0)+2); panel.DrawText(DoubleToString(rates[0].open,Digits()), panel.CellX(0,2,1)+2, panel.CellY(0,2,1)+2,clrNONE,90);
panel.DrawText("High", panel.CellX(0,3,0)+2, panel.CellY(0,3,0)+2); panel.DrawText(DoubleToString(rates[0].high,Digits()), panel.CellX(0,3,1)+2, panel.CellY(0,3,1)+2,clrNONE,90);
panel.DrawText("Low", panel.CellX(0,4,0)+2, panel.CellY(0,4,0)+2); panel.DrawText(DoubleToString(rates[0].low,Digits()), panel.CellX(0,4,1)+2, panel.CellY(0,4,1)+2,clrNONE,90);
panel.DrawText("Close", panel.CellX(0,5,0)+2, panel.CellY(0,5,0)+2); panel.DrawText(DoubleToString(rates[0].close,Digits()), panel.CellX(0,5,1)+2, panel.CellY(0,5,1)+2,clrNONE,90);
//--- Выводим в таблицу 1 данные индикатора 1 с указанного бара в таблицу 1
panel.DrawText(indicators.Title(handle_alligator1), panel.CellX(1,0,0)+2, panel.CellY(1,0,0)+2);
double value1=indicators.GetData(handle_alligator1,0,0,index+InpJawsShift);
string value_str1=(value1!=EMPTY_VALUE ? DoubleToString(value1,indicators.Digits(handle_alligator1)) : " ");
panel.DrawText(value_str1,panel.CellX(1,0,1)+2,panel.CellY(1,0,1)+2,clrNONE,150);
//--- Выводим описание состояния линии индикатора 1
panel.DrawText("Line state", panel.CellX(1,1,0)+2, panel.CellY(1,1,0)+2);
ENUM_LINE_STATE state1=indicators.BufferLineState(Symbol(),PERIOD_CURRENT,handle_alligator1,0,0,index);
panel.DrawText(BufferLineStateDescription(state1),panel.CellX(1,1,1)+2,panel.CellY(1,1,1)+2,clrNONE,150);
//--- Выводим в таблицу 2 данные индикатора 2 с указанного бара в таблицу 2
panel.DrawText(indicators.Title(handle_alligator2), panel.CellX(2,0,0)+2, panel.CellY(2,0,0)+2);
double value2=indicators.GetDataTo(Symbol(),PERIOD_CURRENT,handle_alligator2,0,0,index);
string value_str2=(value2!=EMPTY_VALUE ? DoubleToString(value2,indicators.Digits(handle_alligator2)) : " ");
panel.DrawText(value_str2,panel.CellX(2,0,1)+2,panel.CellY(2,0,1)+2,clrNONE,150);
//--- Выводим описание состояния линии индикатора 2
panel.DrawText("Line state", panel.CellX(2,1,0)+2, panel.CellY(2,1,0)+2);
ENUM_LINE_STATE state2=indicators.BufferLineState(Symbol(),PERIOD_CURRENT,handle_alligator2,0,0,index);
panel.DrawText(BufferLineStateDescription(state2),panel.CellX(2,1,1)+2,panel.CellY(2,1,1)+2,clrNONE,150);
//--- Выводим описание соотношения линии индикатора 1 относительно линии индикатора 2
double value21=indicators.GetDataTo(Symbol(),PERIOD_CURRENT,handle_alligator2,0,0,index+1);
ENUM_LINE_STATE stateR=indicators.BufferLineStateRelative(Symbol(),PERIOD_CURRENT,handle_alligator1,0,0,index,value2,value21);
string ma1=indicators.Name(handle_alligator1);
string ma2=indicators.Name(handle_alligator2);
string state_relative=
(
stateR==LINE_STATE_ABOVE ? StringFormat("%s1 > %s2",ma1,ma2) :
stateR==LINE_STATE_BELOW ? StringFormat("%s1 < %s2",ma1,ma2) :
stateR==LINE_STATE_CROSS_DOWN ? "Top-down crossing" :
stateR==LINE_STATE_CROSS_UP ? "Bottom-up crossing" :
BufferLineStateDescription(stateR)
);
panel.DrawText(StringFormat("%s1 vs %s2",ma1,ma2), panel.CellX(2,2,0)+2, panel.CellY(2,2,0)+2);
panel.DrawText(state_relative, panel.CellX(2,2,1)+2, panel.CellY(2,2,1)+2,clrNONE,150);
//--- Перерисовываем график для немедленного отображения всех изменений на панели
ChartRedraw(ChartID());
}
//+------------------------------------------------------------------+