English 中文 Español Deutsch 日本語 Português
preview
Работаем с датами и временем в MQL5

Работаем с датами и временем в MQL5

MetaTrader 5Трейдинг | 23 февраля 2024, 12:52
666 10
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

Введение

Никто в сфере финансового рынка не скрывает важность времени и то, как оно может повлиять на торговые решения и результаты. MQL5 (MetaQuotes Language 5) предлагает решение для эффективной работы с датой и временем. Мы можем справиться с этой важной темой с помощью множества приложений, которые можно запрограммировать как часть нашей торговой системы, но сначала рассмотрим наиболее важные аспекты этой темы на языке программирования MQL5.

В статье мы рассмотрим следующие темы:

Прочитав статью, вы сможете применять данные типа datetime в mql5 в разработке своих приложений. Надеюсь, статья окажется полезной для вас.
Внимание! Все содержание настоящей статьи предоставляется "как есть", предназначено только для целей обучения и не является торговой рекомендацией. Статья не несет в себе каких-либо гарантий результатов. Все, что вы применяете на практике на основе этой статьи, вы делаете исключительно на свой страх и риск, автор не гарантирует никаких результатов.


Тип datetime

Тип переменной datetime в mql5 используется для сортировки данных даты и времени в формате Unix. Время Unix — это количество секунд, прошедших с 1 января 1970 года. Для лучшего понимания, если мы преобразуем дату 01 января 2023 года в 00:00:00 по Гринвичу во время Unix, мы обнаружить, что она равна 1672531200 секунд. Соответственно, отметка времени (time stamp) — это количество секунд между определенной датой и эпохой Unix, то есть 1 января 1970 года. Мы также можем увидеть время в секундах по сравнению с известным читаемым временем следующим образом:
Известное читаемое время Секунды
1 год 31 556 926 секунд
1 месяц 2 629 743 секунд
1 неделя 604 800 секунд
1 день 86 400 секунд
1 час 3600 секунд

Больше о Unix-времени можно узнать из статьи в Википедии.

Мы можем легко определить конкретную дату и время, используя константу datetime, которая начинается с символа D с датой и временем в одинарных кавычках:

D'yyyy.mm.dd hh:mm:ss'

Либо так:

D'dd.mm.yyyy hh:mm:ss'

Нам могут быть полезны следующие примеры из руководства по mql5:

datetime NY=D'2015.01.01 00:00';     // Time of beginning of year 2015
datetime d1=D'1980.07.19 12:30:27';  // Year Month Day Hours Minutes Seconds
datetime d2=D'19.07.1980 12:30:27';  // Equal to D'1980.07.19 12:30:27';
datetime d3=D'19.07.1980 12';        // Equal to D'1980.07.19 12:00:00'
datetime d4=D'01.01.2004';           // Equal to D'01.01.2004 00:00:00'
datetime compilation_date=__DATE__;             // Compilation date
datetime compilation_date_time=__DATETIME__;    // Compilation date and time
datetime compilation_time=__DATETIME__-__DATE__;// Compilation time
//--- Examples of declarations after which compiler warnings will be returned
datetime warning1=D'12:30:27';       // Equal to D'[date of compilation] 12:30:27'
datetime warning2=D'';               // Equal to __DATETIME__

Ниже приведены результаты после компиляции:

datetime

Тип datetime хранит значения даты и времени в секундах. Это упрощает сравнение и управление значениями даты и времени. Ниже приведены примеры того, что мы можем делать при работе со значениями дат и времени:

  • Сравнение значений дат и времени.
  • Добавление или вычитание значений дат и времени.
  • Преобразование времени в строку или строку во время в разных целях.

Сравнение значений даты и времени:

Если у нас есть два значения времени и даты, и нам нужно сравнить их, мы можем сделать это в MQL5, создав переменную для каждого значения, а затем сравнив их друг с другом, чтобы выполнить действие на основе результата. Пример приведен ниже:

Если пользователь вводит два значения даты и времени, одно старше другого, и мы хотим получить конкретный результат, например, вывести данные, в случае, если одно входное значение больше второго, нам нужно получить сообщение Input one is a recent time (первое входное значение — это недавнее время), но если первое входное значение меньше второго, нам нужно получить сообщение Input two is a recent time (второе входное значение — это недавнее время).

