//+------------------------------------------------------------------+
//| Test_ChartSaveTemplate.mq5 |
//| Copyright 2011, MetaQuotes Software Corp. |
//| https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2000-2024, MetaQuotes Ltd."
#property link "https://www.mql5.com"
#property version "1.00"
#property script_show_inputs
//--- input parameters
input string symbol="GBPUSD"; // символ нового графика
input ENUM_TIMEFRAMES period=PERIOD_H3; // таймфрейм нового графика
//+------------------------------------------------------------------+
//| Script program start function |
//+------------------------------------------------------------------+
void OnStart()
{
//--- сначала набросим на график индикаторы
int handle;
//--- подготовим индикатор к использованию
if(!PrepareZigzag(NULL,0,handle)) return; // попытка не удалась, выходим
//--- набросим индикатор на текущий график, но в отдельное окно
if(!ChartIndicatorAdd(0,1,handle))
{
PrintFormat("Не удалось добавить на график %s/%s индикатор с хэндлом=%d. Код ошибки %d",
_Symbol,
EnumToString(_Period),
handle,
GetLastError());
//--- досрочно прекращаем работу программы
return;
}
//--- прикажем графику обновиться, чтобы сразу увидеть наброшенный индикатор
ChartRedraw();
//--- найдем два последних перелома зигзага
double two_values[];
datetime two_times[];
if(!GetLastTwoFractures(two_values,two_times,handle))
{
PrintFormat("Не удалось найти два последних перелома в индикторе Zigzag!");
//--- досрочно прекращаем работу программы
return;
}
//--- теперь набросим канал стандартного отклонения
string channel="StdDeviation Channel";
if(!ObjectCreate(0,channel,OBJ_STDDEVCHANNEL,0,two_times[1],0))
{
PrintFormat("Не удалось создать объект %s. Код ошибки %d",
EnumToString(OBJ_STDDEVCHANNEL),GetLastError());
return;
}
else
{
//--- канал создан, доопределим вторую опорную точку
ObjectSetInteger(0,channel,OBJPROP_TIME,1,two_times[0]);
//--- зададим каналу текст всплывающей подсказки
ObjectSetString(0,channel,OBJPROP_TOOLTIP,"Demo from MQL5 Help");
//--- обновим график
ChartRedraw();
}
//--- сохраним полученный результат в шаблон
ChartSaveTemplate(0,"StdDevChannelOnZigzag");
//--- откроем новый график и набросим на него сохраненный шаблон
long new_chart=ChartOpen(symbol,period);
//--- включим показ всплывающих подсказок для графических объектов
ChartSetInteger(new_chart,CHART_SHOW_OBJECT_DESCR,true);
if(new_chart!=0)
{
//--- набросим на новый график сохраненный шаблон
ChartApplyTemplate(new_chart,"StdDevChannelOnZigzag");
}
Sleep(10000);
}
//+------------------------------------------------------------------+
//| Создает хэндл зигзага и обеспечивает готовность его данных |
//+------------------------------------------------------------------+
bool PrepareZigzag(string sym,ENUM_TIMEFRAMES tf,int &h)
{
ResetLastError();
//--- индикатор Zigzag должен находиться в папке каталог_данных_терминала\MQL5\Examples
h=iCustom(sym,tf,"Examples\\Zigzag");
if(h==INVALID_HANDLE)
{
PrintFormat("%s: Не удалось создать хэндл индикатора Zigzag. Код ошибки %d",
__FUNCTION__,GetLastError());
return false;
}
//--- при создании хэндла индикатора ему требуется время на расчет значений
int k=0; // количество попыток чтобы дождаться расчета индикатора
//--- ждем расчета в цикле, делаем паузу в 50 миллисекунд, если расчет еще не готов
while(BarsCalculated(h)<=0)
{
k++;
//--- выведем количество попыток
PrintFormat("%s: k=%d",__FUNCTION__,k);
//--- подождем 50 миллисекунд, пока индикатор рассчитается
Sleep(50);
//--- если сделано больше 100 попыток, то что-то не так
if(k>100)
{
//--- сообщим о проблеме
PrintFormat("Не удалось рассчитать индикатор за %d попыток!");
//--- досрочно прекращаем работу программы
return false;
}
}
//--- все готово, индикатор создан и значения рассчитаны
return true;
}
//+------------------------------------------------------------------+
//| Ищет два последних перелома зигзага и помещает в массивы |
//+------------------------------------------------------------------+
bool GetLastTwoFractures(double &get_values[],datetime &get_times[],int handle)
{
double values[]; // массив для получения значений зигзага
datetime times[]; // массив для получения времени
int size=100; // размер массивов
ResetLastError();
//--- копируем 100 последних значений индикатора
int copied=CopyBuffer(handle,0,0,size,values);
//--- проверим сколько скопировалось
if(copied<100)
{
PrintFormat("%s: Не удалось скопировать %d значений индикатора с хэндлом=%d. Код ошибки %d",
__FUNCTION__,size,handle,GetLastError());
return false;
}
//--- определим порядок доступа к массиву как в таймсерии
ArraySetAsSeries(values,true);
//--- сюда запишем номера баров, на которых найдены переломы
int positions[];
//--- зададим размеры массивов
ArrayResize(get_values,3); ArrayResize(get_times,3); ArrayResize(positions,3);
//--- счетчики
int i=0,k=0;
//--- начинаем поиск переломов
while(i<100)
{
double v=values[i];
//--- пустые значения нас не интересуют
if(v!=0.0)
{
//--- запомним номер бара
positions[k]=i;
//--- запомним значение зигзага на переломе
get_values[k]=values[i];
PrintFormat("%s: Zigzag[%d]=%G",__FUNCTION__,i,values[i]);
//--- увеличим счетчик
k++;
//--- если нашли два перелома, то ломаем цикл
if(k>2) break;
}
i++;
}
//--- определим порядок доступа к массивам как в таймсерии
ArraySetAsSeries(times,true); ArraySetAsSeries(get_times,true);
if(CopyTime(_Symbol,_Period,0,size,times)<=0)
{
PrintFormat("%s: Не удалось скопировать %d значений из CopyTime(). Код ошибки %d",
__FUNCTION__,size,GetLastError());
return false;
}
//--- найдем время открытия баров, на которых были 2 последних перелома
get_times[0]=times[positions[1]];// предпоследнее значение будет записано первым переломом
get_times[1]=times[positions[2]];// третье с конца значение будет вторым переломом
PrintFormat("%s: первый=%s, второй=%s",__FUNCTION__,TimeToString(get_times[1]),TimeToString(get_times[0]));
//--- все получилось
return true;
}
|