Перейти к содержанию

(MQL) 2.1 Преобразование данных

Last updated on 29.05.2021

преобразование данных

В прошлой статье я описал некоторые перечисления. По сути это один из видов данных, которые будут активно использоваться нашим фреймворком. В дальнейшем очень часто будет возникать необходимость в преобразовании данных. Поэтому надо уже сейчас создавать необходимый функционал. Речь идёт о функциях-помощниках. Их ещё называют “Хелперы”.

Шаблонные функции

Для начала разберёмся с приведением типов. Это преобразование данных одного типа в другой тип. Для этого создаём новый файл “Conversion.mqh” в папке “Helpers” нашего проекта.

conversion

Открываем файл. Подключаем файл “Enums.mqh” из папки Enums. Кликаем правой кнопкой мыши и в появившемся меню выбираем “Вставить”-> “MQH”. В открывшемся окне находим наш проект. Открываем папку “Enums”. Выбираем файл “Enums.mqh”.

conversion-mqh

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

Преобразование данных

Вот так выглядит шаблонная функция, которая будет использоваться далее:

template<typename T1,typename T2>
T2 Convert(T1 var1,T2 var2)
{
var2=(T2)var1;
return var2;
}

В параметрах функции используются две переменные с разным типом. В переменную var1 передаются те данные, тип (T1) которых мы хотим изменить. А в переменную var2 передаются данные с тем типом (T2), который мы хотим получить на выходе. Конечно можно обе переменные просто передать по ссылке, тогда функция будет иметь такой вид:

template<typename T1,typename T2>
void Convert(T1 &var1,T2 &var2)
{
 var2=(T2)var1;
}

Лично мне удобнее использовать первый вариант, но вы можете сохранить оба. Правда в этом случае у функций должны быть разные имена. Иначе компилятор выскажет вам своё недовольство в виде сообщения “ambiguous call to overloaded function with the same parameters“.

Преобразование перечисления ENUM_EVENTS_TYPE

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

Для начала напишем функции преобразования для перечисления ENUM_EVENTS_TYPE

// Эта функция приводит перечисление ENUM_EVENTS_TYPE к строковому типу 

string EventsTypeToString(ENUM_EVENTS_TYPE set)
{
return EnumToString(set);
}

Для подобного приведения используется стандартная функция EnumToString().

// Эта функция приводит перечисление ENUM_EVENTS_TYPE к числовому типу. Тут используется шаблонная функция "Convert()"

int EventsTypeToInteger(ENUM_EVENTS_TYPE set)
{
 int idx = -1;
 return Convert(set,idx);
}

Следующая функция “IntegerToEventsType()”:

// Эта функция совершает обратное преобразование от числового значения к  перечислению ENUM_EVENTS_TYPE.

ENUM_EVENTS_TYPE IntegerToEventsType(int set)
 {
  ENUM_EVENTS_TYPE type;
  return Convert(set,type);
 }

Далее идёт функция “StringToEventsType()”:

// Эта функция совершает обратное преобразование от строкового значения к  перечислению ENUM_EVENTS_TYPE.

ENUM_EVENTS_TYPE StringToEventsType(string set)
{
 ENUM_EVENTS_TYPE type=-1;
 if(set == "CHECK_NEW_TICK") type = CHECK_NEW_TICK;
 else if(set == "CHECK_NEW_BAR") type = CHECK_NEW_BAR;
 else if(set == "CHECK_NEW_TIME") type = CHECK_NEW_TIME;
 else if(set == "CHECK_SUM_LOSS") type = CHECK_SUM_LOSS;
 else if(set == "CHECK_SUM_PROFIT") type = CHECK_SUM_PROFIT;
 else if(set == "CHECK_ORDERS") type = CHECK_ORDERS;
 
 return type;
}

К сожалению использование функции “Convert()” в этом случае бесполезно. Следует отметить, что приведение перечислений к строковому типу необходимо при записи некоторой информации в файл или выводе её на экран монитора.

Преобразование перечисления ENUM_CLOSE_ORDER

Теперь переходим к следующему перечислению – ENUM_CLOSE_ORDER.