Ниже приведен код, позволяющий это сделать:

//+------------------------------------------------------------------+
//|                                              dateTimeCompare.mq5 |
//+------------------------------------------------------------------+
input datetime inpDate1 = D'2023.09.01 00:00';
input datetime inpDate2 = D'2023.09.30 00:00';
//+------------------------------------------------------------------+
void OnTick()
  {
   if(inpDate1>inpDate2)
     {
      Print("Input one is a recent time");
     }
   else
      if(inpDate1<inpDate2)
        {
         Print("Input two is a recent time");
        }
  }
//+------------------------------------------------------------------+

Если после компиляции кода мы установим входные значения даты и времени следующим образом:

datetimeCompareInp

Как мы видим, первое входное значение старше второго. Итак, мы можем найти результат, аналогичный следующему:

datetimeCompareresult1

Если мы изменили первое входное значение на более позднее, то второе будет аналогично следующему:

 datetimeCompareInp2

Согласно предыдущим настройкам входных параметров, мы должны найти результат, аналогичный следующему:

datetimeCompareresult2

Предыдущий пример кода — это пример того, как мы можем обращаться с датой и временем.

Добавление или вычитание значений дат и времени:

Мы также можем складывать и вычитать значения даты и времени. Допустим, у нас есть два значения даты и времени:

D'2023.09.01 00:00'
D'2023.09.30 00:00'

Теперь нам нужно к первому значению прибавить один день и от второго значения вычесть один день. Один день в секундах равен 86 400. Итак, после этих двух транзакций мы можем найти новые значения:

D'2023.09.02 00:00'
D'2023.09.29 00:00'

Следующий код описывает, как кодировать эти транзакции:

//+------------------------------------------------------------------+
//|                                           dateTimeManipulate.mq5 |
//+------------------------------------------------------------------+
input datetime oldDate = D'2023.09.01 00:00';
input datetime newDate = D'2023.09.30 00:00';
//+------------------------------------------------------------------+
void OnTick()
  {
   datetime addToDate =   oldDate+86400;
   Print("Result of date addition - ",addToDate);
   datetime subtractFromDate =   newDate-86400;
   Print("Result of date subtraction - ",subtractFromDate);
  }
//+------------------------------------------------------------------+

Результат запуска этого программного обеспечения будет таким же, как мы уже упоминали:

 dateTimeMani

Преобразование времени в строку или строку во время в разных целях:

Нам может понадобиться преобразовать тип значений даты и времени. На данный момент у нас есть две функции, которые могут выполнять преобразование строки во время и наоборот. TimeToString или StringToTime. Здесь мы увидим пример того, как мы можем справиться с таким случаем:

//+------------------------------------------------------------------+
//|                                              dateTimeConvert.mq5 |
//+------------------------------------------------------------------+
input datetime oldDate = D'2023.09.01 00:00';
input string newDate = "2023.09.30 00:00";
//+------------------------------------------------------------------+
void OnTick()
  {
   string newOldDate = TimeToString(oldDate);
   datetime newNewDate = StringToTime(newDate);
   Print("Time To String - ",newOldDate);
   Print("String To Time - ",newNewDate);
  }
//+------------------------------------------------------------------+

Выполнив этот код в торговом терминале, мы можем найти возвращаемые значения для каждой функции: первое для преобразования из TimeToString, а второе для преобразования из StringToTime:

 dateTimeConvert

Если мы хотим знать и понимать все операции с типом datetime в MQL5,

  • currentTime возвращает текущее время.
  • Сравнение значений: логически мы используем эту операцию для проверки сравнения времени.
  • Манипуляции с данными даты и времени - сложение и вычитание.
  • форматирование даты и времени.


Структура MqlDateTime

В этой части мы изучим структуру MqlDateTime. Она содержит переменные, которые могут хранить данные даты и времени или значения даты и времени. Ниже приведена структура, аналогичная той, которую мы можем найти в руководстве по MQL5:

struct MqlDateTime
  {
   int year;           // Year
   int mon;            // Month
   int day;            // Day
   int hour;           // Hour
   int min;            // Minutes
   int sec;            // Seconds
   int day_of_week;    // Day of week (0-Sunday, 1-Monday, ... ,6-Saturday)
   int day_of_year;    // Day number of the year (January 1st is assigned the number value of zero)
  };

Как мы видим, она содержит восемь полей переменных типа int.

Мы используем функцию (TimeToStruct) с этой структурой для преобразования значения datetime в переменную MqlDateTime. Параметры функции:

  • dt - дата и время
  • dt_struct - структура для принятия значений

Функция возвращает логическое значение.

Мы также можем использовать функцию (StructToTime) для преобразования переменной структуры MqlDateTime в значение даты и времени. Его единственный параметр - dt_struct. Он возвращает тип даты и времени, содержащий количество секунд.

Мы можем увидеть пример этой структуры MqlDateTime, аналогичный следующему:

Если у нас есть дата и время D'2023.10.10 07:07:07' или любое другое входное значение, нам нужно использовать с ним MqlDateTime. Мы можем сделать это с помощью следующего кода:

//+------------------------------------------------------------------+
//|                                                  MqlDateTime.mq5 |
//+------------------------------------------------------------------+
input datetime dtData = D'2023.10.10 07:07:07';
void OnTick()
  {
   MqlDateTime timeStruct;
   TimeToStruct(dtData,timeStruct);
   int year = timeStruct.year;
   Print("year: ",year);
   Print("=====================");
   int month = timeStruct.mon;
   Print("month: ",month);
   Print("=====================");
   int day = timeStruct.day;
   Print("day: ",day);
   Print("=====================");
   int hour = timeStruct.hour;
   Print("hour: ",hour);
   Print("=====================");
   int minute = timeStruct.min;
   Print("minute: ",minute);
   Print("=====================");
   int second = timeStruct.sec;
   Print("second: ",second);
   Print("=====================");
   int dayofWeek = timeStruct.day_of_week;
   Print("dayofWeek: ",dayofWeek);
   Print("=====================");
   int dayofYear = timeStruct.day_of_year;
   Print("dayofYear: ",dayofYear);
  }
//+------------------------------------------------------------------+

Выполнив этот советник, мы можем найти напечатанные сообщения, такие же, как следующие:

 mqlDateTime

Здесь полезно отметить, что значение месяца или дня по умолчанию равно 01, если вы используете меньше 1 в качестве входных данных. Максимальное значение месяца по умолчанию равно 12, а день равен 31, если используемый входной параметр превышает это максимальное значение. Значения по умолчанию для часа - минимум 0 или максимум 23, для минуты - минимум 0 или максимум 59.


Событие OnTimer()

В этой части мы узнаем, что такое обработчик событий OnTimer() и как его использовать. Его можно использовать, когда вам нужно выполнить свой код или торговую стратегию каждые заданное количество секунд. Итак, если вы хотите, чтобы ваш код выполнял определенное действие через определенный интервал времени, вы можете поместить свой код в обработчик событий OnTimer().

Обработчик событий OnTimer() представляет собой тип void без параметров, и его можно добавить в код, если вам это нужно. Чтобы использовать его, вам необходимо установить интервал таймера в части OnInit(), используя функцию EventSetTimer() с параметром секунд, как в следующем примере:

int OnInit()
{
EventSetTimer(60);
}

Предыдущий пример означает, что код обработчика событий OnTimer() будет выполняться каждые 60 секунд.

Теперь, если нам нужно остановить выполнение кода внутри события OnTimer(), мы можем сделать это, используя void-функцию EventKillTimer() в обработчике событий onDeinit() или деструкторе класса.


Применение NewBar

В этом приложении мы создадим включаемый файл, содержащий классы и функции, которые можно использовать в других файлах, таких как советники. Приложение сообщает, есть ли у нас новый бар, печатая сообщение "A new bar painted" (отрисован новый бар).

Во-первых, следующие шаги предназначены для создания включаемого файла. Основная идея создания включаемого файла здесь заключается в том, чтобы научиться создавать файлы, которые можно использовать во многих проектах, и работать как профессиональный разработчик, если вы новичок.

