
В прошлой статье я описал некоторые перечисления. По сути это один из видов данных, которые будут активно использоваться нашим фреймворком. В дальнейшем очень часто будет возникать необходимость в преобразовании данных. Поэтому надо уже сейчас создавать необходимый функционал. Речь идёт о функциях-помощниках. Их ещё называют «Хелперы».
Шаблонные функции
Для начала разберёмся с приведением типов. Это преобразование данных одного типа в другой тип. Для этого создаём новый файл «Conversion.mqh» в папке «Helpers» нашего проекта.

Открываем файл. Подключаем файл «Enums.mqh» из папки Enums. Кликаем правой кнопкой мыши и в появившемся меню выбираем «Вставить»-> «MQH». В открывшемся окне находим наш проект. Открываем папку «Enums». Выбираем файл «Enums.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, носит виртуальный характер. То есть все они выставляются на стороне торгового робота, но на реальный рынок не выносятся. А связано это с тем, что:
- количество заявок, с которыми будет работать создаваемый фреймворк, намного больше того, с чем работает торговый терминал MetaTrader 5
- так как торговый терминал работает с позициями, то возможность обработки отдельных активных заявок максимально ограничена
- нежелание некоторых трейдеров показывать дилинговым центрам (ДЦ) расположение уровней стоп-лоссов и тейк-профитов.
// Эта функция приводит перечисление 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; }
Это только часть функций. В дальнейшем их список пополниться.