// Эта функция приводит перечисление ENUM_CLOSE_ORDER к строковому типу

string CloseOrderToString(ENUM_CLOSE_ORDER set)
{
return EnumToString(set);
}

Информация о всех закрытых заявках будет храниться не только в файле, но и в отдельном списке.

// Эта функция приводит перечисление ENUM_EVENTS_TYPE к числовому типу

int CloseOrderToInteger(ENUM_CLOSE_ORDER set)
{
 int idx = -1;
 return Convert(set,idx);
}

// Эта функция совершает обратное преобразование от числового значения к  перечислению ENUM_CLOSE_ORDER .

ENUM_CLOSE_ORDER IntegerToCloseOrder(int set)
 {
  ENUM_CLOSE_ORDER type;
  return Convert(set,type);
 }

Список будет заполняться в процессе работы торгового робота. Всю информацию по закрытым заявкам потом можно будет использовать при разработке торговых стратегий.

// Эта функция совершает обратное преобразование от строкового значения к  перечислению ENUM_CLOSE_ORDER.

ENUM_CLOSE_ORDER StringToCloseOrder(string set)
{
ENUM_CLOSE_ORDER type=-1;

if(set==  "CLOSE_ALL_LONG") type =  CLOSE_ALL_LONG;
 else if(set==  "CLOSE_ALL_SHORT") type =  CLOSE_ALL_SHORT;
 else if(set==  "CLOSE_ALL_BUY") type =  CLOSE_ALL_BUY;
 else if(set==  "CLOSE_ALL_BUY_STOP") type =  CLOSE_ALL_BUY_STOP;
 else if(set==  "CLOSE_ALL_BUY_LIMIT") type =  CLOSE_ALL_BUY_LIMIT;
 else if(set==  "CLOSE_ALL_SELL") type =  CLOSE_ALL_SELL;
 else if(set==  "CLOSE_ALL_SELL_STOP") type =  CLOSE_ALL_SELL_STOP; 
 else if(set==  "CLOSE_ALL_SELL_LIMIT") type =  CLOSE_ALL_SELL_LIMIT;
 else if(set==  "CLOSE_ALL_BUY_STOP_LIMIT") type =  CLOSE_ALL_BUY_STOP_LIMIT; 
 else if(set==  "CLOSE_ALL_SELL_STOP_LIMIT") type =  CLOSE_ALL_SELL_STOP_LIMIT; 
 else if(set==  "CLOSE_ALL_BUY_STOP_STOP") type =  CLOSE_ALL_BUY_STOP_STOP; 
 else if(set==  "CLOSE_ALL_SELL_STOP_STOP") type =  CLOSE_ALL_SELL_STOP_STOP; 
 else if(set==  "CLOSE_ALL_BUY_TIME") type =  CLOSE_ALL_BUY_TIME; 
 else if(set==  "CLOSE_ALL_SELL_TIME") type =  CLOSE_ALL_SELL_TIME; 
 else if(set==  "CLOSE_ALL_BUY_STOP_TIME") type =  CLOSE_ALL_BUY_STOP_TIME; 
 else if(set==  "CLOSE_ALL_SELL_STOP_TIME") type =  CLOSE_ALL_SELL_STOP_TIME; 
 else if(set==  "CLOSE_ALL_BUY_LIMIT_TIME") type =  CLOSE_ALL_BUY_LIMIT_TIME; 
 else if(set==  "CLOSE_ALL_SELL_LIMIT_TIME") type =  CLOSE_ALL_SELL_LIMIT_TIME; 
 else if(set==  "CLOSE_ALL_BUY_STOP_LIMIT_TIME") type =  CLOSE_ALL_BUY_STOP_LIMIT_TIME; 
 else if(set==  "CLOSE_ALL_SELL_STOP_LIMIT_TIME") type =  CLOSE_ALL_SELL_STOP_LIMIT_TIME; 
 else if(set==  "CLOSE_ALL_BUY_SUM_LOSS") type =  CLOSE_ALL_BUY_SUM_LOSS; 
 else if(set==  "CLOSE_ALL_SELL_SUM_LOSS") type =  CLOSE_ALL_SELL_SUM_LOSS; 
 else if(set==  "CLOSE_ALL_BUY_SUM_PROFIT") type =  CLOSE_ALL_BUY_SUM_PROFIT;
 else if(set==  "CLOSE_ALL_SELL_SUM_PROFIT") type =  CLOSE_ALL_SELL_SUM_PROFIT;
 else if(set==  "CLOSE_ALL_PROFIT_ORDERS") type =  CLOSE_ALL_PROFIT_ORDERS;
 else if(set==  "CLOSE_ALL_LOSS_ORDERS") type =   CLOSE_ALL_LOSS_ORDERS;
 else if(set==  "CLOSE_ALL_EQUAL_PRICE") type =  CLOSE_ALL_EQUAL_PRICE;
 else if(set==  "CLOSE_ALL_EQUAL_LOT") type =  CLOSE_ALL_EQUAL_LOT;
 else if(set==  "CLOSE_ALL_SWAP_PLUS") type =  CLOSE_ALL_SWAP_PLUS;
 else if(set==  "CLOSE_ALL_SWAP_MINUS") type =  CLOSE_ALL_SWAP_MINUS;
 else if(set==  "CLOSE_ALL_TICKET") type =  CLOSE_ALL_TICKET;
 else if(set==  "CLOSE_ALL_SYMBOL") type =  CLOSE_ALL_SYMBOL;
 else if(set==  "CLOSE_ALL_NAME") type =  CLOSE_ALL_NAME;
 
return type;
}