Объявим класс CNewBar, который будет иметь две частные переменные - time[] для хранения времени текущего бара и LastTime для хранения времени самого последнего бара. Включим контрактор булевой функции newBarCheck с двумя параметрами:

  • тип string символа
  • тип timeFrame ENUM_TIMEFRAMES
class CNewBar
  {
private:
   datetime          time[], lastTime;
public:
   void              CNewBar();
   bool              newBarCheck(string symbol, ENUM_TIMEFRAMES timeFrame);
  };

Установка массива времени в виде серии

void CNewBar::CNewBar(void)
  {
   ArraySetAsSeries(time,true);
  }

Создание функции newBarCheck с двумя параметрами (символ и таймфрейм) для проверки наличия или отсутствия нового бара. Функция будет возвращать значение типа bool.

bool CNewBar::newBarCheck(string symbol, ENUM_TIMEFRAMES timeFrame)

Тело функции проверяет наличие нового бара. Создаются две логические переменные для first и newBar со значением false по умолчанию.

   bool firstCheck = false;
   bool newBar = false;

Используйте функцию CopyTime с вариантами вызова по первой позиции, чтобы получить исторические данные time_array времени открытия бара указанной пары символ-период в указанном количестве. Параметры:

  • symbol_name - имя символа в виде определенной строки в функции.
  • timeframe - временной интервал timeFrame как определенный ENIM_TIMEFRAMES в функции.
  • start_pos - стартовая позиция равна 0.
  • count - данные для копирования равны 2.
  • time_array[] - массив, из которого нужно скопировать время открытия, будет массивом времени.
CopyTime(symbol,timeFrame,0,2,time);
Проверим переменную класса LastTime. Если это первая проверка, то значение переменной LastTime будет равно 0, тогда переменная firstCheck будет равна true.
   if(lastTime == 0)
     {
      firstCheck = true;
     }

Проверяем, превышает ли значение time[0] значение LastTime, а затем проверяем, равно ли значение firstCheck значению false, поэтому newBar будет равно true, тогда LastTime будет тем же значением, что и time[0]

   if(time[0] > lastTime)
     {
      if(firstCheck == false)
      {
         newBar = true;
      }
      lastTime = time[0];
     }

Вернем значение newBar, которое будет логическим значением.

return(newBar);

Ниже приведен полный код в одном блоке:

//+------------------------------------------------------------------+
//|                                                       newBar.mqh |
//+------------------------------------------------------------------+
class CNewBar
  {
private:
   datetime          time[], lastTime;
public:
   void              CNewBar();
   bool              newBarCheck(string symbol, ENUM_TIMEFRAMES timeFrame);
  };
//+------------------------------------------------------------------+
void CNewBar::CNewBar(void)
  {
   ArraySetAsSeries(time,true);
  }
//+------------------------------------------------------------------+
bool CNewBar::newBarCheck(string symbol, ENUM_TIMEFRAMES timeFrame)
  {
   bool firstCheck = false;
   bool newBar = false;
   CopyTime(symbol,timeFrame,0,2,time);
   if(lastTime == 0)
     {
      firstCheck = true;
     }
   if(time[0] > lastTime)
     {
      if(firstCheck == false)
      {
         newBar = true;
      }
      lastTime = time[0];
     }
   return(newBar);
  }
//+------------------------------------------------------------------+

Если вы хотите узнать больше об объектно-ориентированном программировании и классах в MQL5, вы можете прочитать мою предыдущую статью "Объектно-ориентированное программирование (ООП) в MQL5". Надеюсь, она будет для вас полезной.

Теперь, после создания включаемого файла, мы создадим наш советник, который будет обнаруживать новый бар и отображать сообщение "A new bar painted, you can trade" (отрисован новый бар, можно торговать). Сначала включим созданный включаемый файл в код советника с помощью препроцессора #include.

#include <dateTime.mqh>

Объявим объект из класса CNewBar.

CNewBar NewBar;

Создадим переменную bool в качестве входных данных, чтобы выбрать, будем ли мы торговать при рисовании нового бара (true) или нет (false).

bool newBarTrade=true;

После этого в части OnTick() создадим переменную bool newBar со значением по умолчанию true и еще одну целочисленную переменную barShift со значением по умолчанию 0.

   bool newBar=true;
   int barShift=0;

Проверяем, истинно ли значение newBarTrade, тогда newBar будет равен Newbarobject.newBarCheck с параметрами текущего символа и таймфрейма, а barShift будет равен 1.

   if(newBarTrade==true)
     {
      newBar = NewBar.newBarCheck(Symbol(),Period());
      barShift=1;
     }

Убедимся, что newBar равен true. Это означает, что сгенерирован новый бар, поэтому нам нужно получить сообщение "A new bar painted, you can trade"

   if(newBar==true)
     {
      Print("A new bar painted, you can trade");
     }

Ниже приведен полный код этого приложения кода

//+------------------------------------------------------------------+
//|                                                       newBar.mq5 |
//+------------------------------------------------------------------+
#include <dateTime.mqh>
CNewBar NewBar;
bool newBarTrade=true;
//+------------------------------------------------------------------+
void OnTick()
  {
   bool newBar=true;
   int barShift=0;
   if(newBarTrade==true)
     {
      newBar = NewBar.newBarCheck(Symbol(),Period());
      barShift=1;
     }
   if(newBar==true)
     {
      Print("A new bar painted, you can trade");
     }
  }
//+------------------------------------------------------------------+

После выполнения этого советника мы можем получить следующий результат после создания нового бара

алерт newBar

Код можно разработать для изменения действия при рисовании нового бара в соответствии с вашей стратегией, например, открытия сделки или чего-то еще, но в этой статье мы поделимся простым кодом, чтобы понять основную идею.


Применение временного фильтра

В этом приложении нам нужно создать приложение для разрешения или запрета торговли на основе временного фильтра или указанного периода времени. Добавим в созданный включаемый файл новый класс CTimeFilter и создадим публичную логическую функцию timeCheck с тремя параметрами (startTime, endTime, localTime со значением false по умолчанию).

class CTimeFilter
  {
public:
   bool timeCheck(datetime startTime, datetime endTime, bool localTime = false);
  };

Создадим тело функции timeCheck, проверив, были ли введенные данные неправильными путем получения значения startTime больше или равного endTime, а затем вернем предупреждение об ошибке "Error: Invalid Time input" (ошибка: неверный ввод времени) и false

   if(startTime >= endTime)
     {
      Alert("Error: Invalid Time input");
      return(false);
     }

Создадим переменную datetime для currentTime, а затем проверим, равен ли localTime true. TimeLocal() будет присвоено currentTime или TimeCurrent() будет присвоено currentTime

   datetime currentTime;
   if(localTime == true)
     {
      currentTime = TimeLocal();
     }
   else
      currentTime = TimeCurrent();

Создадим логическую переменную с именем timeFilterActive со значением false по умолчанию, затем проверим, больше ли currentTime или равно startTime, и в то же время меньше, чем endTime, затем вернем true для timeFilterActive. Вернем значение timeFilterActive

   bool timeFilterActive = false;
   if(currentTime >= startTime && currentTime < endTime)
     {
      timeFilterActive = true;
     }
   return(timeFilterActive);

Ниже приведен полный код во включаемом файле

class CTimeFilter
  {
public:
   bool timeCheck(datetime startTime, datetime endTime, bool localTime = false);
  };
bool CTimeFilter::timeCheck(datetime startTime, datetime endTime, bool localTime = false)
  {
   if(startTime >= endTime)
     {
      Alert("Error: Invalid Time input");
      return(false);
     }
   datetime currentTime;
   if(localTime == true)
     {
      currentTime = TimeLocal();
     }
   else
      currentTime = TimeCurrent();
   bool timeFilterActive = false;
   if(currentTime >= startTime && currentTime < endTime)
     {
      timeFilterActive = true;
     }
   return(timeFilterActive);
  }

После создания включаемого файла создадим наш советник timeFilterApp, выполнив следующий шаг:

Включим файл dateTime, чтобы использовать его содержимое.

#include <dateTime.mqh>

 Создадим две переменные даты и времени в качестве входных значений с именами StartTime и EndTime.

input datetime StartTime = D'2023.10.10 10:00';
input datetime EndTime = D'2023.10.10 17:00';

Создадим объект с именем filter в глобальной области видимости

CTimeFilter filter;