Преобразование перечисления ENUM_MODIFY_ORDER

Продолжаем преобразование данных. На очереди перечисление – ENUM_MODIFY_ORDER.

// Эта функция приводит перечисление ENUM_MODIFY_ORDER к строковому типу

string ModifyOrderToString(ENUM_MODIFY_ORDER set)
{
return EnumToString(set);
}

// Эта функция приводит перечисление ENUM_MODIFY_ORDER к числовому типу

int ModifyOrderToInteger(ENUM_MODIFY_ORDER set)
{
int idx = -1;
return Convert(set,idx);
}

// Эта функция совершает обратное преобразование от числового значения к  перечислению ENUM_MODIFY_ORDER.

ENUM_MODIFY_ORDER IntegerToModifyOrder(int set)
{
 ENUM_MODIFY_ORDER type=-1;
 return Convert(set,type);
 
}

// Эта функция совершает обратное преобразование от строкового значения к  перечислению ENUM_MODIFY_ORDER.

ENUM_MODIFY_ORDER StringToModifyOrder(string set)
{
 ENUM_MODIFY_ORDER type=-1;

 if(set==  "MODIFY_STOP_LOSS") type = MODIFY_STOP_LOSS;
  else if(set==  "MODIFY_TAKE_PROFIT") type = MODIFY_TAKE_PROFIT;
  else if(set==  "MODIFY_PRICE_OPEN") type = MODIFY_PRICE_OPEN;
  else if(set==  "MODIFY_TIME_EXPIRATION") type = MODIFY_TIME_EXPIRATION;
  else if(set==  "MODIFY_TIME_OPEN") type = MODIFY_TIME_OPEN;
  else if(set==  "MODIFY_PRICE_STOP") type = MODIFY_PRICE_STOP;
  else if(set==  "MODIFY_LOT") type = MODIFY_LOT;

return type;
}

Все модификации заявок происходят на стороне торгового робота. Для дилингового центра (или брокера) все эти операции остаются невидимыми, так как открытые позиции остаются неизменными.

Преобразование перечисления ENUM_OPEN_ORDER_TYPE

Что касается этого перечисления, то основная масса заявок, кроме ENUM_ORDER_BUY и ENUM_ORDER_SELL, носит виртуальный характер. То есть все они выставляются на стороне торгового робота, но на реальный рынок не выносятся. А связано это с тем, что:

  1. количество заявок, с которыми будет работать создаваемый фреймворк, намного больше того, с чем работает торговый терминал MetaTrader 5
  2. так как торговый терминал работает с позициями, то возможность обработки отдельных активных заявок максимально ограничена
  3. нежелание некоторых трейдеров показывать дилинговым центрам (ДЦ) расположение уровней стоп-лоссов и тейк-профитов.