В части OnTick() создайте timeFilterActive и назначьте ему filter.timeCheck с параметрами.

bool timeFilterActive = filter.timeCheck(StartTime,EndTime,false);

Чтобы проверить, истинно ли значение timeFilterActive, нам нужно получить сообщение "Trading is active based on time filter" (торговля включена на основе временного фильтра) или "Trading is inactive based on time filter" (торговля отключена на основе временного фильтра).

   if(timeFilterActive == true)
     {
      Print("Trading is active based on time filter");
     }
     else Print("Trading is inactive based on time filter");

Полный код выглядит так:

//+------------------------------------------------------------------+
//|                                                timeFilterApp.mq5 |
//+------------------------------------------------------------------+
#include <dateTime.mqh>
input datetime StartTime = D'2023.10.10 10:00';
input datetime EndTime = D'2023.10.10 17:00';
CTimeFilter filter;
void OnTick()
  {
   bool timeFilterActive = filter.timeCheck(StartTime,EndTime,false);
   if(timeFilterActive == true)
     {
      Print("Trading is active based on time filter");
     }
     else Print("Trading is inactive based on time filter");
  }

После выполнения этого приложения мы увидим один из трех результатов в зависимости от введенного времени.

В случае активного времени:

 timeFilterAppinpactive

timeFilterApp

В случае неактивного времени:

timeFilterAppinpinactive

 timeFilterAppinactive

В случае ложных входных параметров:

 timeFilterAppinperror.

timeFilterApperror

Есть еще один метод, который мы можем использовать без включаемого файл. Ниже приведены шаги, которые помогут это сделать.

Создадим четыре входные переменные int для начальных и заключительных часов и минут в глобальном масштабе.

input int TimeStartHour = 
10 ;
input int TimeStartMin = 0;
input int TimeEndHour = 17;
input int TimeEndMin = 
0 ;

В части OnTick() создадим переменную structTime, используя функцию MqlDateTime, которая содержит данные даты и времени

MqlDateTime structTime;

Передадим созданную переменную structTime в функцию TimeCurrent

TimeCurrent(structTime);

Установка секунд на 0 часов и минут для времени начала

   structTime.sec = 0;
   structTime.hour = TimeStartHour;
   structTime.min = TimeStartMin;

Создадим переменную datetime для timeStart и передадим structTime в функцию StructToTime, которая преобразует структурную переменную MqlDateTime в значение типа datetime, а затем присваивает ее переменной timeStart

datetime timeStart = StructToTime(structTime);

Установим часы и минуты времени окончания

   structTime.hour = TimeEndHour;
   structTime.min = TimeEndMin;

Создадим переменную timeEnd так же, как мы делали с timeStart.

datetime timeEnd = StructToTime(structTime);

Создадим логическую переменную isTime для определения разрешенного времени для торговли.

bool isTime = TimeCurrent() >= timeStart && TimeCurrent() < timeEnd;

Создадим сообщение об ошибке в случае неверного ввода

   if(TimeStartHour >= TimeEndHour)
     {
      Print("Error: Invalid Time input");
     }

Установим условия торгового времени

   if(isTime==true)
     {
      Print("Trading is active based on time filter");
     }
   else
      Print("Trading is inactive based on time filter");

Полный код выглядит так:

//+------------------------------------------------------------------+
//|                                               timeFilterApp2.mq5 |
//+------------------------------------------------------------------+
input int TimeStartHour = 10;
input int TimeStartMin = 0;
input int TimeEndHour = 17;
input int TimeEndMin = 0;
//+------------------------------------------------------------------+
void OnTick()
  {
   MqlDateTime structTime;
   TimeCurrent(structTime);
   structTime.sec = 0;
   structTime.hour = TimeStartHour;
   structTime.min = TimeStartMin;
   datetime timeStart = StructToTime(structTime);
   structTime.hour = TimeEndHour;
   structTime.min = TimeEndMin;
   datetime timeEnd = StructToTime(structTime);
   bool isTime = TimeCurrent() >= timeStart && TimeCurrent() < timeEnd;
   if(TimeStartHour >= TimeEndHour)
     {
      Print("Error: Invalid Time input");
     }
   if(isTime==true)
     {
      Print("Trading is active based on time filter");
     }
   else
      Print("Trading is inactive based on time filter");
  }
//+------------------------------------------------------------------+

Выполнив код, мы увидим следующие результаты:

В случае активного времени:

 timeFilterApp2inpactive

timeFilterApp2active

В случае неактивного времени для торговли

timeFilterApp2inpinactive

 timeFilterApp2inactiv

В случае неверных входных значений

 timeFilterApp2inperror

 timeFilterApp2error


Применение tradeAtTime

Допустим, нам нужно установить конкретное время, в которое нам нужно только торговать, нам нужно будет установить это время как разрешенное время для торговли, и ниже приведены необходимые для этого шаги.

Создаем строковую входную переменную openTime со значением по умолчанию "10:00"

input string openTime="10:00";

Создаем переменной datetime для LastTime

datetime lastTime;

В части OnTick() создадим переменную datatime dtOpenTime, чтобы присвоить ей значения StringToTime для openTime

datetime dtOpenTime=StringToTime(openTime);

Проверяем условие разрешенного времени. Если последнее разрешенное время не равно dtOpenTime и в то же время timeCurrent() больше, чем dtOpenTime, нам нужно обновить значение LastTime с помощью dtOpenTime и напечатать сообщение "Now is the allowed time to trade" (разрешенное время торговли). Это сообщение появится один раз в указанное время.

   if(lastTime !=dtOpenTime && TimeCurrent()>dtOpenTime)
     {
      lastTime=dtOpenTime;
      Print("Now is the allowed time to trade");
     }

Ниже приведен полный код:

//+------------------------------------------------------------------+
//|                                                  tradeAtTime.mq5 |
//+------------------------------------------------------------------+
input string openTime="10:00";
datetime lastTime;
//+------------------------------------------------------------------+
void OnTick()
  {
   datetime dtOpenTime=StringToTime(openTime);
   if(lastTime !=dtOpenTime && TimeCurrent()>dtOpenTime)
     {
      lastTime=dtOpenTime;
      Print("Now is the allowed time to trade");
     }
  }
//+------------------------------------------------------------------+

После выполнения кода находим его сигнал:

 tradeAtTime

Заключение

Мы рассмотрели, что такое дата и время и как мы можем обращаться с ними в MQL5 при создании своих приложений. Мы применили наши знания при создании простых приложений. Мы рассмотрели следующие темы:

  • Тип datetime
  • Структура MqlDateTime
  • Событие OnTimer
  • Применение NewBar
  • Применение временного фильтра
  • Применение tradeAtTime

Существует множество приложений, работающих с датой и временем, и мы не можем перечислить их все, но, понимая основы, мы можем применить полученные знания при создании собственных приложений.

По ссылкам ниже вы можете ознакомиться с другими моими статьями. В частности, вы можете найти серию статей о создании торговых систем на основе самых популярных технических индикаторов. Надеюсь, они окажутся полезными.

Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/13466

Прикрепленные файлы |
dateTime.mqh (2.1 KB)
newBar.mq5 (0.68 KB)
timeFilterApp.ex5 (6.52 KB)
timeFilterApp2.mq5 (1.12 KB)
tradeAtTime.mq5 (0.62 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (10)
JRandomTrader
JRandomTrader | 25 февр. 2024 в 15:25
Maxim Kuznetsov #:

Он там от начала месяца секунды берёт, видимо, чтоб короче число было.

Хотя с почти (если не нужен обратный пересчёт имени объекта в день месяца) тем же результатом можно взять остаток от деления TimeCurrent() на число, близкое к среднему числу секунд в месяце.

Maxim Kuznetsov
Maxim Kuznetsov | 25 февр. 2024 в 16:32
JRandomTrader #:

Он там от начала месяца секунды берёт, видимо, чтоб короче число было.

Хотя с почти (если не нужен обратный пересчёт имени объекта в день месяца) тем же результатом можно взять остаток от деления TimeCurrent() на число, близкое к среднему числу секунд в месяце.

а вычесть из одной даты другую (начало месяца) не позволяет какая-то хитрая религия ? :-)

на практике - если где-то внутри нужно знать точное начало месяца, дня, недели то они однократно считаются и запоминаются. Чтобы лишний раз на каждый чих не пересчитывать