// Эта функция приводит перечисление ENUM_OPEN_ORDER_TYPE к строковому типу

string OpenOrderTypeToString(ENUM_OPEN_ORDER_TYPE set)
{
 return EnumToString(set);
}
// Эта функция приводит перечисление ENUM_OPEN_ORDER_TYPE к числовому типу

int OpenOrderTypeToInteger(ENUM_OPEN_ORDER_TYPE set)
{
 int idx = -1;
 return Convert(set,idx);
}

Торговый робот будет активировать и изменять заявки (открытие, наращивание, сокращение и закрытие позиции) только при наступлении определённых условий. Эти условия будут зависеть от торговой стратегии.

// Эта функция совершает обратное преобразование от числового значения к  перечислению ENUM_OPEN_ORDER_TYPE.

ENUM_OPEN_ORDER_TYPE IntegerToOpenOrderType(int set)
{
 ENUM_OPEN_ORDER_TYPE type=-1;
 return Convert(set,type);
}
// Эта функция совершает обратное преобразование от строкового значения к  перечислению ENUM_OPEN_ORDER_TYPE.

ENUM_OPEN_ORDER_TYPE StringToOpenOrderType(string set)
{
  ENUM_OPEN_ORDER_TYPE type=-1;

  if(set==  "ENUM_ORDER_BUY") type =  ENUM_ORDER_BUY;
   else if(set==   "ENUM_ORDER_BUY_STOP") type =  ENUM_ORDER_BUY_STOP;
   else if(set==   "ENUM_ORDER_BUY_LIMIT") type =     ENUM_ORDER_BUY_LIMIT;
   else if(set==   "ENUM_ORDER_SELL") type =  ENUM_ORDER_SELL;
   else if(set==   "ENUM_ORDER_SELL_STOP") type =  ENUM_ORDER_SELL_STOP; 
   else if(set==   "ENUM_ORDER_SELL_LIMIT") type =  ENUM_ORDER_SELL_LIMIT;
   else if(set==   "ENUM_ORDER_BUY_STOP_LIMIT") type =  ENUM_ORDER_BUY_STOP_LIMIT; 
   else if(set==   "ENUM_ORDER_SELL_STOP_LIMIT") type =  ENUM_ORDER_SELL_STOP_LIMIT; 
   else if(set==   "ENUM_ORDER_BUY_STOP_STOP") type =  ENUM_ORDER_BUY_STOP_STOP; 
   else if(set==   "ENUM_ORDER_SELL_STOP_STOP") type =  ENUM_ORDER_SELL_STOP_STOP; 
   else if(set==   "ENUM_ORDER_BUY_TIME") type =  ENUM_ORDER_BUY_TIME; 
   else if(set==   "ENUM_ORDER_SELL_TIME") type =  ENUM_ORDER_SELL_TIME; 
   else if(set==   "ENUM_ORDER_BUY_STOP_TIME") type =  ENUM_ORDER_BUY_STOP_TIME; 
   else if(set==   "ENUM_ORDER_SELL_STOP_TIME") type =  ENUM_ORDER_SELL_STOP_TIME; 
   else if(set==   "ENUM_ORDER_BUY_LIMIT_TIME") type =  ENUM_ORDER_BUY_LIMIT_TIME; 
   else if(set==   "ENUM_ORDER_SELL_LIMIT_TIME") type =  ENUM_ORDER_SELL_LIMIT_TIME; 
   else if(set==   "ENUM_ORDER_BUY_STOP_LIMIT_TIME") type =  ENUM_ORDER_BUY_STOP_LIMIT_TIME; 
   else if(set==   "ENUM_ORDER_SELL_STOP_LIMIT_TIME") type =  ENUM_ORDER_SELL_STOP_LIMIT_TIME; 
   else if(set==   "ENUM_ORDER_BUY_SUM_LOSS") type =  ENUM_ORDER_BUY_SUM_LOSS; 
   else if(set==   "ENUM_ORDER_SELL_SUM_LOSS") type =  ENUM_ORDER_SELL_SUM_LOSS; 
   else if(set==   "ENUM_ORDER_BUY_SUM_PROFIT") type =  ENUM_ORDER_BUY_SUM_PROFIT;
   else if(set==   "ENUM_ORDER_SELL_SUM_PROFIT") type =  ENUM_ORDER_SELL_SUM_PROFIT;

return type;
}