datetime thisDayTime, nextDayTime;
datetime thisYearTime,thisMonTime;
int thisYear, thisMon;

// вызывать внутри всех обработчиков OnXXX терминала- это прототип службы времени
void TimeService() {
    datetime now=TimeCurrent();
    if (now>=nextDayTime) {
        MqlDateTime dt; TimeToStruct(dt,now);
        dt.hour=dt.min=dt.sec=0;
        thisDayTime=StructToTime(dt);
        nextDayTime=thisDayTime+24*60*60;
        OnDay();  /// обработчик "начало дня"
        if (dt.month!=thisMon|| dt.year!=thisYear) {
               thisMon=dt.month;
               dt.day=0; thisMon=StructToTime(dt);
               OnMon();   /// обработчик "начало месяца"
        }

        if ( dt.year!=thisYear ) {
               thisYear=dt.year; 
               dt.month=0; thisYearTime=StructToTime(dt);
               OnYear();  /// обработчик "начало года"
        }
    }
}

JRandomTrader
JRandomTrader | 26 февр. 2024 в 09:39

Сорри, вспомнилось в тему:

Фредерик Браун
Конец начал

Профессор Джонс долгое время работал над теорией времени.
- И сегодня я нашел ключевое уравнение, - сказал он своей дочери как-то утром.
- Время это поле. Я создал  машину, которая способна управлять этим полем.
Он протянул руку и, нажимая кнопку, сказал:
- Это заставит время идти назад идти время заставит это
- :сказал, кнопку нажимая, и руку протянул он.
- Полем этим управлять способна которая, машину создал я. Поле это время,
- утром как-то дочери своей он сказал. - Уравнение ключевое нашел я сегодня и.
Времени теорией над работал время долгое Джонс профессор.

Начал конец
Браун Фредерик
Sergey Gridnev
Sergey Gridnev | 26 февр. 2024 в 09:47
JRandomTrader #:

Сорри, вспомнилось в тему:

Наверное, стоило не только порядок слов перевернуть, но и порядок букв ;)
Edgar Akhmadeev
Edgar Akhmadeev | 26 февр. 2024 в 13:08
JRandomTrader #:

Сорри, вспомнилось в тему:

Вспомнил советскую фантастическую повесть, где дочь за перед экспериментом отца в институте времени твердила ему "укпонк имжан", а он не понимал её детское баловство.

А она спасла его этим.

Оптимизация и тестирование торговых стратегий (Часть 1): Взгляд на "Red Dragon H4", "BOLT", "YinYang", и "Statistics SAR" Оптимизация и тестирование торговых стратегий (Часть 1): Взгляд на "Red Dragon H4", "BOLT", "YinYang", и "Statistics SAR"
Так как я постоянно занимаюсь, разработкой разного рода торговых систем сегодня хочу поделиться с Вами несколькими из них по стратегиям "Red Dragon H4", "BOLT", "YinYang" и "Statistics SAR". Данные стратегии были найдены на просторах интернета.
Угловые операции для трейдеров Угловые операции для трейдеров
В этой статье будут рассмотрены угловые операции. Мы рассмотрим методы построения углов и способы их применения в трейдинге.
Нейросети — это просто (Часть 78): Детектор объектов на основе Трансформера (DFFT) Нейросети — это просто (Часть 78): Детектор объектов на основе Трансформера (DFFT)
В данной статье я предлагаю посмотреть на вопрос построения торговой стратегии с другой стороны. Мы не будем прогнозировать будущее ценовое движение, а попробуем построить торговую систему на основе анализа исторических данных.
Добавляем пользовательскую LLM в торгового робота (Часть 1): Развертывание оборудования и среды Добавляем пользовательскую LLM в торгового робота (Часть 1): Развертывание оборудования и среды
Языковые модели (LLM) являются важной частью быстро развивающегося искусственного интеллекта, поэтому нам следует подумать о том, как интегрировать мощные LLM в нашу алгоритмическую торговлю. Большинству людей сложно настроить эти мощные модели в соответствии со своими потребностями, развернуть их локально, а затем применить к алгоритмической торговле. В этой серии статей будет рассмотрен пошаговый подход к достижению этой цели.