Преобразование перечисления ENUM_LOT_CALCULATE

Трейдеры, особенно начинающие, часто рассчитывают объём заявки используя такую штуку как “Мартингейл“, а также “сеточное” размещение заявок. Поэтому в торговый фреймворк я включил расчёт объёмов заявок по системе “Мартингейл” и “Альтернативный Мартингейл”. Также я добавил три варианта расчёта объёмов для “сеточного” размещения.

// Эта функция приводит перечисление ENUM_LOT_CALCULATE к строковому типу

string LotCalculateToString(ENUM_LOT_CALCULATE set)
{
return EnumToString(set);
}
// Эта функция приводит перечисление ENUM_OPEN_ORDER_TYPE к числовому типу

int LotCalculateToInteger(ENUM_LOT_CALCULATE set)
{
int idx = -1;
return Convert(set,idx);
}

Кроме того в фреймворк включён расчет объёма заявки, который вычисляется исходя из размера доли свободных средств, которой трейдер готов “пожертвовать”.

// Эта функция совершает обратное преобразование от числового значения к  перечислению ENUM_LOT_CALCULATE.

ENUM_LOT_CALCULATE IntegerToLotCalculate(int set)
{
ENUM_LOT_CALCULATE type=-1;
return Convert(set,type);
}
// Эта функция совершает обратное преобразование от строкового значения к  перечислению ENUM_LOT_CALCULATE.

ENUM_LOT_CALCULATE StringToLotCalculate(string set)
{
 ENUM_LOT_CALCULATE type=-1;

 if(set==  "LOT_CALCULATE_DEFAULT") type = LOT_CALCULATE_DEFAULT;
  else if(set==  "LOT_CALCULATE_PERCENT") type = LOT_CALCULATE_PERCENT;
  else if(set==  "LOT_CALCULATE_MARTIN") type = LOT_CALCULATE_MARTIN;
  else if(set==  "LOT_CALCULATE_MARTIN_ALTER") type = LOT_CALCULATE_MARTIN_ALTER;
  else if(set==  "LOT_CALCULATE_GRID_ASCEND") type = LOT_CALCULATE_GRID_ASCEND;
  else if(set==  "LOT_CALCULATE_GRID_DESCEND") type = LOT_CALCULATE_GRID_DESCEND;
  else if(set==  "LOT_CALCULATE_GRID_SAW") type = LOT_CALCULATE_GRID_SAW;

return type;
}

Преобразование перечисления ENUM_ORDER_TABLE_TYPE

Все заявки, будут заносится в таблицу. Эта таблица будет обрабатываться торговым роботом. Каждая заявка будет помечаться перечислением ENUM_ORDER_TABLE_TYPE.

// Эта функция приводит перечисление ENUM_ORDER_TABLE_TYPE к строковому типу

string OrderTableTypeToString(ENUM_ORDER_TABLE_TYPE set)
{
return EnumToString(set);
}

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

// Эта функция приводит перечисление ENUM_ORDER_TABLE_TYPE к числовому типу

int OrderTableTypeToInteger(ENUM_ORDER_TABLE_TYPE set)
{
int idx = -1;
return Convert(set,idx);
}
// Эта функция совершает обратное преобразование от числового значения к  перечислению ENUM_ORDER_TABLE_TYPE.

ENUM_ORDER_TABLE_TYPE IntegerToOrderTableType(int set)
{
ENUM_ORDER_TABLE_TYPE type=-1;
switch(set)
{
case 0: type= ENUM_TABLE_MARKET;break;
case 1: type= ENUM_TABLE_INDICATOR;break;
}
return type;
}

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

// Эта функция совершает обратное преобразование от строкового значения к  перечислению ENUM_ORDER_TABLE_TYPE.

ENUM_ORDER_TABLE_TYPE StringToOrderTableType(string set)
{
ENUM_ORDER_TABLE_TYPE type=-1;
if(set==  "ENUM_TABLE_MARKET") type = ENUM_TABLE_MARKET;
else if(set==  "ENUM_TABLE_INDICATOR") type = ENUM_TABLE_INDICATOR;
return type;
}

Преобразование перечисления ENUM_LANGUAGE

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

// Эта функция приводит перечисление ENUM_LANGUAGE к строковому типу

string LanguageToString(ENUM_LANGUAGE set)
{
return EnumToString(set);
}
//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+

Если нужный перевод отсутствует, то трейдер сможет создать его самостоятельно и в дальнейшем его использовать.

// Эта функция приводит перечисление ENUM_LANGUAGE к числовому типу

int LanguageToInteger(ENUM_LANGUAGE set)
{
int idx = -1;
return Convert(set,idx);
}

Преобразование перечисления ENUM_TIMEFRAMES

Данное перечисление является стандартным. Поэтому ранее оно не рассматривалось.

// Эта функция приводит перечисление ENUM_TIMEFRAMES к строковому типу

string TimeFrameToString(ENUM_TIMEFRAMES set)
{
return EnumToString(set);
}
// Эта функция приводит перечисление ENUM_TIMEFRAMES к числовому типу

int TimeFrameToInteger(ENUM_TIMEFRAMES set)
{
int idx = -1;
return Convert(set,idx);
}

Использование этого перечисления позволяет не только создавать торговые стратегии для разных таймфреймов.

// Эта функция совершает обратное преобразование от числового значения к  перечислению ENUM_TIMEFRAMES.

ENUM_TIMEFRAMES IntegerToTimeFrame(int set)
{
 ENUM_TIMEFRAMES type=-1;
 return Convert(set,type);
}
// Эта функция совершает обратное преобразование от строкового значения к  перечислению ENUM_TIMEFRAMES.

ENUM_TIMEFRAMES StringToTimeFrame(string set)
 {
  ENUM_TIMEFRAMES type=-1;
  if(StringToLower(set)){
     if(set=="period_m1" || set=="m1")type= PERIOD_M1;
     if(set=="period_m2" || set=="m2")type= PERIOD_M2;
     if(set=="period_m3" || set=="m3")type= PERIOD_M3;
     if(set=="period_m4" || set=="m4")type= PERIOD_M4;
     if(set=="period_m5" || set=="m5")type= PERIOD_M5;
     if(set=="period_m6" || set=="m6")type= PERIOD_M6;
     if(set=="period_m10" || set=="m10")type= PERIOD_M10;
     if(set=="period_m12" || set=="m12")type= PERIOD_M12;
     if(set=="period_m15" || set=="m15")type= PERIOD_M15;
     if(set=="period_m20" || set=="m20")type= PERIOD_M20;
     if(set=="period_m30" || set=="m30")type= PERIOD_M30;
     if(set=="period_h1" || set=="h1")type= PERIOD_H1;
     if(set=="period_h2" || set=="h2")type= PERIOD_H2;
     if(set=="period_h3" || set=="h3")type= PERIOD_H3;
     if(set=="period_h4" || set=="h4")type= PERIOD_H4;
     if(set=="period_h6" || set=="h6")type= PERIOD_H6;
     if(set=="period_h8" || set=="h8")type= PERIOD_H8;
     if(set=="period_h12" || set=="h12")type= PERIOD_H12;
     if(set=="period_d1" || set=="d1")type= PERIOD_D1;
     if(set=="period_w1" || set=="w1")type= PERIOD_W1;
     if(set=="period_mn1" || set=="mn1")type= PERIOD_MN1;
     if(set=="period_current" || set=="current" || set=="m0" || set=="period_m0")type= PERIOD_CURRENT;
    }
    return type;
 }

Это только часть функций. В дальнейшем их список пополниться.

Опубликовано в рубрике2. ХелперыОснову для торговых роботов (MQL)