Библиотека для простого и быстрого создания программ для MetaTrader (Часть XIX): Класс сообщений библиотеки

26 августа 2019, 09:12
Artyom Trishkin
0
1 159

Содержание

Текстовые сообщения любой программы носят, на первый взгляд, вспомогательный характер, и кажутся совершенно незначительной её составляющей. Так что вроде как на задачу их организации можно и не обращать внимания: есть — хорошо, нету — ну и не важно. Однако это совсем не так. Любые сообщения из программы являются неотъемлемой частью коммуникации между пользователем и программой. Будь то простая программа или некий серьёзный проект — сообщения, порой, оказываются единственным связующим звеном между пользователем и программой.

В нашей библиотеке на данный момент организован самый простой вариант организации и вывода сообщений — сразу в тексте классов библиотеки в месте, где необходимо вывести сообщение в журнал "Эксперты", прописан код вывода сообщения на двух языках — в зависимости от языка терминала выводится сообщение либо на русском языке, либо на английском. Для текущих потребностей этого вполне достаточно. Но такая организация работы с текстом становится весьма не удобной в случае, если требуется перевод русского текста на иной язык, отличный от английского: пользователю, решившему перевести русские сообщения на другой язык, либо добавить в программу ещё один язык к двум уже имеющимся, потребуется найти разрозненные по разным файлам и разным местам файлов и заменить все русские сообщения на необходимые. Это очень неудобно.
И такая организация данных таит в себе ещё одну проблему: при создании множества однотипных объектов, имеющих в своём составе тексты, все созданные объекты будут содержать в себе абсолютно одинаковые текстовые сообщения, что в конечном итоге сказывается на размере скомпилированной программы. А ведь такие повторяющиеся от объекта к объекту тексты можно написать лишь в единственном экземпляре, и далее уже обращаться к ним по их месту расположения.

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

Концепция хранения и вывода сообщений

На мой взгляд, удобным способом хранения и использования текстовых сообщений является создание многомерного массива этих сообщений, где в первом измерении будет храниться индекс, указывающий на конкретное сообщение, а во втором измерении будут храниться сами сообщения на разных языках. В нулевом индексе второго измерения будем хранить сообщения на языке страны пользователя (для данной редакции библиотеки — на русском), в первом индексе второго измерения будем хранить сообщения на международном языке — на английском, а во всех последующих индексах — любые добавляемые пользователем в библиотеку языки по его потребности.

Таким образом все сообщения библиотеки у нас будут собраны в массив, а индексы нужных сообщений — в перечисление. Второй (и как оказалось — ещё несколько) массив у нас будет создан для хранения сообщений об ошибках, возвращаемых непосредственно терминалом — коды возврата торгового сервера и коды ошибок времени выполнения программы. Для этих массивов индексом нужного сообщения будет являться код, возвращаемый функцией GetLastError().

Создаваемый сегодня класс работы с сообщениями будет уметь

  • выводить нужное сообщение на выбранном языке по индексу предопределённого сообщения (все сообщения библиотеки),
  • выводить сообщение на выбранном языке по коду возврата торгового сервера или коду ошибки из функции GetLastError(),
  • выводить переданное в него сообщение "как есть",
  • отправлять сообщение на e-mail,
  • отправлять Push-уведомление на мобильное устройство,
  • отправлять указанный файл на FTP-адрес,
  • проигрывать указанную мелодию,
  • удобно добавлять  сообщения на дополнительных языках к каждому из уже имеющихся предопределённых сообщений: просто дописать в базу — двумерный массив сообщений, нужный перевод сообщения на требуемом языке,
  • легко переключаться между языком программы — достаточно указать нужный индекс второго измерения массива, по которому расположены сообщения требуемого языка.

База данных текстов сообщений

Так как мы условились хранить все предопределённые сообщения в массивах и иметь списки-перечисления с индексами, указывающими на расположение требуемого сообщения в массиве, то в файле библиотеки \MQL5\Include\DoEasy\ Datas.mqh создадим для них требуемое перечисление (индекс первого сообщения будет равен индексу, с которого начинается список пользовательских ошибок — это позволит не пересекаться индексам сообщений библиотеки с кодом какого-либо стандартного сообщения терминала):

//+------------------------------------------------------------------+
//| Список индексов текстовых сообщений библиотеки                   |
//+------------------------------------------------------------------+
enum ENUM_MESSAGES_LIB
  {
   MSG_LIB_PARAMS_LIST_BEG=ERR_USER_ERROR_FIRST,      // Начало списка параметров
   MSG_LIB_PARAMS_LIST_END,                           // Конец списка параметров
   MSG_LIB_PROP_NOT_SUPPORTED,                        // Свойство не поддерживается
   MSG_LIB_PROP_NOT_SUPPORTED_MQL4,                   // Свойство не поддерживается в MQL4
   MSG_LIB_PROP_NOT_SUPPORTED_POSITION,               // Свойство не поддерживается у позиции
   MSG_LIB_PROP_NOT_SUPPORTED_PENDING,                // Свойство не поддерживается у отложенного ордера
   MSG_LIB_PROP_NOT_SUPPORTED_MARKET,                 // Свойство не поддерживается у маркет-ордера
   MSG_LIB_PROP_NOT_SUPPORTED_MARKET_HIST,            // Свойство не поддерживается у исторического маркет-ордера
   MSG_LIB_PROP_NOT_SET,                              // Значение не задано
   MSG_LIB_PROP_EMPTY,                                // Отсутствует
   
   MSG_LIB_SYS_ERROR,                                 // Ошибка
   MSG_LIB_SYS_NOT_SYMBOL_ON_SERVER,                  // Ошибка. Такого символа нет на сервере
   MSG_LIB_SYS_FAILED_PUT_SYMBOL,                     // Не удалось поместить в обзор рынка. Ошибка: 
   MSG_LIB_SYS_NOT_GET_PRICE,                         // Не удалось получить текущие цены. Ошибка: 
   MSG_LIB_SYS_NOT_GET_MARGIN_RATES,                  // Не удалось получить коэффициенты взимания маржи. Ошибка: 
   MSG_LIB_SYS_NOT_GET_DATAS,                         // Не удалось получить данные
   
   MSG_LIB_SYS_FAILED_CREATE_STORAGE_FOLDER,          // Не удалось создать папку хранения файлов. Ошибка: 
   MSG_LIB_SYS_FAILED_ADD_ACC_OBJ_TO_LIST,            // Ошибка. Не удалось добавить текущий объект-аккаунт в список-коллекцию
   MSG_LIB_SYS_FAILED_CREATE_CURR_ACC_OBJ,            // Ошибка. Не удалось создать объект-аккаунт с данными текущего счёта
   MSG_LIB_SYS_FAILED_OPEN_FILE_FOR_WRITE,            // Не удалось открыть для записи файл
   MSG_LIB_SYS_INPUT_ERROR_NO_SYMBOL,                 // Ошибка входных данных: нет символа
   MSG_LIB_SYS_FAILED_CREATE_SYM_OBJ,                 // Не удалось создать объект-символ
   MSG_LIB_SYS_FAILED_ADD_SYM_OBJ,                    // Не удалось добавить символ
   
   MSG_LIB_SYS_NOT_GET_CURR_PRICES,                   // Не удалось получить текущие цены по символу события
   MSG_LIB_SYS_EVENT_ALREADY_IN_LIST,                 // Такое событие уже есть в списке
   MSG_LIB_SYS_ERROR_ALREADY_CREATED_COUNTER,         // Ошибка. Уже создан счётчик с идентификатором
   MSG_LIB_SYS_FAILED_CREATE_COUNTER,                 // Не удалось создать счётчик таймера
   MSG_LIB_SYS_FAILED_CREATE_TEMP_LIST,               // Ошибка создания временного списка
   MSG_LIB_SYS_ERROR_NOT_MARKET_LIST,                 // Ошибка. Список не является списком рыночной коллекции
   MSG_LIB_SYS_ERROR_NOT_HISTORY_LIST,                // Ошибка. Список не является списком исторической коллекции
   MSG_LIB_SYS_FAILED_ADD_ORDER_TO_LIST,              // Не удалось добавить ордер в список
   MSG_LIB_SYS_FAILED_ADD_DEAL_TO_LIST,               // Не удалось добавить сделку в список
   MSG_LIB_SYS_FAILED_ADD_CTRL_ORDER_TO_LIST,         // Не удалось добавить контрольный ордер
   MSG_LIB_SYS_FAILED_ADD_CTRL_POSITION_TO_LIST,      // Не удалось добавить контрольую позицию
   MSG_LIB_SYS_FAILED_ADD_MODIFIED_ORD_TO_LIST,       // Не удалось добавить модифицированный ордер в список изменённых ордеров
    
   MSG_LIB_SYS_NO_TICKS_YET,                          // Ещё не было тиков
   MSG_LIB_SYS_FAILED_CREATE_OBJ_STRUCT,              // Не удалось создать структуру объекта
   MSG_LIB_SYS_FAILED_WRITE_UARRAY_TO_FILE,           // Не удалось записать uchar-массив в файл
   MSG_LIB_SYS_FAILED_LOAD_UARRAY_FROM_FILE,          // Не удалось загрузить uchar-массив из файла
   MSG_LIB_SYS_FAILED_CREATE_OBJ_STRUCT_FROM_UARRAY,  // Не удалось создать структуру объекта из uchar-массива
   MSG_LIB_SYS_FAILED_SAVE_OBJ_STRUCT_TO_UARRAY,      // Не удалось сохранить структуру объекта в uchar-массив, ошибка
   MSG_LIB_SYS_ERROR_INDEX,                           // Ошибка. Значение "index" должно быть в пределах 0 - 3
   
   MSG_LIB_SYS_ERROR_EMPTY_STRING,                    // Ошибка. Строка предопределённых символов пустая, будет использоваться
   MSG_LIB_SYS_FAILED_PREPARING_SYMBOLS_ARRAY,        // Не удалось подготовить массив используемых символов. Ошибка 
   MSG_LIB_SYS_INVALID_ORDER_TYPE,                    // Не правильный тип ордера:
   
   MSG_LIB_SYS_ERROR_FAILED_GET_PRICE_ASK,            // Не удалось получить цену Ask. Ошибка
   MSG_LIB_SYS_ERROR_FAILED_GET_PRICE_BID,            // Не удалось получить цену Bid. Ошибка
   MSG_LIB_SYS_ERROR_FAILED_OPEN_BUY,                 // Не удалось открыть позицию Buy. Ошибка
   MSG_LIB_SYS_ERROR_FAILED_PLACE_BUYLIMIT,           // Не удалось установить ордер BuyLimit. Ошибка
   MSG_LIB_SYS_ERROR_FAILED_PLACE_BUYSTOP,            // Не удалось установить ордер BuyStop. Ошибка
   MSG_LIB_SYS_ERROR_FAILED_PLACE_BUYSTOPLIMIT,       // Не удалось установить ордер BuyStopLimit. Ошибка
   MSG_LIB_SYS_ERROR_FAILED_OPEN_SELL,                // Не удалось открыть позицию Sell. Ошибка
   MSG_LIB_SYS_ERROR_FAILED_PLACE_SELLLIMIT,          // Не удалось установить ордер SellLimit. Ошибка
   MSG_LIB_SYS_ERROR_FAILED_PLACE_SELLSTOP,           // Не удалось установить ордер SellStop. Ошибка
   MSG_LIB_SYS_ERROR_FAILED_PLACE_SELLSTOPLIMIT,      // Не удалось установить ордер SellStopLimit. Ошибка
   MSG_LIB_SYS_ERROR_FAILED_SELECT_POS,               // Не удалось выбрать позицию. Ошибка
   MSG_LIB_SYS_ERROR_POSITION_ALREADY_CLOSED,         // Позиция уже закрыта
   MSG_LIB_SYS_ERROR_NOT_POSITION,                    // Ошибка. Не позиция:
   MSG_LIB_SYS_ERROR_FAILED_CLOSE_POS,                // Не удалось закрыть позицию. Ошибка 
   MSG_LIB_SYS_ERROR_FAILED_SELECT_POS_BY,            // Не удалось выбрать встречную позицию. Ошибка
   MSG_LIB_SYS_ERROR_POSITION_BY_ALREADY_CLOSED,      // Встречная позиция уже закрыта
   MSG_LIB_SYS_ERROR_NOT_POSITION_BY,                 // Ошибка. Встречная позиция не является позицией:
   MSG_LIB_SYS_ERROR_FAILED_CLOSE_POS_BY,             // Не удалось закрыть позицию встречной. Ошибка
   MSG_LIB_SYS_ERROR_FAILED_SELECT_ORD,               // Не удалось выбрать ордер. Ошибка 
   MSG_LIB_SYS_ERROR_ORDER_ALREADY_DELETED,           // Ордер уже удалён
   MSG_LIB_SYS_ERROR_NOT_ORDER,                       // Ошибка. Не ордер:
   MSG_LIB_SYS_ERROR_FAILED_DELETE_ORD,               // Не удалось удалить ордер. Ошибка
   MSG_LIB_SYS_ERROR_SELECT_CLOSED_POS_TO_MODIFY,     // Ошибка. Для модификации выбрана закрытая позиция:
   MSG_LIB_SYS_ERROR_FAILED_MODIFY_POS,               // Не удалось модифицировать позицию. Ошибка 
   MSG_LIB_SYS_ERROR_SELECT_DELETED_ORD_TO_MODIFY,    // Ошибка. Для модификации выбран удалённый ордер:
   MSG_LIB_SYS_ERROR_FAILED_MODIFY_ORD,               // Не удалось модифицировать ордер. Ошибка
   MSG_LIB_SYS_ERROR_CODE_OUT_OF_RANGE,               // Код возврата вне заданного диапазона кодов ошибок
   
   MSG_LIB_TEXT_YES,                                  // Да
   MSG_LIB_TEXT_NO,                                   // Нет
   MSG_LIB_TEXT_AND,                                  // и
   MSG_LIB_TEXT_IN,                                   // в
   MSG_LIB_TEXT_TO,                                   // к
   MSG_LIB_TEXT_OPENED,                               // Открыт
   MSG_LIB_TEXT_PLACED,                               // Установлен
   MSG_LIB_TEXT_DELETED,                              // Удалён
   MSG_LIB_TEXT_CLOSED,                               // Закрыт
   MSG_LIB_TEXT_CLOSED_BY,                            // встречным
   MSG_LIB_TEXT_CLOSED_VOL,                           // Закрыт объём
   MSG_LIB_TEXT_AT_PRICE,                             // по цене
   MSG_LIB_TEXT_ON_PRICE,                             // на цену
   MSG_LIB_TEXT_TRIGGERED,                            // Сработал
   MSG_LIB_TEXT_TURNED_TO,                            // изменён на
   MSG_LIB_TEXT_ADDED,                                // Добавлено
   MSG_LIB_TEXT_SYMBOL_ON_SERVER,                     // на сервере
   MSG_LIB_TEXT_SYMBOL_TO_LIST,                       // в список
   MSG_LIB_TEXT_FAILED_ADD_TO_LIST,                   // не удалось добавить в список
   MSG_LIB_TEXT_SUNDAY,                               // Воскресение
   MSG_LIB_TEXT_MONDAY,                               // Понедельник
   MSG_LIB_TEXT_TUESDAY,                              // Вторник
   MSG_LIB_TEXT_WEDNESDAY,                            // Среда
   MSG_LIB_TEXT_THURSDAY,                             // Четверг
   MSG_LIB_TEXT_FRIDAY,                               // Пятница
   MSG_LIB_TEXT_SATURDAY,                             // Суббота
   MSG_LIB_TEXT_SYMBOL,                               // символа: 
   MSG_LIB_TEXT_ACCOUNT,                              // аккаунта: 
   
   MSG_LIB_TEXT_PROP_VALUE,                           // Значение свойства
   MSG_LIB_TEXT_INC_BY,                               // увеличено на
   MSG_LIB_TEXT_DEC_BY,                               // уменьшено на
   MSG_LIB_TEXT_MORE_THEN,                            // стало больше
   MSG_LIB_TEXT_LESS_THEN,                            // стало меньше
   MSG_LIB_TEXT_EQUAL,                                // равно
   
   MSG_LIB_TEXT_ERROR_COUNTER_WITN_ID,                // Ошибка. Счётчик с идентификатором 
   MSG_LIB_TEXT_STEP,                                 // , шагом
   MSG_LIB_TEXT_AND_PAUSE,                            //  и паузой 
   MSG_LIB_TEXT_ALREADY_EXISTS,                       // уже существует
   
   MSG_LIB_TEXT_BASE_OBJ_UNKNOWN_EVENT,               // Неизвестное событие базового объекта
   
   MSG_LIB_TEXT_NOT_MAIL_ENABLED,                     // В терминале нет разрешения на отправку писем
   MSG_LIB_TEXT_NOT_PUSH_ENABLED,                     // В терминале нет разрешения на отправку Push-уведомлений
   MSG_LIB_TEXT_NOT_FTP_ENABLED,                      // В терминале нет разрешения на отправку файлов на FTP-адрес
   
   MSG_LIB_TEXT_ARRAY_DATA_INTEGER_NULL,              // Массив данных контролируемых integer-свойств имеет нулевой размер
   MSG_LIB_TEXT_NEED_SET_INTEGER_VALUE,               // Необходимо сначала установить размер массива равным количеству integer-свойств объекта
   MSG_LIB_TEXT_TODO_USE_INTEGER_METHOD,              // Для этого используйте метод
   MSG_LIB_TEXT_WITH_NUMBER_INTEGER_VALUE,            // со значением количества integer-свойств объекта в параметре
   
   MSG_LIB_TEXT_ARRAY_DATA_DOUBLE_NULL,               // Массив данных контролируемых double-свойств имеет нулевой размер
   MSG_LIB_TEXT_NEED_SET_DOUBLE_VALUE,                // Необходимо сначала установить размер массива равным количеству double-свойств объекта
   MSG_LIB_TEXT_TODO_USE_DOUBLE_METHOD,               // Для этого используйте метод
   MSG_LIB_TEXT_WITH_NUMBER_DOUBLE_VALUE,             // со значением количества double-свойств объекта в параметре
   
   MSG_LIB_PROP_BID,                                  // Цена Bid
   MSG_LIB_PROP_ASK,                                  // Цена Ask
   MSG_LIB_PROP_LAST,                                 // Цена последней сделки
   MSG_LIB_PROP_PRICE_SL,                             // Цена StopLoss
   MSG_LIB_PROP_PRICE_TP,                             // Цена TakeProfit
   MSG_LIB_PROP_PROFIT,                               // Профит
   MSG_LIB_PROP_SYMBOL,                               // Символ
   MSG_LIB_PROP_BALANCE,                              // Балансовая операция
   MSG_LIB_PROP_CREDIT,                               // Кредитная операция
   MSG_LIB_PROP_CLOSE_BY_SL,                          // Закрытие по StopLoss
   MSG_LIB_PROP_CLOSE_BY_TP,                          // Закрытие по TakeProfit
   MSG_LIB_PROP_ACCOUNT,                              // Счёт
   
//--- COrder
   MSG_ORD_BUY,                                       // Buy
   MSG_ORD_SELL,                                      // Sell
   MSG_ORD_TO_BUY,                                    // Ордер на покупку
   MSG_ORD_TO_SELL,                                   // Ордер на продажу
   MSG_DEAL_TO_BUY,                                   // Сделка на покупку
   MSG_DEAL_TO_SELL,                                  // Сделка на продажу
   MSG_ORD_HISTORY,                                   // Исторический ордер
   MSG_ORD_DEAL,                                      // Сделка
   MSG_ORD_POSITION,                                  // Позиция
   MSG_ORD_PENDING_ACTIVE,                            // Установленный отложенный ордер
   MSG_ORD_PENDING,                                   // Отложенный ордер
   MSG_ORD_UNKNOWN_TYPE,                              // Неизвестный тип ордера
   MSG_POS_UNKNOWN_TYPE,                              // Неизвестный тип позиции
   MSG_POS_UNKNOWN_DEAL,                              // Неизвестный тип сделки
   //---
   MSG_ORD_SL_ACTIVATED,                              // Срабатывание StopLoss
   MSG_ORD_TP_ACTIVATED,                              // Срабатывание TakeProfit
   MSG_ORD_PLACED_FROM_MQL4,                          // Выставлен из mql4-программы
   MSG_ORD_STATE_CANCELLED,                           // Ордер отменён
   MSG_ORD_STATE_CANCELLED_CLIENT,                    // Ордер снят клиентом
   MSG_ORD_STATE_STARTED,                             // Ордер проверен на корректность, но еще не принят брокером
   MSG_ORD_STATE_PLACED,                              // Ордер принят
   MSG_ORD_STATE_PARTIAL,                             // Ордер выполнен частично
   MSG_ORD_STATE_FILLED,                              // Ордер выполнен полностью
   MSG_ORD_STATE_REJECTED,                            // Ордер отклонен
   MSG_ORD_STATE_EXPIRED,                             // Ордер снят по истечении срока его действия
   MSG_ORD_STATE_REQUEST_ADD,                         // Ордер в состоянии регистрации (выставление в торговую систему)
   MSG_ORD_STATE_REQUEST_MODIFY,                      // Ордер в состоянии модификации
   MSG_ORD_STATE_REQUEST_CANCEL,                      // Ордер в состоянии удаления
   MSG_ORD_STATE_UNKNOWN,                             // Неизвестное состояние
   //---
   MSG_ORD_REASON_CLIENT,                             // Ордер выставлен из десктопного терминала
   MSG_ORD_REASON_MOBILE,                             // Ордер выставлен из мобильного приложения
   MSG_ORD_REASON_WEB,                                // Ордер выставлен из веб-платформы
   MSG_ORD_REASON_EXPERT,                             // Ордер выставлен из советника или скрипта
   MSG_ORD_REASON_SO,                                 // Ордер выставлен в результате наступления Stop Out
   MSG_ORD_REASON_DEAL_CLIENT,                        // Сделка проведена из десктопного терминала
   MSG_ORD_REASON_DEAL_MOBILE,                        // Сделка проведена из мобильного приложения
   MSG_ORD_REASON_DEAL_WEB,                           // Сделка проведена из веб-платформы
   MSG_ORD_REASON_DEAL_EXPERT,                        // Сделка проведена из советника или скрипта
   MSG_ORD_REASON_DEAL_STOPOUT,                       // Сделка проведена в результате наступления Stop Out
   MSG_ORD_REASON_DEAL_ROLLOVER,                      // Сделка проведена по причине переноса позиции
   MSG_ORD_REASON_DEAL_VMARGIN,                       // Сделка проведена по причине начисления/списания вариационной маржи
   MSG_ORD_REASON_DEAL_SPLIT,                         // Сделка проведена по причине сплита (понижения цены) инструмента
   MSG_ORD_REASON_POS_CLIENT,                         // Позиция открыта из десктопного терминала
   MSG_ORD_REASON_POS_MOBILE,                         // Позиция открыта из мобильного приложения
   MSG_ORD_REASON_POS_WEB,                            // Позиция открыта из веб-платформы
   MSG_ORD_REASON_POS_EXPERT,                         // Позиция открыта из советника или скрипта
   //---
   MSG_ORD_MAGIC,                                     // Магик
   MSG_ORD_TICKET,                                    // Тикет
   MSG_ORD_TICKET_FROM,                               // Тикет родительского ордера
   MSG_ORD_TICKET_TO,                                 // Тикет наследуемого ордера
   MSG_ORD_TIME_EXP,                                  // Дата экспирации
   MSG_ORD_TYPE,                                      // Тип
   MSG_ORD_TYPE_BY_DIRECTION,                         // Тип по направлению
   MSG_ORD_REASON,                                    // Причина
   MSG_ORD_POSITION_ID,                               // Идентификатор позиции
   MSG_ORD_DEAL_ORDER_TICKET,                         // Сделка на основании ордера с тикетом
   MSG_ORD_DEAL_ENTRY,                                // Направление сделки
   MSG_ORD_DEAL_IN,                                   // Вход в рынок
   MSG_ORD_DEAL_OUT,                                  // Выход из рынка
   MSG_ORD_DEAL_INOUT,                                // Разворот
   MSG_ORD_DEAL_OUT_BY,                               // Закрытие встречной позицией
   MSG_ORD_POSITION_BY_ID,                            // Идентификатор встречной позиции
   MSG_ORD_TIME_OPEN,                                 // Время открытия в милисекундах
   MSG_ORD_TIME_CLOSE,                                // Время закрытия в милисекундах
   MSG_ORD_TIME_UPDATE,                               // Время изменения позиции в милисекундах
   MSG_ORD_STATE,                                     // Состояние
   MSG_ORD_STATUS,                                    // Статус
   MSG_ORD_DISTANCE_PT,                               // Дистанция от цены в пунктах
   MSG_ORD_PROFIT_PT,                                 // Прибыль в пунктах
   MSG_ORD_GROUP_ID,                                  // Идентификатор группы
   MSG_ORD_PRICE_OPEN,                                // Цена открытия
   MSG_ORD_PRICE_CLOSE,                               // Цена закрытия
   MSG_ORD_PRICE_STOP_LIMIT,                          // Цена постановки Limit ордера при активации StopLimit ордера
   MSG_ORD_COMMISSION,                                // Комиссия
   MSG_ORD_SWAP,                                      // Своп
   MSG_ORD_VOLUME,                                    // Объём
   MSG_ORD_VOLUME_CURRENT,                            // Невыполненный объём
   MSG_ORD_PROFIT_FULL,                               // Прибыль+комиссия+своп
   MSG_ORD_COMMENT,                                   // Комментарий
   MSG_ORD_COMMENT_EXT,                               // Пользовательский комментарий
   MSG_ORD_EXT_ID,                                    // Идентификатор на бирже
   MSG_ORD_CLOSE_BY,                                  // Закрывающий ордер
   
//--- CEvent
   MSG_EVN_TYPE,                                      // Тип события
   MSG_EVN_TIME,                                      // Время события
   MSG_EVN_STATUS,                                    // Статус события
   MSG_EVN_REASON,                                    // Причина события
   MSG_EVN_TYPE_DEAL,                                 // Тип сделки
   MSG_EVN_TICKET_DEAL,                               // Тикет сделки
   MSG_EVN_TYPE_ORDER,                                // Тип ордера события
   MSG_EVN_TYPE_ORDER_POSITION,                       // Тип ордера позиции
   MSG_EVN_TICKET_ORDER_POSITION,                     // Тикет первого ордера позиции
   MSG_EVN_TICKET_ORDER_EVENT,                        // Тикет ордера события
   MSG_EVN_POSITION_ID,                               // Идентификатор позиции
   MSG_EVN_POSITION_BY_ID,                            // Идентификатор встречной позиции
   MSG_EVN_MAGIC_BY_ID,                               // Магический номер встречной позиции
   MSG_EVN_TIME_ORDER_POSITION,                       // Время открытия позиции
   MSG_EVN_TYPE_ORD_POS_BEFORE,                       // Тип ордера позиции до смены направления
   MSG_EVN_TICKET_ORD_POS_BEFORE,                     // Тикет ордера позиции до смены направления
   MSG_EVN_TYPE_ORD_POS_CURRENT,                      // Тип ордера текущей позиции
   MSG_EVN_TICKET_ORD_POS_CURRENT,                    // Тикет ордера текущей позиции
   MSG_EVN_PRICE_EVENT,                               // Цена на момент события
   MSG_EVN_VOLUME_ORDER_INITIAL,                      // Начальный объём ордера
   MSG_EVN_VOLUME_ORDER_EXECUTED,                     // Исполненный объём ордера
   MSG_EVN_VOLUME_ORDER_CURRENT,                      // Оставшийся объём ордера
   MSG_EVN_VOLUME_POSITION_EXECUTED,                  // Текущий объём позиции
   MSG_EVN_PRICE_OPEN_BEFORE,                         // Цена открытия до модификации
   MSG_EVN_PRICE_SL_BEFORE,                           // Цена StopLoss до модификации
   MSG_EVN_PRICE_TP_BEFORE,                           // Цена TakeProfit до модификации
   MSG_EVN_PRICE_EVENT_ASK,                           // Цена Ask в момент события
   MSG_EVN_PRICE_EVENT_BID,                           // Цена Bid в момент события
   MSG_EVN_SYMBOL_BY_POS,                             // Символ встречной позиции
   //---
   MSG_EVN_STATUS_MARKET_PENDING,                     // Установлен отложенный ордер
   MSG_EVN_STATUS_MARKET_POSITION,                    // Открыта позиция
   MSG_EVN_STATUS_HISTORY_PENDING,                    // Удален отложенный ордер
   MSG_EVN_STATUS_HISTORY_POSITION,                   // Закрыта позиция
   MSG_EVN_STATUS_UNKNOWN,                            // Неизвестный статус
   //---
   MSG_EVN_NO_EVENT,                                  // Нет торгового события
   MSG_EVN_PENDING_ORDER_PLASED,                      // Отложенный ордер установлен
   MSG_EVN_PENDING_ORDER_REMOVED,                     // Отложенный ордер удалён
   MSG_EVN_ACCOUNT_CREDIT,                            // Начисление кредита
   MSG_EVN_ACCOUNT_CREDIT_WITHDRAWAL,                 // Изъятие кредитных средств
   MSG_EVN_ACCOUNT_CHARGE,                            // Дополнительные сборы
   MSG_EVN_ACCOUNT_CORRECTION,                        // Корректирующая запись
   MSG_EVN_ACCOUNT_BONUS,                             // Перечисление бонусов
   MSG_EVN_ACCOUNT_COMISSION,                         // Дополнительные комиссии
   MSG_EVN_ACCOUNT_COMISSION_DAILY,                   // Комиссия, начисляемая в конце торгового дня
   MSG_EVN_ACCOUNT_COMISSION_MONTHLY,                 // Комиссия, начисляемая в конце месяца
   MSG_EVN_ACCOUNT_COMISSION_AGENT_DAILY,             // Агентская комиссия, начисляемая в конце торгового дня
   MSG_EVN_ACCOUNT_COMISSION_AGENT_MONTHLY,           // Агентская комиссия, начисляемая в конце месяца
   MSG_EVN_ACCOUNT_INTEREST,                          // Начисления процентов на свободные средства
   MSG_EVN_BUY_CANCELLED,                             // Отмененная сделка покупки
   MSG_EVN_SELL_CANCELLED,                            // Отмененная сделка продажи
   MSG_EVN_DIVIDENT,                                  // Начисление дивиденда
   MSG_EVN_DIVIDENT_FRANKED,                          // Начисление франкированного дивиденда
   MSG_EVN_TAX,                                       // Начисление налога
   MSG_EVN_BALANCE_REFILL,                            // Пополнение баланса
   MSG_EVN_BALANCE_WITHDRAWAL,                        // Снятие средств с баланса
   MSG_EVN_ACTIVATED_PENDING,                         // Активирован отложенный ордер
   MSG_EVN_ACTIVATED_PENDING_PARTIALLY,               // Частичное срабатывание отложенного ордера
   MSG_EVN_POSITION_OPENED_PARTIALLY,                 // Позиция открыта частично
   MSG_EVN_POSITION_CLOSED_PARTIALLY,                 // Позиция закрыта частично
   MSG_EVN_POSITION_CLOSED_BY_POS,                    // Позиция закрыта встречной
   MSG_EVN_POSITION_CLOSED_PARTIALLY_BY_POS,          // Позиция закрыта встречной частично
   MSG_EVN_POSITION_CLOSED_BY_SL,                     // Позиция закрыта по StopLoss
   MSG_EVN_POSITION_CLOSED_BY_TP,                     // Позиция закрыта по TakeProfit
   MSG_EVN_POSITION_CLOSED_PARTIALLY_BY_SL,           // Позиция закрыта частично по StopLoss
   MSG_EVN_POSITION_CLOSED_PARTIALLY_BY_TP,           // Позиция закрыта частично по TakeProfit
   MSG_EVN_POSITION_REVERSED_BY_MARKET,               // Разворот позиции по рыночному запросу
   MSG_EVN_POSITION_REVERSED_BY_PENDING,              // Разворот позиции срабатыванием отложенного ордера
   MSG_EVN_POSITION_REVERSE_PARTIALLY,                // Разворот позиции частичным исполнением заявки
   MSG_EVN_POSITION_VOLUME_ADD_BY_MARKET,             // Добавлен объём к позиции по рыночному запросу
   MSG_EVN_POSITION_VOLUME_ADD_BY_PENDING,            // Добавлен объём к позиции активацией отложенного ордера
   MSG_EVN_MODIFY_ORDER_PRICE,                        // Модифицирована цена установки ордера
   MSG_EVN_MODIFY_ORDER_PRICE_SL,                     // Модифицированы цена установки и StopLoss ордера
   MSG_EVN_MODIFY_ORDER_PRICE_TP,                     // Модифицированы цена установки и TakeProfit ордера
   MSG_EVN_MODIFY_ORDER_PRICE_SL_TP,                  // Модифицированы цена установки, StopLoss и TakeProfit ордера
   MSG_EVN_MODIFY_ORDER_SL_TP,                        // Модифицированы цены StopLoss и TakeProfit ордера
   MSG_EVN_MODIFY_ORDER_SL,                           // Модифицирован StopLoss ордера
   MSG_EVN_MODIFY_ORDER_TP,                           // Модифицирован TakeProfit ордера
   MSG_EVN_MODIFY_POSITION_SL_TP,                     // Модифицированы цены StopLoss и TakeProfit позиции
   MSG_EVN_MODIFY_POSITION_SL,                        // Модифицирован StopLoss позиции
   MSG_EVN_MODIFY_POSITION_TP,                        // Модифицирован TakeProfit позиции
   //---
   MSG_EVN_REASON_ADD,                                // Добавлен объём к позиции
   MSG_EVN_REASON_ADD_PARTIALLY,                      // Добавлен объём к позиции частичным исполнением заявки
   MSG_EVN_REASON_ADD_BY_PENDING_PARTIALLY,           // Добавлен объём к позиции частичной активацией отложенного ордера
   MSG_EVN_REASON_STOPLIMIT_TRIGGERED,                // Сработал StopLimit-ордер
   MSG_EVN_REASON_MODIFY,                             // Модификация
   MSG_EVN_REASON_CANCEL,                             // Отмена
   MSG_EVN_REASON_EXPIRED,                            // Истёк срок действия
   MSG_EVN_REASON_DONE,                               // Рыночный запрос, выполненный в полном объёме
   MSG_EVN_REASON_DONE_PARTIALLY,                     // Выполненный частично рыночный запрос
   MSG_EVN_REASON_REVERSE,                            // Разворот позиции
   MSG_EVN_REASON_REVERSE_BY_PENDING_PARTIALLY,       // Разворот позиции при при частичном срабатывании отложенного ордера
   MSG_EVN_REASON_DONE_SL_PARTIALLY,                  // Частичное закрытие по StopLoss
   MSG_EVN_REASON_DONE_TP_PARTIALLY,                  // Частичное закрытие по TakeProfit
   MSG_EVN_REASON_DONE_BY_POS,                        // Закрытие встречной позицией
   MSG_EVN_REASON_DONE_PARTIALLY_BY_POS,              // Частичное закрытие встречной позицией
   MSG_EVN_REASON_DONE_BY_POS_PARTIALLY,              // Закрытие частью объёма встречной позиции
   MSG_EVN_REASON_DONE_PARTIALLY_BY_POS_PARTIALLY,    // Частичное закрытие частью объёма встречной позиции
   
//--- CSymbol
   MSG_SYM_PROP_INDEX,                                // Индекс в окне \"Обзор рынка\"
   MSG_SYM_PROP_CUSTOM,                               // Пользовательский символ
   MSG_SYM_PROP_CHART_MODE,                           // Тип цены для построения баров
   MSG_SYM_PROP_EXIST,                                // Символ с таким именем существует
   MSG_SYM_PROP_SELECT,                               // Символ выбран в Market Watch
   MSG_SYM_PROP_VISIBLE,                              // Символ отображается в Market Watch
   MSG_SYM_PROP_SESSION_DEALS,                        // Количество сделок в текущей сессии
   MSG_SYM_PROP_SESSION_BUY_ORDERS,                   // Общее число ордеров на покупку в текущий момент
   MSG_SYM_PROP_SESSION_SELL_ORDERS,                  // Общее число ордеров на продажу в текущий момент
   MSG_SYM_PROP_VOLUME,                               // Объем в последней сделке
   MSG_SYM_PROP_VOLUMEHIGH,                           // Максимальный объём за день
   MSG_SYM_PROP_VOLUMELOW,                            // Минимальный объём за день
   MSG_SYM_PROP_TIME,                                 // Время последней котировки
   MSG_SYM_PROP_DIGITS,                               // Количество знаков после запятой
   MSG_SYM_PROP_DIGITS_LOTS,                          // Количество знаков после запятой в значении лота
   MSG_SYM_PROP_SPREAD,                               // Размер спреда в пунктах
   MSG_SYM_PROP_SPREAD_FLOAT,                         // Плавающий спред
   MSG_SYM_PROP_TICKS_BOOKDEPTH,                      // Максимальное количество показываемых заявок в стакане
   MSG_SYM_PROP_TRADE_CALC_MODE,                      // Способ вычисления стоимости контракта
   MSG_SYM_PROP_TRADE_MODE,                           // Тип исполнения ордеров
   MSG_SYM_PROP_START_TIME,                           // Дата начала торгов по инструменту
   MSG_SYM_PROP_EXPIRATION_TIME,                      // Дата окончания торгов по инструменту
   MSG_SYM_PROP_TRADE_STOPS_LEVEL,                    // Минимальный отступ от цены закрытия для установки Stop ордеров
   MSG_SYM_PROP_TRADE_FREEZE_LEVEL,                   // Дистанция заморозки торговых операций
   MSG_SYM_PROP_TRADE_EXEMODE,                        // Режим заключения сделок
   MSG_SYM_PROP_SWAP_MODE,                            // Модель расчета свопа
   MSG_SYM_PROP_SWAP_ROLLOVER3DAYS,                   // День недели для начисления тройного свопа
   MSG_SYM_PROP_MARGIN_HEDGED_USE_LEG,                // Расчет хеджированной маржи по наибольшей стороне
   MSG_SYM_PROP_EXPIRATION_MODE,                      // Флаги разрешенных режимов истечения ордера
   MSG_SYM_PROP_FILLING_MODE,                         // Флаги разрешенных режимов заливки ордера
   MSG_SYM_PROP_ORDER_MODE,                           // Флаги разрешённых типов ордеров
   MSG_SYM_PROP_ORDER_GTC_MODE,                       // Срок действия StopLoss и TakeProfit ордеров
   MSG_SYM_PROP_OPTION_MODE,                          // Тип опциона
   MSG_SYM_PROP_OPTION_RIGHT,                         // Право опциона
   MSG_SYM_PROP_BACKGROUND_COLOR,                     // Цвет фона символа в Market Watch
   //---
   MSG_SYM_PROP_BIDHIGH,                              // Максимальный Bid за день
   MSG_SYM_PROP_BIDLOW,                               // Минимальный Bid за день
   MSG_SYM_PROP_ASKHIGH,                              // Максимальный Ask за день
   MSG_SYM_PROP_ASKLOW,                               // Минимальный Ask за день
   MSG_SYM_PROP_LASTHIGH,                             // Максимальный Last за день
   MSG_SYM_PROP_LASTLOW,                              // Минимальный Last за день
   MSG_SYM_PROP_VOLUME_REAL,                          // Реальный объём за день
   MSG_SYM_PROP_VOLUMEHIGH_REAL,                      // Максимальный реальный объём за день
   MSG_SYM_PROP_VOLUMELOW_REAL,                       // Минимальный реальный объём за день
   MSG_SYM_PROP_OPTION_STRIKE,                        // Цена исполнения опциона
   MSG_SYM_PROP_POINT,                                // Значение одного пункта
   MSG_SYM_PROP_TRADE_TICK_VALUE,                     // Рассчитанная стоимость тика для позиции
   MSG_SYM_PROP_TRADE_TICK_VALUE_PROFIT,              // Рассчитанная стоимость тика для прибыльной позиции
   MSG_SYM_PROP_TRADE_TICK_VALUE_LOSS,                // Рассчитанная стоимость тика для убыточной позиции
   MSG_SYM_PROP_TRADE_TICK_SIZE,                      // Минимальное изменение цены
   MSG_SYM_PROP_TRADE_CONTRACT_SIZE,                  // Размер торгового контракта
   MSG_SYM_PROP_TRADE_ACCRUED_INTEREST,               // Накопленный купонный доход
   MSG_SYM_PROP_TRADE_FACE_VALUE,                     // Начальная стоимость облигации, установленная эмитентом
   MSG_SYM_PROP_TRADE_LIQUIDITY_RATE,                 // Коэффициент ликвидности
   MSG_SYM_PROP_VOLUME_MIN,                           // Минимальный объем для заключения сделки
   MSG_SYM_PROP_VOLUME_MAX,                           // Максимальный объем для заключения сделки
   MSG_SYM_PROP_VOLUME_STEP,                          // Минимальный шаг изменения объема для заключения сделки
   MSG_SYM_PROP_VOLUME_LIMIT,                         // Максимально допустимый общий объем позиции и отложенных ордеров в одном направлении
   MSG_SYM_PROP_SWAP_LONG,                            // Значение свопа на покупку
   MSG_SYM_PROP_SWAP_SHORT,                           // Значение свопа на продажу
   MSG_SYM_PROP_MARGIN_INITIAL,                       // Начальная (инициирующая) маржа
   MSG_SYM_PROP_MARGIN_MAINTENANCE,                   // Поддерживающая маржа по инструменту
   MSG_SYM_PROP_MARGIN_LONG_INITIAL,                  // Коэффициент взимания начальной маржи по длинным позициям
   MSG_SYM_PROP_MARGIN_SHORT_INITIAL,                 // Коэффициент взимания начальной маржи по коротким позициям
   MSG_SYM_PROP_MARGIN_LONG_MAINTENANCE,              // Коэффициент взимания поддерживающей маржи по длинным позициям
   MSG_SYM_PROP_MARGIN_SHORT_MAINTENANCE,             // Коэффициент взимания поддерживающей маржи по коротким позициям
   MSG_SYM_PROP_MARGIN_BUY_STOP_INITIAL,              // Коэффициент взимания начальной маржи по BuyStop ордерам
   MSG_SYM_PROP_MARGIN_BUY_LIMIT_INITIAL,             // Коэффициент взимания начальной маржи по BuyLimit ордерам
   MSG_SYM_PROP_MARGIN_BUY_STOPLIMIT_INITIAL,         // Коэффициент взимания начальной маржи по BuyStopLimit ордерам
   MSG_SYM_PROP_MARGIN_SELL_STOP_INITIAL,             // Коэффициент взимания начальной маржи по SellStop ордерам
   MSG_SYM_PROP_MARGIN_SELL_LIMIT_INITIAL,            // Коэффициент взимания начальной маржи по SellLimit ордерам
   MSG_SYM_PROP_MARGIN_SELL_STOPLIMIT_INITIAL,        // Коэффициент взимания начальной маржи по SellStopLimit ордерам
   MSG_SYM_PROP_MARGIN_BUY_STOP_MAINTENANCE,          // Коэффициент взимания поддерживающей маржи по BuyStop ордерам
   MSG_SYM_PROP_MARGIN_BUY_LIMIT_MAINTENANCE,         // Коэффициент взимания поддерживающей маржи по BuyLimit ордерам
   MSG_SYM_PROP_MARGIN_BUY_STOPLIMIT_MAINTENANCE,     // Коэффициент взимания поддерживающей маржи по BuyStopLimit ордерам
   MSG_SYM_PROP_MARGIN_SELL_STOP_MAINTENANCE,         // Коэффициент взимания поддерживающей маржи по SellStop ордерам
   MSG_SYM_PROP_MARGIN_SELL_LIMIT_MAINTENANCE,        // Коэффициент взимания поддерживающей маржи по SellLimit ордерам
   MSG_SYM_PROP_MARGIN_SELL_STOPLIMIT_MAINTENANCE,    // Коэффициент взимания поддерживающей маржи по SellStopLimit ордерам
   MSG_SYM_PROP_SESSION_VOLUME,                       // Cуммарный объём сделок в текущую сессию
   MSG_SYM_PROP_SESSION_TURNOVER,                     // Cуммарный оборот в текущую сессию
   MSG_SYM_PROP_SESSION_INTEREST,                     // Cуммарный объём открытых позиций
   MSG_SYM_PROP_SESSION_BUY_ORDERS_VOLUME,            // Общий объём ордеров на покупку в текущий момент
   MSG_SYM_PROP_SESSION_SELL_ORDERS_VOLUME,           // Общий объём ордеров на продажу в текущий момент
   MSG_SYM_PROP_SESSION_OPEN,                         // Цена открытия сессии
   MSG_SYM_PROP_SESSION_CLOSE,                        // Цена закрытия сессии
   MSG_SYM_PROP_SESSION_AW,                           // Средневзвешенная цена сессии
   MSG_SYM_PROP_SESSION_PRICE_SETTLEMENT,             // Цена поставки на текущую сессию
   MSG_SYM_PROP_SESSION_PRICE_LIMIT_MIN,              // Минимально допустимое значение цены на сессию
   MSG_SYM_PROP_SESSION_PRICE_LIMIT_MAX,              // Максимально допустимое значение цены на сессию
   MSG_SYM_PROP_MARGIN_HEDGED,                        // Размер контракта или маржи для одного лота перекрытых позиций
   //---
   MSG_SYM_PROP_NAME,                                 // Имя символа
   MSG_SYM_PROP_BASIS,                                // Имя базового актива для производного инструмента
   MSG_SYM_PROP_CURRENCY_BASE,                        // Базовая валюта инструмента
   MSG_SYM_PROP_CURRENCY_PROFIT,                      // Валюта прибыли
   MSG_SYM_PROP_CURRENCY_MARGIN,                      // Валюта залоговых средств
   MSG_SYM_PROP_BANK,                                 // Источник текущей котировки
   MSG_SYM_PROP_DESCRIPTION,                          // Описание символа
   MSG_SYM_PROP_FORMULA,                              // Формула для построения цены пользовательского символа
   MSG_SYM_PROP_ISIN,                                 // Имя торгового символа в системе международных идентификационных кодов
   MSG_SYM_PROP_PAGE,                                 // Адрес интернет страницы с информацией по символу
   MSG_SYM_PROP_PATH,                                 // Путь в дереве символов
   //---
   MSG_SYM_STATUS_FX,                                 // Форекс символ
   MSG_SYM_STATUS_FX_MAJOR,                           // Форекс символ-мажор
   MSG_SYM_STATUS_FX_MINOR,                           // Форекс символ-минор
   MSG_SYM_STATUS_FX_EXOTIC,                          // Форекс символ-экзотик
   MSG_SYM_STATUS_FX_RUB,                             // Форекс символ/рубль
   MSG_SYM_STATUS_METAL,                              // Металл
   MSG_SYM_STATUS_INDEX,                              // Индекс
   MSG_SYM_STATUS_INDICATIVE,                         // Индикатив
   MSG_SYM_STATUS_CRYPTO,                             // Криптовалютный символ
   MSG_SYM_STATUS_COMMODITY,                          // Товарный символ
   MSG_SYM_STATUS_EXCHANGE,                           // Биржевой символ
   MSG_SYM_STATUS_FUTURES,                            // Фьючерс
   MSG_SYM_STATUS_CFD,                                // Контракт на разницу
   MSG_SYM_STATUS__STOCKS,                            // Ценная бумага
   MSG_SYM_STATUS_BONDS,                              // Облигация
   MSG_SYM_STATUS_OPTION,                             // Опцион
   MSG_SYM_STATUS_COLLATERAL,                         // Неторгуемый актив
   MSG_SYM_STATUS_CUSTOM,                             // Пользовательский символ
   MSG_SYM_STATUS_COMMON,                             // Символ общей группы
   //---
   MSG_SYM_CHART_MODE_BID,                            // Бары строятся по ценам Bid
   MSG_SYM_CHART_MODE_LAST,                           // Бары строятся по ценам Last
   MSG_SYM_CALC_MODE_FOREX,                           // Расчет прибыли и маржи для Форекс
   MSG_SYM_CALC_MODE_FOREX_NO_LEVERAGE,               // Расчет прибыли и маржи для Форекс без учета плеча
   MSG_SYM_CALC_MODE_FUTURES,                         // Расчет залога и прибыли для фьючерсов
   MSG_SYM_CALC_MODE_CFD,                             // Расчет залога и прибыли для CFD
   MSG_SYM_CALC_MODE_CFDINDEX,                        // Расчет залога и прибыли для CFD на индексы
   MSG_SYM_CALC_MODE_CFDLEVERAGE,                     // Расчет залога и прибыли для CFD при торговле с плечом
   MSG_SYM_CALC_MODE_EXCH_STOCKS,                     // Расчет залога и прибыли для торговли ценными бумагами на бирже
   MSG_SYM_CALC_MODE_EXCH_FUTURES,                    // Расчет залога и прибыли для торговли фьючерсными контрактами на бирже
   MSG_SYM_CALC_MODE_EXCH_FUTURES_FORTS,              // Расчет залога и прибыли для торговли фьючерсными контрактами на FORTS
   MSG_SYM_CALC_MODE_EXCH_BONDS,                      // Расчет прибыли и маржи по торговым облигациям на бирже
   MSG_SYM_CALC_MODE_EXCH_STOCKS_MOEX,                // Расчет прибыли и маржи при торговле ценными бумагами на MOEX
   MSG_SYM_CALC_MODE_EXCH_BONDS_MOEX,                 // Расчет прибыли и маржи по торговым облигациям на MOEX
   MSG_SYM_CALC_MODE_SERV_COLLATERAL,                 // Используется в качестве неторгуемого актива на счете
   MSG_SYM_MODE_UNKNOWN,                              // Неизвестный режим
   //---
   MSG_SYM_TRADE_MODE_DISABLED,                       // Торговля по символу запрещена
   MSG_SYM_TRADE_MODE_LONGONLY,                       // Разрешены только покупки
   MSG_SYM_TRADE_MODE_SHORTONLY,                      // Разрешены только продажи
   MSG_SYM_TRADE_MODE_CLOSEONLY,                      // Разрешены только операции закрытия позиций
   MSG_SYM_TRADE_MODE_FULL,                           // Нет ограничений на торговые операции
   //---
   MSG_SYM_TRADE_EXECUTION_REQUEST,                   // Торговля по запросу
   MSG_SYM_TRADE_EXECUTION_INSTANT,                   // Торговля по потоковым ценам
   MSG_SYM_TRADE_EXECUTION_MARKET,                    // Исполнение ордеров по рынку
   MSG_SYM_TRADE_EXECUTION_EXCHANGE,                  // Биржевое исполнение
   //---
   MSG_SYM_SWAP_MODE_DISABLED,                        // Нет свопов
   MSG_SYM_SWAP_MODE_POINTS,                          // Свопы начисляются в пунктах
   MSG_SYM_SWAP_MODE_CURRENCY_SYMBOL,                 // Свопы начисляются в деньгах в базовой валюте символа
   MSG_SYM_SWAP_MODE_CURRENCY_MARGIN,                 // Свопы начисляются в деньгах в маржинальной валюте символа
   MSG_SYM_SWAP_MODE_CURRENCY_DEPOSIT,                // Свопы начисляются в деньгах в валюте депозита клиента
   MSG_SYM_SWAP_MODE_INTEREST_CURRENT,                // Свопы начисляются в годовых процентах от цены инструмента на момент расчета свопа
   MSG_SYM_SWAP_MODE_INTEREST_OPEN,                   // Свопы начисляются в годовых процентах от цены открытия позиции по символу
   MSG_SYM_SWAP_MODE_REOPEN_CURRENT,                  // Свопы начисляются переоткрытием позиции по цене закрытия
   MSG_SYM_SWAP_MODE_REOPEN_BID,                      // Свопы начисляются переоткрытием позиции по текущей цене Bid
   //---
   MSG_SYM_ORDERS_GTC,                                // Отложенные ордеры и уровни Stop Loss/Take Profit действительны неограниченно по времени до явной отмены
   MSG_SYM_ORDERS_DAILY,                              // При смене торгового дня отложенные ордеры и все уровни StopLoss и TakeProfit удаляются
   MSG_SYM_ORDERS_DAILY_EXCLUDING_STOPS,              // При смене торгового дня удаляются только отложенные ордеры, уровни StopLoss и TakeProfit сохраняются
   //---
   MSG_SYM_OPTION_MODE_EUROPEAN,                      // Европейский тип опциона – может быть погашен только в указанную дату
   MSG_SYM_OPTION_MODE_AMERICAN,                      // Американский тип опциона – может быть погашен в любой день до истечения срока опциона
   MSG_SYM_OPTION_MODE_UNKNOWN,                       // Неизвестный тип опциона
   MSG_SYM_OPTION_RIGHT_CALL,                         // Опцион, дающий право купить актив по фиксированной цене
   MSG_SYM_OPTION_RIGHT_PUT,                          // Опцион, дающий право продать актив по фиксированной цене
   //---
   MSG_SYM_MARKET_ORDER_ALLOWED_YES,                  // Рыночный ордер (Да)
   MSG_SYM_MARKET_ORDER_ALLOWED_NO,                   // Рыночный ордер (Нет)
   MSG_SYM_LIMIT_ORDER_ALLOWED_YES,                   // Лимит ордер (Да)
   MSG_SYM_LIMIT_ORDER_ALLOWED_NO,                    // Лимит ордер (Нет)
   MSG_SYM_STOP_ORDER_ALLOWED_YES,                    // Стоп ордер (Да)
   MSG_SYM_STOP_ORDER_ALLOWED_NO,                     // Стоп ордер (Нет)
   MSG_SYM_STOPLIMIT_ORDER_ALLOWED_YES,               // Стоп-лимит ордер (Да)
   MSG_SYM_STOPLIMIT_ORDER_ALLOWED_NO,                // Стоп-лимит ордер (Нет)
   MSG_SYM_STOPLOSS_ORDER_ALLOWED_YES,                // StopLoss (Да)
   MSG_SYM_STOPLOSS_ORDER_ALLOWED_NO,                 // StopLoss (Нет)
   MSG_SYM_TAKEPROFIT_ORDER_ALLOWED_YES,              // TakeProfit (Да)
   MSG_SYM_TAKEPROFIT_ORDER_ALLOWED_NO,               // TakeProfit (Нет)
   MSG_SYM_CLOSEBY_ORDER_ALLOWED_YES,                 // Закрытие встречным (Да)
   MSG_SYM_CLOSEBY_ORDER_ALLOWED_NO,                  // Закрытие встречным (Нет)
   MSG_SYM_FILLING_MODE_RETURN_YES,                   // Вернуть (Да)
   MSG_SYM_FILLING_MODE_FOK_YES,                      // Всё/Ничего (Да)
   MSG_SYM_FILLING_MODE_FOK_NO,                       // Всё/Ничего (Нет)
   MSG_SYM_FILLING_MODE_IOK_YES,                      // Всё/Частично (Да)
   MSG_SYM_FILLING_MODE_IOK_NO,                       // Всё/Частично (Нет)
   MSG_SYM_EXPIRATION_MODE_GTC_YES,                   // Неограниченно (Да)
   MSG_SYM_EXPIRATION_MODE_GTC_NO,                    // Неограниченно (Нет)
   MSG_SYM_EXPIRATION_MODE_DAY_YES,                   // До конца дня (Да)
   MSG_SYM_EXPIRATION_MODE_DAY_NO,                    // До конца дня (Нет)
   MSG_SYM_EXPIRATION_MODE_SPECIFIED_YES,             // Срок указывается в ордере (Да)
   MSG_SYM_EXPIRATION_MODE_SPECIFIED_NO,              // Срок указывается в ордере (Нет)
   MSG_SYM_EXPIRATION_MODE_SPECIFIED_DAY_YES,         // День указывается в ордере (Да)
   MSG_SYM_EXPIRATION_MODE_SPECIFIED_DAY_NO,          // День указывается в ордере (Нет)
   
   MSG_SYM_EVENT_SYMBOL_ADD,                          // В окно "Обзор рынка" добавлен символ
   MSG_SYM_EVENT_SYMBOL_DEL,                          // Из окна "Обзор рынка" удалён символ
   MSG_SYM_EVENT_SYMBOL_SORT,                         // Изменено расположение символов в окне "Обзор рынка"
   MSG_SYM_SYMBOLS_MODE_CURRENT,                      // Работа только с текущим символом
   MSG_SYM_SYMBOLS_MODE_DEFINES,                      // Работа с предопределённым списком символов
   MSG_SYM_SYMBOLS_MODE_MARKET_WATCH,                 // Работа с символами из окна "Обзор рынка"
   MSG_SYM_SYMBOLS_MODE_ALL,                          // Работа с полным списком всех доступных символов
   
//--- CAccount
   MSG_ACC_PROP_LOGIN,                                // Номер счёта
   MSG_ACC_PROP_TRADE_MODE,                           // Тип торгового счета
   MSG_ACC_PROP_LEVERAGE,                             // Размер предоставленного плеча
   MSG_ACC_PROP_LIMIT_ORDERS,                         // Максимально допустимое количество действующих отложенных ордеров
   MSG_ACC_PROP_MARGIN_SO_MODE,                       // Режим задания минимально допустимого уровня залоговых средств
   MSG_ACC_PROP_TRADE_ALLOWED,                        // Разрешенность торговли для текущего счета
   MSG_ACC_PROP_TRADE_EXPERT,                         // Разрешенность торговли для эксперта
   MSG_ACC_PROP_MARGIN_MODE,                          // Режим расчета маржи
   MSG_ACC_PROP_CURRENCY_DIGITS,                      // Количество знаков после запятой для валюты счета
   MSG_ACC_PROP_SERVER_TYPE,                          // Тип торгового сервера
   //---
   MSG_ACC_PROP_BALANCE,                              // Баланс счета
   MSG_ACC_PROP_CREDIT,                               // Предоставленный кредит
   MSG_ACC_PROP_PROFIT,                               // Текущая прибыль на счете
   MSG_ACC_PROP_EQUITY,                               // Собственные средства на счете
   MSG_ACC_PROP_MARGIN,                               // Зарезервированные залоговые средства на счете
   MSG_ACC_PROP_MARGIN_FREE,                          // Свободные средства на счете, доступные для открытия позиции
   MSG_ACC_PROP_MARGIN_LEVEL,                         // Уровень залоговых средств на счете в процентах
   MSG_ACC_PROP_MARGIN_SO_CALL,                       // Уровень залоговых средств для наступления Margin Call
   MSG_ACC_PROP_MARGIN_SO_SO,                         // Уровень залоговых средств для наступления Stop Out
   MSG_ACC_PROP_MARGIN_INITIAL,                       // Зарезервированные средства для обеспечения гарантийной суммы по всем отложенным ордерам
   MSG_ACC_PROP_MARGIN_MAINTENANCE,                   // Зарезервированные средства для обеспечения минимальной суммы по всем открытым позициям
   MSG_ACC_PROP_ASSETS,                               // Текущий размер активов на счёте
   MSG_ACC_PROP_LIABILITIES,                          // Текущий размер обязательств на счёте
   MSG_ACC_PROP_COMMISSION_BLOCKED,                   // Сумма заблокированных комиссий по счёту
   //---
   MSG_ACC_PROP_NAME,                                 // Имя клиента
   MSG_ACC_PROP_SERVER,                               // Имя торгового сервера
   MSG_ACC_PROP_CURRENCY,                             // Валюта депозита
   MSG_ACC_PROP_COMPANY,                              // Имя компании, обслуживающей счет
   //---
   MSG_ACC_TRADE_MODE_DEMO,                           // Демонстрационный счёт
   MSG_ACC_TRADE_MODE_CONTEST,                        // Конкурсный счёт
   MSG_ACC_TRADE_MODE_REAL,                           // Реальный счёт
   MSG_ACC_TRADE_MODE_UNKNOWN,                        // Неизвестный тип счёта
   //---
   MSG_ACC_STOPOUT_MODE_PERCENT,                      // Уровень задается в процентах
   MSG_ACC_STOPOUT_MODE_MONEY,                        // Уровень задается в деньгах
   MSG_ACC_MARGIN_MODE_RETAIL_NETTING,                // Внебиржевой рынок в режиме "Неттинг"
   MSG_ACC_MARGIN_MODE_RETAIL_HEDGING,                // Внебиржевой рынок в режиме "Хеджинг"
   MSG_ACC_MARGIN_MODE_RETAIL_EXCHANGE,               // Биржевой рынок
   
//--- CEngine
   MSG_ENG_NO_TRADE_EVENTS,                           // С момента последнего запуска ЕА торговых событий не было
   MSG_ENG_FAILED_GET_LAST_TRADE_EVENT_DESCR,         // Не удалось получить описание последнего торгового события

  };
//---

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

Теперь нам нужно создать двумерные массивы таким образом, чтобы каждое сообщение из вышенаписанного перечисления соответствовало расположению соответствующего текста в массиве (первое измерение), а во втором измерении будем располагать сами сообщения — в нулевом индексе должно находиться сообщение на языке страны пользователя (в данной редакции — на русском языке), в первом индексе — сообщение на английском языке.
Напишем массив всех сообщений библиотеки и добавим для удобства изменения количества используемых языков макроподстановку с указанием количества языков:

//---
#define TOTAL_LANG      (2)                           // Количество используемых языков
//+------------------------------------------------------------------+
//| Массив предопределённых сообщений библиотеки                     |
//| (1) на языке страны пользователя                                 |
//| (2) на международном - английском языке                          |
//| (3) любой требуемый добавочный язык сообщения.                   |
//|  По умолчанию используются два языка - русский и английский.     |
//|  Для добавления нужного количества иных языков достаточно        |
//|  указать общее количество используемых языков в TOTAL_LANG       |
//|  и дописать требуемый перевод после текста на английском языке   |
//+------------------------------------------------------------------+
string messages_library[][TOTAL_LANG]=
  {
   {"Начало списка параметров","The beginning of the event parameter list"},
   {"Конец списка параметров","End of the parameter list"},
   {"Свойство не поддерживается","Property is not support"},
   {"Свойство не поддерживается в MQL4","Property is not supported in MQL4"},
   {"Свойство не поддерживается у позиции","Property not supported for position"},
   {"Свойство не поддерживается у отложенного ордера","The property is not supported for a pending order"},
   {"Свойство не поддерживается у маркет-ордера","The property is not supported for a market-order"},
   {"Свойство не поддерживается у исторического маркет-ордера","The property is not supported for a history market-order"},
   {"Значение не задано","Value not set"},
   {"Отсутствует","Not set"},
   
   {"Ошибка ","Error "},
   {"Ошибка. Такого символа нет на сервере","Error. There is no such symbol on the server"},
   {"Не удалось поместить в обзор рынка. Ошибка: ","Failed to put in the market watch. Error: "},
   {"Не удалось получить текущие цены. Ошибка: ","Could not get current prices. Error: "},
   {"Не удалось получить коэффициенты взимания маржи. Ошибка: ","Failed to get margin rates. Error: "},
   {"Не удалось получить данные ","Failed to get data of "},
   
   {"Не удалось создать папку хранения файлов. Ошибка: ","Could not create file storage folder. Error: "},
   {"Ошибка. Не удалось добавить текущий объект-аккаунт в список-коллекцию","Error. Failed to add current account object to collection list"},
   {"Ошибка. Не удалось создать объект-аккаунт с данными текущего счёта","Error. Failed to create an account object with current account data"},
   {"Не удалось открыть для записи файл ","Could not open file for writing: "},
   {"Ошибка входных данных: нет символа ","Input error: no "},
   {"Не удалось создать объект-символ ","Failed to create symbol object "},
   {"Не удалось добавить символ ","Failed to add "},
   
   {"Не удалось получить текущие цены по символу события ","Failed to get current prices by event symbol "},
   {"Такое событие уже есть в списке","This event is already in the list"},
   
   {"Ошибка. Уже создан счётчик с идентификатором ","Error. Already created a counter with id "},
   {"Не удалось создать счётчик таймера ","Failed to create timer counter "},
   
   {"Ошибка создания временного списка","Error creating temporary list"},
   {"Ошибка. Список не является списком рыночной коллекции","Error. The list is not a list of the market collection"},
   {"Ошибка. Список не является списком исторической коллекции","Error. The list is not a list of the history collection"},
   {"Не удалось добавить ордер в список","Could not add order to the list"},
   {"Не удалось добавить сделку в список","Could not add deal to the list"},
   {"Не удалось добавить контрольный ордер ","Failed to add a control order "},
   {"Не удалось добавить контрольую позицию ","Failed to add a control position "},
   {"Не удалось добавить модифицированный ордер в список изменённых ордеров","Could not add modified order to the list of modified orders"},
   
   {"Ещё не было тиков","No ticks yet"},
   {"Не удалось создать структуру объекта","Could not create object structure"},
   {"Не удалось записать uchar-массив в файл","Could not write uchar array to file"},
   {"Не удалось загрузить uchar-массив из файла","Could not load uchar array from file"},
   {"Не удалось создать структуру объекта из uchar-массива","Could not create object structure from uchar array"},
   {"Не удалось сохранить структуру объекта в uchar-массив, ошибка ","Failed to save object structure to uchar array, error "},
   {"Ошибка. Значение \"index\" должно быть в пределах 0 - 3","Error. The \"index\" value must be between 0 - 3"},
   
   {"Ошибка. Строка предопределённых символов пустая, будет использоваться ","Error. String of predefined symbols is empty, the symbol will be used: "},
   {"Не удалось подготовить массив используемых символов. Ошибка ","Failed to create an array of used characters. Error "},
   {"Не правильный тип ордера: ","Invalid order type: "},

   {"Не удалось получить цену Ask. Ошибка ","Could not get Ask price. Error "},
   {"Не удалось получить цену Bid. Ошибка ","Could not get Bid price. Error "},
   {"Не удалось открыть позицию Buy. Ошибка ","Failed to open a Buy position. Error "},
   {"Не удалось установить ордер BuyLimit. Ошибка ","Could not place order BuyLimit. Error "},
   {"Не удалось установить ордер BuyStop. Ошибка ","Could not place order BuyStop. Error "},
   {"Не удалось установить ордер BuyStopLimit. Ошибка ","Could not place order BuyStopLimit. Error "},

   {"Не удалось открыть позицию Sell. Ошибка ","Failed to open a Sell position. Error "},
   {"Не удалось установить ордер SellLimit. Ошибка ","Could not place order SellLimit. Error "},
   {"Не удалось установить ордер SellStop. Ошибка ","Could not place order SellStop. Error "},
   {"Не удалось установить ордер SellStopLimit. Ошибка ","Could not place order SellStopLimit. Error "},

   {"Не удалось выбрать позицию. Ошибка ","Could not select position. Error "},
   {"Позиция уже закрыта","Position already closed"},
   {"Ошибка. Не позиция: ","Error. Not position: "},
   {"Не удалось закрыть позицию. Ошибка ","Could not close position. Error "},
   {"Не удалось выбрать встречную позицию. Ошибка ","Could not select the opposite position. Error "},
   {"Встречная позиция уже закрыта","Opposite position already closed"},
   {"Ошибка. Встречная позиция не является позицией: ","Error. Opposite position is not a position: "},
   {"Не удалось закрыть позицию встречной. Ошибка ","Could not close position by opposite position. Error "},
   {"Не удалось выбрать ордер. Ошибка ","Could not select order. Error "},
   {"Ордер уже удалён","Order already deleted"},
   {"Ошибка. Не ордер: ","Error. Not order: "},
   {"Не удалось удалить ордер. Ошибка ","Could not delete order. Error "},
   {"Ошибка. Для модификации выбрана закрытая позиция: ","Error. Closed position selected for modification: "},
   {"Не удалось модифицировать позицию. Ошибка ","Failed to modify position. Error "},
   {"Ошибка. Для модификации выбран удалённый ордер: ","Error. Deleted order selected for modification: "},
   {"Не удалось модифицировать ордер. Ошибка ","Failed to order modify. Error "},
   {"Код возврата вне заданного диапазона кодов ошибок","Return code out of range of error codes"},

   {"Да","Yes"},
   {"Нет","No"},
   {"и","and"},
   {"в","in"},
   {"к","to"},

   {"Открыт","Opened"},
   {"Установлен","Placed"},
   {"Удалён","Deleted"},
   {"Закрыт","Closed"},
   {"встречным","by opposite"},
   {"Закрыт объём","Closed volume"},
   {"по цене","at price"},
   {"на цену","on price"},
   {"Сработал","Triggered"},
   {"изменён на","turned to"},
   {"Добавлено","Added"},
   {" на сервере"," symbol on the server"},
   {" в список"," symbol to the list"},
   {"не удалось добавить в список","failed to add to the list"},
   
   {"Воскресение","Sunday"},
   {"Понедельник","Monday"},
   {"Вторник","Tuesday"},
   {"Среда","Wednesday"},
   {"Четверг","Thursday"},
   {"Пятница","Friday"},
   {"Суббота","Saturday"},
   {"символа: ","symbol property: "},
   {"аккаунта: ","account property: "},
   
   {"Значение свойства ","Value of the "},
   {" увеличено на "," increased by "},
   {" уменьшено на "," decreased by "},
   {" стало больше "," became more than "},
   {" стало меньше "," became less than "},
   {" равно "," is equal to "},
   
   {"Ошибка. Счётчик с идентификатором ","Error. Counter with ID "},
   {" шагом ",", step "},
   {" и паузой "," and pause "},
   {" уже существует"," already exists"},
   
   {"Неизвестное событие базового объекта ","Unknown event of base object "},
   
   {"В терминале нет разрешения на отправку e-mail","The terminal does not have permission to send e-mail"},
   {"В терминале нет разрешения на отправку Push-уведомлений","The terminal does not have permission to send a Push-notifications"},
   {"В терминале нет разрешения на отправку файлов на FTP-адрес","The terminal does not have permission to send files to an FTP address"},
   
   {"Массив данных контролируемых integer-свойств имеет нулевой размер","Controlled integer-properties data array has zero size"},
   {"Необходимо сначала установить размер массива равным количеству integer-свойств объекта","You must first set the size of the array equal to the number of object integer-properties"},
   {"Для этого используйте метод CBaseObj::SetControlDataArraySizeLong()","To do this, use the CBaseObj::SetControlDataArraySizeLong() method"},
   {"со значением количества integer-свойств объекта в параметре \"size\"","with the value of the number of integer-properties of the object in the parameter \"size\""},
   
   {"Массив данных контролируемых double-свойств имеет нулевой размер","Controlled double-properties data array has zero size"},
   {"Необходимо сначала установить размер массива равным количеству double-свойств объекта","You must first set the size of the array equal to the number of object double-properties"},
   {"Для этого используйте метод CBaseObj::SetControlDataArraySizeDouble()","To do this, use the CBaseObj::SetControlDataArraySizeDouble() method"},
   {"со значением количества double-свойств объекта в параметре \"size\"","with the value of the number of double-properties of the object in the parameter \"size\""},
   
   {"Цена Bid","Price Bid"},
   {"Цена Ask","Price Ask"},
   {"Цена Last","Price Last"},
   {"Цена StopLoss","Price StopLoss"},
   {"Цена TakeProfit","Price TakeProfit"},
   {"Прибыль","Profit"},
   {"Символ","Symbol"},
   {"Балансовая операция","Balance operation"},
   {"Кредитная операция","Credit operation"},
   {"Закрытие по StopLoss","Close by StopLoss"},
   {"Закрытие по TakeProfit","Close by TakeProfit"},
   {"Счёт","Account"},
   
//--- COrder
   {"Buy","Buy"},
   {"Sell","Sell"},
   {"Ордер на покупку","The order to Buy"},
   {"Ордер на продажу","The order to Sell"},
   
   {"Сделка на покупку","The deal to Buy"},
   {"Сделка на продажу","The deal to Sell"},
   
   {"Исторический ордер","History order"},
   {"Сделка","Deal"},
   {"Позиция","Active position"},
   {"Установленный отложенный ордер","Active pending order"},
   {"Отложенный ордер","Pending order"},
   {"Неизвестный тип ордера","Unknown order type"},
   {"Неизвестный тип позиции","Unknown position type"},
   {"Неизвестный тип сделки","Unknown deal type"},
   //---
   {"Срабатывание StopLoss","Due to StopLoss"},
   {"Срабатывание TakeProfit","Due to TakeProfit"},
   {"Выставлен из mql4-программы","Placed from mql4 program"},
   {"Ордер отменён","Order cancelled"},
   {"Ордер снят клиентом","Order withdrawn by client"},
   {"Ордер проверен на корректность, но еще не принят брокером","The order is checked for correctness, but not yet accepted by the broker"}, 
   {"Ордер принят","Order accepted"},
   {"Ордер выполнен частично","The order is filled partially"},
   {"Ордер выполнен полностью","The order is filled"},
   {"Ордер отклонен","Order rejected"},
   {"Ордер снят по истечении срока его действия","Order withdrawn upon expiration"},
   {"Ордер в состоянии регистрации (выставление в торговую систему)","Order in the state of registration (placing in the trading system)"},
   {"Ордер в состоянии модификации","The order is in a state of modification"}, 
   {"Ордер в состоянии удаления","Order is in deletion state"},
   {"Неизвестное состояние","Unknown state"},
   //---
   {"Ордер выставлен из десктопного терминала","Order is set from the desktop terminal"},
   {"Ордер выставлен из мобильного приложения","Order is set from the mobile app"},
   {"Ордер выставлен из веб-платформы","Oder is set from the web platform"},
   {"Ордер выставлен советником или скриптом","Order is set from the EA or script"},
   {"Ордер выставлен в результате наступления Stop Out","Due to Stop Out"},
   {"Сделка проведена из десктопного терминала","Deal was carried out from the desktop terminal"},
   {"Сделка проведена из мобильного приложения","Deal was carried out from the mobile app"},
   {"Сделка проведена из веб-платформы","Deal was carried out from the web platform"},
   {"Сделка проведена из советника или скрипта","Deal was carried out from the EA or script"},
   {"Сделка проведена в результате наступления Stop Out","Due to Stop Out"},
   {"Сделка проведена по причине переноса позиции","Due to position rollover"},
   {"Сделка проведена по причине начисления/списания вариационной маржи","Due to variation margin"},
   {"Сделка проведена по причине сплита (понижения цены) инструмента","Due to the split"},
   {"Позиция открыта из десктопного терминала","Position is open from the desktop terminal"},
   {"Позиция открыта из мобильного приложения","Position is open from the mobile app"},
   {"Позиция открыта из веб-платформы","Position is open from the web platform"},
   {"Позиция открыта из советника или скрипта","The position is open from the EA or script"},
   //---
   {"Магический номер","Magic number"},
   {"Тикет","Ticket"},
   {"Тикет родительского ордера","Ticket of parent order"},
   {"Тикет наследуемого ордера","Inherited order ticket"},
   {"Дата экспирации","Date of expiration"},
   {"Тип","Type"},
   {"Тип по направлению","Type by direction"},
   {"Причина","Reason"},
   {"Идентификатор позиции","Position identifier"},
   {"Сделка на основании ордера с тикетом","Deal by order ticket"},
   {"Направление сделки","Deal entry"},
   {"Вход в рынок","Entry to the market"},
   {"Выход из рынка","Out from the market"},
   {"Разворот","Turning in the opposite direction"},
   {"Закрытие встречной позицией","Closing by opposite position"},
   {"Идентификатор встречной позиции","Opposite position identifier"},
   {"Время открытия в милисекундах","Opening time in milliseconds"},
   {"Время закрытия в милисекундах","Closing time in milliseconds"},
   {"Время изменения позиции в милисекундах","Time to change the position in milliseconds"},
   {"Состояние","Statе"},
   {"Статус","Status"},
   {"Дистанция от цены в пунктах","Distance from price in points"},
   {"Прибыль в пунктах","Profit in points"},
   {"Идентификатор группы","Group's identifier"},
   {"Цена открытия","Price open"},
   {"Цена закрытия","Price close"},
   {"Цена постановки Limit ордера при активации StopLimit ордера","The price of placing Limit order when StopLimit order are activated"},
   {"Комиссия","Comission"},
   {"Своп","Swap"},
   {"Объём","Volume"},
   {"Невыполненный объём","Unfulfilled volume"},
   {"Прибыль+комиссия+своп","Profit+Comission+Swap"},
   {"Комментарий","Comment"},
   {"Пользовательский комментарий","Custom comment"},
   {"Идентификатор на бирже","Exchange identifier"},
   {"Закрывающий ордер","Order for closing by"},
   
//--- CEvent
   {"Тип события","Event's type"},
   {"Время события","Time of event"},
   {"Статус события","Status of event"},
   {"Причина события","Reason of event"},
   {"Тип сделки","Deal's type"},
   {"Тикет сделки","Deal's ticket"},
   {"Тип ордера события","Event's order type"},
   {"Тип ордера позиции","Position's order type"},
   {"Тикет первого ордера позиции","Position's first order ticket"},
   {"Тикет ордера события","Event's order ticket"},
   {"Идентификатор позиции","Position ID"},
   {"Идентификатор встречной позиции","Opposite position's ID"},
   {"Магический номер встречной позиции","Magic number of opposite position"},
   {"Время открытия позиции","Position's opened time"},
   {"Тип ордера позиции до смены направления","Type order of position before changing direction"},
   {"Тикет ордера позиции до смены направления","Ticket order of position before changing direction"},
   {"Тип ордера текущей позиции","Type order of current position"},
   {"Тикет ордера текущей позиции","Ticket order of current position"},
   {"Цена на момент события","Price at the time of the event"},
   {"Начальный объём ордера","Order initial volume"},
   {"Исполненный объём ордера","Order executed volume"},
   {"Оставшийся объём ордера","Order remaining volume"},
   {"Текущий объём позиции","Position current volume"},
   {"Цена открытия до модификации","Price open before modification"},
   {"Цена StopLoss до модификации","Price StopLoss before modification"},
   {"Цена TakeProfit до модификации","Price TakeProfit before modification"},
   {"Цена Ask в момент события","Price Ask at the time of the event"},
   {"Цена Bid в момент события","Price Bid at the time of the event"},
   {"Символ встречной позиции","Symbol of opposite position"},
   //---
   {"Установлен отложенный ордер","Pending order placed"},
   {"Открыта позиция","Position is open"},
   {"Удален отложенный ордер","Pending order removed"},
   {"Закрыта позиция","Position closed"},
   {"Неизвестный статус","Unknown status"},
   //---
   {"Нет торгового события","No trade event"},
   {"Отложенный ордер установлен","Pending order placed"},
   {"Отложенный ордер удалён","Pending order removed"},
   {"Начисление кредита","Credit"},
   {"Изъятие кредитных средств","Withdrawal of credit"},
   {"Дополнительные сборы","Additional charge"},
   {"Корректирующая запись","Correction"},
   {"Перечисление бонусов","Bonus"},
   {"Дополнительные комиссии","Additional commission"},
   {"Комиссия, начисляемая в конце торгового дня","Daily commission"},
   {"Комиссия, начисляемая в конце месяца","Monthly commission"},
   {"Агентская комиссия, начисляемая в конце торгового дня","Daily agent commission"},
   {"Агентская комиссия, начисляемая в конце месяца","Monthly agent commission"},
   {"Начисления процентов на свободные средства","Interest rate"},
   {"Отмененная сделка покупки","Canceled buy deal"},
   {"Отмененная сделка продажи","Canceled sell deal"},
   {"Начисление дивиденда","Dividend operations"},
   {"Начисление франкированного дивиденда","Franked (non-taxable) dividend operations"},
   {"Начисление налога","Tax charges"},
   {"Пополнение баланса","Balance refill"},
   {"Снятие средств с баланса","Withdrawals from the balance"},
   //---
   {"Активирован отложенный ордер","Pending order activated"},
   {"Частичное срабатывание отложенного ордера","Pending order partially triggered"},
   {"Позиция открыта частично","Position is open partially"},
   {"Позиция закрыта частично","Position closed partially"},
   {"Позиция закрыта встречной","Position closed by opposite position"},
   {"Позиция закрыта встречной частично","Position closed partially by opposite position"},
   {"Позиция закрыта по StopLoss","Position closed by StopLoss"},
   {"Позиция закрыта по TakeProfit","Position closed by TakeProfit"},
   {"Позиция закрыта частично по StopLoss","Position closed partially by StopLoss"},
   {"Позиция закрыта частично по TakeProfit","Position closed partially by TakeProfit"},
   {"Разворот позиции по рыночному запросу","Position reversal by market request"},
   {"Разворот позиции срабатыванием отложенного ордера","Position reversal by triggered a pending order"},
   {"Разворот позиции частичным исполнением заявки","Position reversal by partially completed of the request"},
   {"Добавлен объём к позиции по рыночному запросу","Added volume to position by market request"},
   {"Добавлен объём к позиции активацией отложенного ордера","Added volume to the position by activation of a pending order"},
   {"Модифицирована цена установки ордера","Modified order price"},
   {"Модифицированы цена установки и StopLoss ордера","Modified of order price and StopLoss"},
   {"Модифицированы цена установки и TakeProfit ордера","Modified of order price and TakeProfit"},
   {"Модифицированы цена установки, StopLoss и TakeProfit ордера","Modified of order price, StopLoss and TakeProfit"},
   {"Модифицированы цены StopLoss и TakeProfit ордера","Modified of order StopLoss and TakeProfit"},
   {"Модифицирован StopLoss ордера","Modified order StopLoss"},
   {"Модифицирован TakeProfit ордера","Modified order TakeProfit"},
   {"Модифицированы цены StopLoss и TakeProfit позиции","Modified of position StopLoss and TakeProfit"},
   {"Модифицирован StopLoss позиции","Modified position StopLoss"},
   {"Модифицирован TakeProfit позиции","Modified position TakeProfit"},
   //---
   {"Добавлен объём к позиции","Added volume to position"},
   {"Добавлен объём к позиции частичным исполнением заявки","Volume added to the position by partially completed request"},
   {"Добавлен объём к позиции частичной активацией отложенного ордера","Added volume to position by pending order's triggered partially"},
   {"Сработал StopLimit-ордер","StopLimit order triggered"},
   {"Модификация","Modified"},
   {"Отмена","Canceled"},
   {"Истёк срок действия","Expired"},
   {"Рыночный запрос, выполненный в полном объёме","Fully completed market request"},
   {"Выполненный частично рыночный запрос","Partially completed market request"},
   {"Разворот позиции","Position reversal"},
   {"Разворот позиции при при частичном срабатывании отложенного ордера","Position reversal on a partially triggered pending order"},
   {"Частичное закрытие по StopLoss","Partially close by StopLoss triggered"},
   {"Частичное закрытие по TakeProfit","Partially close by TakeProfit triggered"},
   {"Закрытие встречной позицией","Closed by opposite position"},
   {"Частичное закрытие встречной позицией","Closed partially by opposite position"},
   {"Закрытие частью объёма встречной позиции","Closed by incomplete volume of opposite position"},
   {"Частичное закрытие частью объёма встречной позиции","Closed partially by incomplete volume of opposite position"},

//--- CSymbol
   {"Индекс в окне \"Обзор рынка\"","Index in the \"Market Watch window\""},
   {"Пользовательский символ","Custom symbol"},
   {"Тип цены для построения баров","Price type used for generating symbols bars"},
   {"Символ с таким именем существует","Symbol with this name exists"},
   {"Символ выбран в Market Watch","Symbol is selected in Market Watch"},
   {"Символ отображается в Market Watch","Symbol is visible in Market Watch"},
   {"Количество сделок в текущей сессии","Number of deals in the current session"},
   {"Общее число ордеров на покупку в текущий момент","Number of Buy orders at the moment"},
   {"Общее число ордеров на продажу в текущий момент","Number of Sell orders at the moment"},
   {"Объем в последней сделке","Volume of the last deal"},
   {"Максимальный объём за день","Maximal day volume"},
   {"Минимальный объём за день","Minimal day volume"},
   {"Время последней котировки","Time of the last quote"},
   {"Количество знаков после запятой","Digits after a decimal point"},
   {"Количество знаков после запятой в значении лота","Digits after a decimal point in the value of the lot"},
   {"Размер спреда в пунктах","Spread value in points"},
   {"Плавающий спред","Spread is floating"},
   {"Максимальное количество показываемых заявок в стакане","Maximal number of requests shown in Depth of Market"},
   {"Способ вычисления стоимости контракта","Contract price calculation mode"},
   {"Тип исполнения ордеров","Order execution type"},
   {"Дата начала торгов по инструменту","Date of the symbol trade beginning"},
   {"Дата окончания торгов по инструменту","Date of the symbol trade end"},
   {"Минимальный отступ от цены закрытия для установки Stop ордеров","Minimal indention from the close price to place Stop orders"},
   {"Дистанция заморозки торговых операций","Distance to freeze trade operations in points"},
   {"Режим заключения сделок","Deal execution mode"},
   {"Модель расчета свопа","Swap calculation model"},
   {"День недели для начисления тройного свопа","Day of week to charge 3 days swap rollover"},
   {"Расчет хеджированной маржи по наибольшей стороне","Calculating hedging margin using the larger leg"},
   {"Флаги разрешенных режимов истечения ордера","Flags of allowed order expiration modes"},
   {"Флаги разрешенных режимов заливки ордера","Flags of allowed order filling modes"},
   {"Флаги разрешённых типов ордеров","Flags of allowed order types"},
   {"Срок действия StopLoss и TakeProfit ордеров","Expiration of Stop Loss and Take Profit orders"},
   {"Тип опциона","Option type"},
   {"Право опциона","Option right"},
   {"Цвет фона символа в Market Watch","Background color of the symbol in Market Watch"},
   {"Максимальный Bid за день","Maximal Bid of the day"},
   {"Минимальный Bid за день","Minimal Bid of the day"},
   {"Максимальный Ask за день","Maximal Ask of the day"},
   {"Минимальный Ask за день","Minimal Ask of the day"},
   {"Максимальный Last за день","Maximal Last of the day"},
   {"Минимальный Last за день","Minimal Last of the day"},
   {"Реальный объём за день","Real volume of the last deal"},
   {"Максимальный реальный объём за день","Maximal real volume of the day"},
   {"Минимальный реальный объём за день","Minimal real volume of the day"},
   {"Цена исполнения опциона","The strike price of an option"},
   {"Значение одного пункта","Symbol point value"},
   {"Рассчитанная стоимость тика для позиции","Calculated tick price for a position"},
   {"Рассчитанная стоимость тика для прибыльной позиции","Calculated tick price for a profitable position"},
   {"Рассчитанная стоимость тика для убыточной позиции","Calculated tick price for a losing position"},
   {"Минимальное изменение цены","Minimal price change"},
   {"Размер торгового контракта","Trade contract size"},
   {"Накопленный купонный доход","Accumulated coupon interest"},
   {"Начальная стоимость облигации, установленная эмитентом","Initial bond value set by the issuer"},
   {"Коэффициент ликвидности","Liquidity Rate"},
   {"Минимальный объем для заключения сделки","Minimal volume for a deal"},
   {"Максимальный объем для заключения сделки","Maximal volume for a deal"},
   {"Минимальный шаг изменения объема для заключения сделки","Minimal volume change step for deal execution"},
   {
    "Максимально допустимый общий объем позиции и отложенных ордеров в одном направлении",
    "Maximum allowed aggregate volume of an open position and pending orders in one direction"
   },
   {"Значение свопа на покупку","Long swap value"},
   {"Значение свопа на продажу","Short swap value"},
   {"Начальная (инициирующая) маржа","Initial margin"},
   {"Поддерживающая маржа по инструменту","Maintenance margin"},
   {"Коэффициент взимания начальной маржи по длинным позициям","Coefficient of margin initial charging for long positions"},
   {"Коэффициент взимания начальной маржи по коротким позициям","Coefficient of margin initial charging for short positions"},
   {"Коэффициент взимания поддерживающей маржи по длинным позициям","Coefficient of margin maintenance charging for long positions"},
   {"Коэффициент взимания поддерживающей маржи по коротким позициям","Coefficient of margin maintenance charging for short positions"},
   {"Коэффициент взимания начальной маржи по BuyStop ордерам","Coefficient of margin initial charging for BuyStop orders"},
   {"Коэффициент взимания начальной маржи по BuyLimit ордерам","Coefficient of margin initial charging for BuyLimit orders"},
   {"Коэффициент взимания начальной маржи по BuyStopLimit ордерам","Coefficient of margin initial charging for BuyStopLimit orders"},
   {"Коэффициент взимания начальной маржи по SellStop ордерам","Coefficient of margin initial charging for SellStop orders"},
   {"Коэффициент взимания начальной маржи по SellLimit ордерам","Coefficient of margin initial charging for SellLimit orders"},
   {"Коэффициент взимания начальной маржи по SellStopLimit ордерам","Coefficient of margin initial charging for SellStopLimit orders"},
   {"Коэффициент взимания поддерживающей маржи по BuyStop ордерам","Coefficient of margin maintenance charging for BuyStop orders"},
   {"Коэффициент взимания поддерживающей маржи по BuyLimit ордерам","Coefficient of margin maintenance charging for BuyLimit orders"},
   {"Коэффициент взимания поддерживающей маржи по BuyStopLimit ордерам","Coefficient of margin maintenance charging for BuyStopLimit orders"},
   {"Коэффициент взимания поддерживающей маржи по SellStop ордерам","Coefficient of margin maintenance charging for SellStop orders"},
   {"Коэффициент взимания поддерживающей маржи по SellLimit ордерам","Coefficient of margin maintenance charging for SellLimit orders"},
   {"Коэффициент взимания поддерживающей маржи по SellStopLimit ордерам","Coefficient of margin maintenance charging for SellStopLimit orders"},
   {"Cуммарный объём сделок в текущую сессию","Summary volume of current session deals"},
   {"Cуммарный оборот в текущую сессию","Summary turnover of the current session"},
   {"Cуммарный объём открытых позиций","Summary open interest"},
   {"Общий объём ордеров на покупку в текущий момент","Current volume of Buy orders"},
   {"Общий объём ордеров на продажу в текущий момент","Current volume of Sell orders"},
   {"Цена открытия сессии","Open price of the current session"},
   {"Цена закрытия сессии","Close price of the current session"},
   {"Средневзвешенная цена сессии","Average weighted price of the current session"},
   {"Цена поставки на текущую сессию","Settlement price of the current session"},
   {"Минимально допустимое значение цены на сессию","Minimal price of the current session"},
   {"Максимально допустимое значение цены на сессию","Maximal price of the current session"},
   {"Размер контракта или маржи для одного лота перекрытых позиций","Contract size or margin value per one lot of hedged positions"},
   {"Имя символа","Symbol name"},
   {"Имя базового актива для производного инструмента","The underlying asset of a derivative"},
   {"Базовая валюта инструмента","Basic currency of a symbol"},
   {"Валюта прибыли","Profit currency"},
   {"Валюта залоговых средств","Margin currency"},
   {"Источник текущей котировки","Feeder of the current quote"},
   {"Описание символа","Symbol description"},
   {"Формула для построения цены пользовательского символа","The formula used for custom symbol pricing"},
   {"Имя торгового символа в системе международных идентификационных кодов","The name of a symbol in the ISIN system"},
   {"Адрес интернет страницы с информацией по символу","The address of the web page containing symbol information"},
   {"Путь в дереве символов","Path in the symbol tree"},
   //---
   {"Форекс символ","Forex symbol"},
   {"Форекс символ-мажор","Forex major symbol"},
   {"Форекс символ-минор","Forex minor symbol"},
   {"Форекс символ-экзотик","Forex Exotic Symbol"},
   {"Форекс символ/рубль","Forex symbol RUB"},
   {"Металл","Metal"},
   {"Индекс","Index"},
   {"Индикатив","Indicative"},
   {"Криптовалютный символ","Crypto symbol"},
   {"Товарный символ","Commodity symbol"},
   {"Биржевой символ","Exchange symbol"},
   {"Фьючерс","Furures"},
   {"Контракт на разницу","Contract For Difference"},
   {"Ценная бумага","Stocks"},
   {"Облигация","Bonds"},
   {"Опцион","Option"},
   {"Неторгуемый актив","Collateral"},
   {"Пользовательский символ","Custom symbol"},
   {"Символ общей группы","Common group symbol"},
   //---
   {"Бары строятся по ценам Bid","Bars are based on Bid prices"},
   {"Бары строятся по ценам Last","Bars are based on Last prices"},
   {"Расчет прибыли и маржи для Форекс","Forex mode"},
   {"Расчет прибыли и маржи для Форекс без учета плеча","Forex No Leverage mode"},
   {"Расчет залога и прибыли для фьючерсов","Futures mode"},
   {"Расчет залога и прибыли для CFD","CFD mode"},
   {"Расчет залога и прибыли для CFD на индексы","CFD index mode"},
   {"Расчет залога и прибыли для CFD при торговле с плечом","CFD Leverage mode"},
   {"Расчет залога и прибыли для торговли ценными бумагами на бирже","Exchange mode"},
   {"Расчет залога и прибыли для торговли фьючерсными контрактами на бирже","Futures mode"},
   {"Расчет залога и прибыли для торговли фьючерсными контрактами на FORTS","FORTS Futures mode"},
   {"Расчет прибыли и маржи по торговым облигациям на бирже","Exchange Bonds mode"},
   {"Расчет прибыли и маржи при торговле ценными бумагами на MOEX","Exchange MOEX Stocks mode"},
   {"Расчет прибыли и маржи по торговым облигациям на MOEX","Exchange MOEX Bonds mode"},
   {"Используется в качестве неторгуемого актива на счете","Collateral mode"},
   {"Неизвестный режим","Unknown mode"},
   {"Торговля по символу запрещена","Trade is disabled for the symbol"},
   {"Разрешены только покупки","Allowed only long positions"},
   {"Разрешены только продажи","Allowed only short positions"},
   {"Разрешены только операции закрытия позиций","Allowed only position close operations"},
   {"Нет ограничений на торговые операции","No trade restrictions"},
   //---
   {"Торговля по запросу","Execution by request"},
   {"Торговля по потоковым ценам","Instant execution"},
   {"Исполнение ордеров по рынку","Market execution"},
   {"Биржевое исполнение","Exchange execution"},
   //---
   {"Нет свопов","Swaps disabled (no swaps)"},
   {"Свопы начисляются в пунктах","Swaps are charged in points"},
   {"Свопы начисляются в деньгах в базовой валюте символа","Swaps are charged in money in base currency of the symbol"},
   {"Свопы начисляются в деньгах в маржинальной валюте символа","Swaps are charged in money in margin currency of the symbol"},
   {"Свопы начисляются в деньгах в валюте депозита клиента","Swaps are charged in money, in client deposit currency"},
   {
    "Свопы начисляются в годовых процентах от цены инструмента на момент расчета свопа",
    "Swaps are charged as the specified annual interest from the instrument price at calculation of swap"
   },
   {"Свопы начисляются в годовых процентах от цены открытия позиции по символу","Swaps are charged as the specified annual interest from the open price of position"},
   {"Свопы начисляются переоткрытием позиции по цене закрытия","Swaps are charged by reopening positions by the close price"},
   {"Свопы начисляются переоткрытием позиции по текущей цене Bid","Swaps are charged by reopening positions by the current Bid price"},
   //---
   {
    "Отложенные ордеры и уровни Stop Loss/Take Profit действительны неограниченно по времени до явной отмены",
    "Pending orders and Stop Loss/Take Profit levels are valid for an unlimited period until their explicit cancellation"
   },
   {
    "При смене торгового дня отложенные ордеры и все уровни StopLoss и TakeProfit удаляются",
    "At the end of the day, all Stop Loss and Take Profit levels, as well as pending orders are deleted"
   },
   {
    "При смене торгового дня удаляются только отложенные ордеры, уровни StopLoss и TakeProfit сохраняются",
    "At the end of the day, only pending orders are deleted, while Stop Loss and Take Profit levels are preserved"
   },
   //---
   {"Европейский тип опциона – может быть погашен только в указанную дату","European option may only be exercised on a specified date"},
   {"Американский тип опциона – может быть погашен в любой день до истечения срока опциона","American option may be exercised on any trading day or before expiry"},
   {"Неизвестный тип опциона","Unknown option type"},
   {"Опцион, дающий право купить актив по фиксированной цене","A call option gives you the right to buy an asset at a specified price"},
   {"Опцион, дающий право продать актив по фиксированной цене","A call option gives you the right to sell an asset at a specified price"},
   //---
   {"Рыночный ордер (Да)","Market order (Yes)"},
   {"Рыночный ордер (Нет)","Market order (No)"},
   {"Лимит ордер (Да)","Limit order (Yes)"},
   {"Лимит ордер (Нет)","Limit order (No)"},
   {"Стоп ордер (Да)","Stop order (Yes)"},
   {"Стоп ордер (Нет)","Stop order (No)"},
   {"Стоп-лимит ордер (Да)","StopLimit order (Yes)"},
   {"Стоп-лимит ордер (Нет)","StopLimit order (No)"},
   {"StopLoss (Да)","StopLoss (Yes)"},
   {"StopLoss (Нет)","StopLoss (No)"},
   {"TakeProfit (Да)","TakeProfit (Yes)"},
   {"TakeProfit (Нет)","TakeProfit (No)"},
   {"Закрытие встречным (Да)","CloseBy order (Yes)"},
   {"Закрытие встречным (Нет)","CloseBy order (No)"},
   {"Вернуть (Да)","Return (Yes)"},
   {"Всё/Ничего (Да)","Fill or Kill (Yes)"},
   {"Всё/Ничего (Нет)","Fill or Kill (No)"},
   {"Всё/Частично (Да)","Immediate or Cancel order (Yes)"},
   {"Всё/Частично (Нет)","Immediate or Cancel order (No)"},
   {"Неограниченно (Да)","Unlimitedr (Yes)"},
   {"Неограниченно (Нет)","Unlimited (No)"},
   {"До конца дня (Да)","Valid till the end of the day (Yes)"},
   {"До конца дня (Нет)","Valid till the end of the day (No)"},
   {"Срок указывается в ордере (Да)","Time is specified in the order (Yes)"},
   {"Срок указывается в ордере (Нет)","Time is specified in the order (No)"},
   {"День указывается в ордере (Да)","Date is specified in the order (Yes)"},
   {"День указывается в ордере (Нет)","Date is specified in the order (No)"},
   
   {"В окно \"Обзор рынка\" добавлен символ","Added a symbol to the \"Market Watch\" window"},
   {"Из окна \"Обзор рынка\" удалён символ","From the \"Market Watch\" window was removed"},
   {"Изменено расположение символов в окне \"Обзор рынка\"","Changed the arrangement of symbols in the \"Market Watch\" window"},
   {"Работа только с текущим символом","Work only with the current symbol"},
   {"Работа с предопределённым списком символов","Work with a predefined list of symbols"},
   {"Работа с символами из окна \"Обзор рынка\"","Working with symbols from the \"Market Watch\" window"},
   {"Работа с полным списком всех доступных символов","Work with the full list of all available symbols"},
   
   
//--- CAccount
   {"Номер счёта","Account number"},
   {"Тип торгового счета","Account trade mode"},
   {"Размер предоставленного плеча","Account leverage"},
   {"Максимально допустимое количество действующих отложенных ордеров","Maximum allowed number of active pending orders"},
   {"Режим задания минимально допустимого уровня залоговых средств","Mode for setting the minimal allowed margin"},
   {"Разрешенность торговли для текущего счета","Allowed trade for the current account"},
   {"Разрешенность торговли для эксперта","Allowed trade for an Expert Advisor"},
   {"Режим расчета маржи","Margin calculation mode"},
   {"Количество знаков после запятой для валюты счета","The number of decimal places in the account currency"},
   {"Тип торгового сервера","Type of trading server"},
   //---
   {"Баланс счета","Account balance"},
   {"Предоставленный кредит","Account credit"},
   {"Текущая прибыль на счете","Current profit of an account"},
   {"Собственные средства на счете","Account equity"},
   {"Зарезервированные залоговые средства на счете","Account margin used in the deposit currency"},
   {"Свободные средства на счете, доступные для открытия позиции","Free margin of an account"},
   {"Уровень залоговых средств на счете в процентах","Account margin level in percents"},
   {"Уровень залоговых средств для наступления Margin Call","Margin call level"},
   {"Уровень залоговых средств для наступления Stop Out","Margin stop out level"},
   {
    "Зарезервированные средства для обеспечения гарантийной суммы по всем отложенным ордерам",
    "Amount reserved on an account to cover the margin of all pending orders"
   },
   {
    "Зарезервированные средства для обеспечения минимальной суммы по всем открытым позициям",
    "Min equity reserved on an account to cover the min amount of all open positions"
   },
   {"Текущий размер активов на счёте","The current assets of an account"},
   {"Текущий размер обязательств на счёте","The current liabilities on an account"},
   {"Сумма заблокированных комиссий по счёту","The current blocked commission amount on an account"},
   //---
   {"Имя клиента","Client name"},
   {"Имя торгового сервера","Trade server name"},
   {"Валюта депозита","Account currency"},
   {"Имя компании, обслуживающей счет","Name of a company that serves the account"},
   //---
   {"Демонстрационный счёт","Demo account"},
   {"Конкурсный счёт","Contest account"},
   {"Реальный счёт","Real account"},
   {"Неизвестный тип счёта","Unknown account type"},
   //---
   {"Уровень задается в процентах","Account StopOut mode in percents"},
   {"Уровень задается в деньгах","Account StopOut mode in money"},
   {"Внебиржевой рынок в режиме \"Неттинг\"","Netting mode"},
   {"Внебиржевой рынок в режиме \"Хеджинг\"","Hedging mode"},
   {"Биржевой рынок","Exchange market mode"},
   
//--- CEngine
   {"С момента последнего запуска ЕА торговых событий не было","There have been no trade events since the last launch of EA"},
   {"Не удалось получить описание последнего торгового события","Failed to get the description of the last trading event"},

  };
//+---------------------------------------------------------------------+

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

Важно — все сообщения, располагаемые в массивах, должны точно соответствовать их константам, расположенным в перечислении, либо точно соответствовать коду сообщения об ошибке, возвращаемого из функции GetLastError().

Для того чтобы добавить перевод текста на ещё один язык, достаточно просто к каждому сообщению (после сообщения на английском языке) добавить нужный перевод на нужный язык. Но если мы хотим заменить один из двух предопределённых языков на иной, то достаточно просто исправить уже имеющиеся сообщения — например, перевести русские сообщения на другой язык кроме английского (английский язык, по уже устоявшимся правилам, в программе быть обязан как язык международного общения).

Например (для выделенного участка кода выше), чтобы добавить перевод текста "Неизвестный тип счёта" на немецкий язык, необходимо дописать перевод данного сообщения на немецкий язык после сообщения на английском языке:

{"Неизвестный тип счёта","Unknown account type","Unbekannter Kontotyp"},

Естественно, что если мы добавляем ещё один язык к сообщениям, то необходимо его добавить к абсолютно всем имеющимся сообщениям во всех массивах текстов сообщений— иначе индексы сообщений будут сбиты, что приведёт к непредсказуемым результатам при попытке вывода сообщений.

Теперь напишем массив сообщений кодов возвратов торгового сервера:

//+---------------------------------------------------------------------+
//| Массив сообщений кодов возвратов торгового сервера (10004 - 10044)  |
//| (1) на языке страны пользователя                                    |
//| (2) на международном языке                                          |
//+---------------------------------------------------------------------+
string messages_ts_ret_code[][TOTAL_LANG]=
  {
   {"Реквота","Requote"},                                                                                                                          // 10004
   {"Неизвестный код возврата торгового сервера","Unknown trading server return code"},                                                   // 10005
   {"Запрос отклонен","Request rejected"},                                                                                                         // 10006
   {"Запрос отменен трейдером","Request canceled by trader"},                                                                                      // 10007
   {"Ордер размещен","Order placed"},                                                                                                              // 10008
   {"Заявка выполнена","Request completed"},                                                                                                       // 10009
   {"Заявка выполнена частично","Only part of the request was completed"},                                                                         // 10010
   {"Ошибка обработки запроса","Request processing error"},                                                                                        // 10011
   {"Запрос отменен по истечению времени","Request canceled by timeout"},                                                                          // 10012
   {"Неправильный запрос","Invalid request"},                                                                                                      // 10013
   {"Неправильный объем в запросе","Invalid volume in the request"},                                                                               // 10014
   {"Неправильная цена в запросе","Invalid price in the request"},                                                                                 // 10015
   {"Неправильные стопы в запросе","Invalid stops in the request"},                                                                                // 10016
   {"Торговля запрещена","Trade is disabled"},                                                                                                     // 10017
   {"Рынок закрыт","Market is closed"},                                                                                                            // 10018
   {"Нет достаточных денежных средств для выполнения запроса","There is not enough money to complete the request"},                                // 10019
   {"Цены изменились","Prices changed"},                                                                                                           // 10020
   {"Отсутствуют котировки для обработки запроса","There are no quotes to process the request"},                                                   // 10021
   {"Неверная дата истечения ордера в запросе","Invalid order expiration date in the request"},                                                    // 10022
   {"Состояние ордера изменилось","Order state changed"},                                                                                          // 10023
   {"Слишком частые запросы","Too frequent requests"},                                                                                             // 10024
   {"В запросе нет изменений","No changes in request"},                                                                                            // 10025
   {"Автотрейдинг запрещен сервером","Autotrading disabled by server"},                                                                            // 10026
   {"Автотрейдинг запрещен клиентским терминалом","Autotrading disabled by client terminal"},                                                      // 10027
   {"Запрос заблокирован для обработки","Request locked for processing"},                                                                          // 10028
   {"Ордер или позиция заморожены","Order or position frozen"},                                                                                    // 10029
   {"Указан неподдерживаемый тип исполнения ордера по остатку","Invalid order filling type"},                                                      // 10030
   {"Нет соединения с торговым сервером","No connection with the trade server"},                                                                   // 10031
   {"Операция разрешена только для реальных счетов","Operation is allowed only for live accounts"},                                                // 10032
   {"Достигнут лимит на количество отложенных ордеров","The number of pending orders has reached the limit"},                                      // 10033
   {"Достигнут лимит на объем ордеров и позиций для данного символа","The volume of orders and positions for the symbol has reached the limit"},   // 10034
   {"Неверный или запрещённый тип ордера","Incorrect or prohibited order type"},                                                                   // 10035
   {"Позиция с указанным идентификатором уже закрыта","Position with the specified identifier has already been closed"},                           // 10036
   {"Неизвестный код возврата торгового сервера","Unknown trading server return code"},                                                   // 10037
   {"Закрываемый объем превышает текущий объем позиции","A close volume exceeds the current position volume"},                                     // 10038
   {"Для указанной позиции уже есть ордер на закрытие","A close order already exists for a specified position"},                                   // 10039
   {"Достигнут лимит на количество открытых позиций","The number of positions has reached the limit"},                                             // 10040
   {
    "Запрос на активацию отложенного ордера отклонен, а сам ордер отменен",                                                                        // 10041
    "The pending order activation request is rejected, the order is canceled"
   },
   {
    "Запрос отклонен, так как на символе установлено правило \"Разрешены только длинные позиции\"",                                                // 10042
    "The request is rejected, because the \"Only long positions are allowed\" rule is set for the symbol"
   },
   {
    "Запрос отклонен, так как на символе установлено правило \"Разрешены только короткие позиции\"",                                               // 10043
    "The request is rejected, because the \"Only short positions are allowed\" rule is set for the symbol"
   },
   {
    "Запрос отклонен, так как на символе установлено правило \"Разрешено только закрывать существующие позиции\"",                                 // 10044
    "The request is rejected, because the \"Only position closing is allowed\" rule is set for the symbol "
   },
  };
//+------------------------------------------------------------------+

Все коды, возвращаемые торговым сервером, начинаются с кода 10004. Некоторые коды пропущены, и не имеют описания. Например код 10005 и 10037. Но в массиве они быть обязаны — ведь все коды расположены в массиве строго в порядке возрастания. Поэтому на неиспользуемых кодах было добавлено сообщение "Неизвестный код возврата торгового сервера".

И что важно — коды возврата торгового сервера начинаются со значения 10004, а в массиве они располагаются начиная с индекса 0. Поэтому при доступе к массиву, мы из полученного кода будем вычитать значение самого первого кода возврата торгового сервера. Тогда мы точно попадём на индекс нужного кода, описание которого расположено в массиве.
Например, для кода 10004 мы получим индекс 0 (10004 - 10004 = 0), для кода 10007 мы получим индекс 3 (10007 - 10004 = 3)

Массив сообщений ошибок времени выполнения:

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения (0, 4001 - 4019)      |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime[][TOTAL_LANG]=
  {
   {"Операция выполнена успешно","The operation completed successfully"},                                                                          // 0
   {"Неожиданная внутренняя ошибка","Unexpected internal error"},                                                                                  // 4001
   {"Ошибочный параметр при внутреннем вызове функции клиентского терминала","Wrong parameter in the inner call of the client terminal function"}, // 4002
   {"Ошибочный параметр при вызове системной функции","Wrong parameter when calling the system function"},                                         // 4003
   {"Недостаточно памяти для выполнения системной функции","Not enough memory to perform the system function"},                                    // 4004
   {
    "Структура содержит объекты строк и/или динамических массивов и/или структуры с такими объектами и/или классы",                                // 4005
    "The structure contains objects of strings and/or dynamic arrays and/or structure of such objects and/or classes"
   },                                                                                                                                                    
   {
    "Массив неподходящего типа, неподходящего размера или испорченный объект динамического массива",                                               // 4006
    "Array of a wrong type, wrong size, or a damaged object of a dynamic array"
   },
   {
    "Недостаточно памяти для перераспределения массива либо попытка изменения размера статического массива",                                       // 4007
    "Not enough memory for the relocation of an array, or an attempt to change the size of a static array"
   },
   {"Недостаточно памяти для перераспределения строки","Not enough memory for the relocation of string"},                                          // 4008
   {"Неинициализированная строка","Not initialized string"},                                                                                       // 4009
   {"Неправильное значение даты и/или времени","Invalid date and/or time"},                                                                        // 4010
   {"Общее число элементов в массиве не может превышать 2147483647","Total amount of elements in the array cannot exceed 2147483647"},             // 4011
   {"Ошибочный указатель","Wrong pointer"},                                                                                                        // 4012
   {"Ошибочный тип указателя","Wrong type of pointer"},                                                                                            // 4013
   {"Системная функция не разрешена для вызова","Function is not allowed for call"},                                                               // 4014
   {"Совпадение имени динамического и статического ресурсов","The names of the dynamic and the static resource match"},                            // 4015
   {"Ресурс с таким именем в EX5 не найден","Resource with this name has not been found in EX5"},                                                  // 4016
   {"Неподдерживаемый тип ресурса или размер более 16 MB","Unsupported resource type or its size exceeds 16 Mb"},                                  // 4017
   {"Имя ресурса превышает 63 символа","The resource name exceeds 63 characters"},                                                                 // 4018
   {"При вычислении математической функции произошло переполнение ","Overflow occurred when calculating math function "},                          // 4019
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения (раздел ошибок Графиков):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения  (4101 - 4116)        |
//| (Графики)                                                        |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_charts[][TOTAL_LANG]=
  {
   {"Ошибочный идентификатор графика","Wrong chart ID"},                                                                                           // 4101
   {"График не отвечает","Chart does not respond"},                                                                                                // 4102
   {"График не найден","Chart not found"},                                                                                                         // 4103
   {"У графика нет эксперта, который мог бы обработать событие","No Expert Advisor in the chart that could handle the event"},                     // 4104
   {"Ошибка открытия графика","Chart opening error"},                                                                                              // 4105
   {"Ошибка при изменении для графика символа и периода","Failed to change chart symbol and period"},                                              // 4106
   {"Ошибочное значение параметра для функции по работе с графиком","Error value of the parameter for the function of working with charts"},       // 4107
   {"Ошибка при создании таймера","Failed to create timer"},                                                                                       // 4108
   {"Ошибочный идентификатор свойства графика","Wrong chart property ID"},                                                                         // 4109
   {"Ошибка при создании скриншота","Error creating screenshots"},                                                                                 // 4110
   {"Ошибка навигации по графику","Error navigating through chart"},                                                                               // 4111
   {"Ошибка при применении шаблона","Error applying template"},                                                                                    // 4112
   {"Подокно, содержащее указанный индикатор, не найдено","Subwindow containing the indicator was not found"},                                     // 4113
   {"Ошибка при добавлении индикатора на график","Error adding an indicator to chart"},                                                            // 4114
   {"Ошибка при удалении индикатора с графика","Error deleting an indicator from the chart"},                                                      // 4115
   {"Индикатор не найден на указанном графике","Indicator not found on the specified chart"},                                                      // 4116
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения  (раздел ошибок Графических объектов):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения  (4201 - 4205)        |
//| (Графические объекты)                                            |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_graph_obj[][TOTAL_LANG]=
  {
   {"Ошибка при работе с графическим объектом","Error working with a graphical object"},                                                           // 4201
   {"Графический объект не найден","Graphical object was not found"},                                                                              // 4202
   {"Ошибочный идентификатор свойства графического объекта","Wrong ID of a graphical object property"},                                            // 4203
   {"Невозможно получить дату, соответствующую значению","Unable to get date corresponding to the value"},                                         // 4204
   {"Невозможно получить значение, соответствующее дате","Unable to get value corresponding to the date"},                                         // 4205
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения  (раздел ошибок MarketInfo):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения  (4301 - 4305)        |
//| (MarketInfo)                                                     |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_market[][TOTAL_LANG]=
  {
   {"Неизвестный символ","Unknown symbol"},                                                                                                        // 4301
   {"Символ не выбран в MarketWatch","Symbol is not selected in MarketWatch"},                                                                     // 4302
   {"Ошибочный идентификатор свойства символа","Wrong identifier of a symbol property"},                                                           // 4303
   {"Время последнего тика неизвестно (тиков не было)","Time of the last tick is not known (no ticks)"},                                           // 4304
   {"Ошибка добавления или удаления символа в MarketWatch","Error adding or deleting a symbol in MarketWatch"},                                    // 4305
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения  (раздел ошибок Доступа к истории):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения  (4401 - 4407)        |
//| (Доступ к истории)                                               |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_history[][TOTAL_LANG]=
  {
   {"Запрашиваемая история не найдена","Requested history not found"},                                                                             // 4401
   {"Ошибочный идентификатор свойства истории","Wrong ID of the history property"},                                                                // 4402
   {"Превышен таймаут при запросе истории","Exceeded history request timeout"},                                                                    // 4403
   {"Количество запрашиваемых баров ограничено настройками терминала","Number of requested bars limited by terminal settings"},                    // 4404
   {"Множество ошибок при загрузке истории","Multiple errors when loading history"},                                                               // 4405
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4406
   {"Принимающий массив слишком мал чтобы вместить все запрошенные данные","Receiving array is too small to store all requested data"},            // 4407
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения  (раздел ошибок Global Variables):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения  (4501 - 4524)        |
//| (Global Variables)                                               |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_global[][TOTAL_LANG]=
  {
   {"Глобальная переменная клиентского терминала не найдена","Global variable of the client terminal is not found"},                               // 4501
   {
    "Глобальная переменная клиентского терминала с таким именем уже существует",                                                                   // 4502
    "Global variable of the client terminal with the same name already exists"
   },
   {"Не было модификаций глобальных переменных","Global variables were not modified"},                                                             // 4503
   {"Не удалось открыть и прочитать файл со значениями глобальных переменных","Cannot read file with global variable values"},                     // 4504
   {"Не удалось записать файл со значениями глобальных переменных","Cannot write file with global variable values"},                               // 4505
   
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4506
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4507
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4508
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4509
   
   {"Не удалось отправить письмо","Email sending failed"},                                                                                         // 4510
   {"Не удалось воспроизвести звук","Sound playing failed"},                                                                                       // 4511
   {"Ошибочный идентификатор свойства программы","Wrong identifier of the program property"},                                                      // 4512
   {"Ошибочный идентификатор свойства терминала","Wrong identifier of the terminal property"},                                                     // 4513
   {"Не удалось отправить файл по ftp","File sending via ftp failed"},                                                                             // 4514
   {"Не удалось отправить уведомление","Failed to send a notification"},                                                                           // 4515
   {
    "Неверный параметр для отправки уведомления – в функцию SendNotification() передали пустую строку или NULL",                                   // 4516
    "Invalid parameter for sending a notification – an empty string or NULL has been passed to the SendNotification() function"
   },
   {
    "Неверные настройки уведомлений в терминале (не указан ID или не выставлено разрешение)",                                                      // 4517
    "Wrong settings of notifications in the terminal (ID is not specified or permission is not set)"
   },
   {"Слишком частая отправка уведомлений","Too frequent sending of notifications"},                                                                // 4518
   {"Не указан FTP сервер","FTP server is not specified"},                                                                                         // 4519
   {"Не указан FTP логин","FTP login is not specified"},                                                                                           // 4520
   {"Не найден файл в директории MQL5\\Files для отправки на FTP сервер","File not found in the MQL5\\Files directory to send on FTP server"},     // 4521
   {"Ошибка при подключении к FTP серверу","FTP connection failed"},                                                                               // 4522
   {"На FTP сервере не найдена директория для выгрузки файла ","FTP path not found on server"},                                                    // 4523
   {"Подключение к FTP серверу закрыто","FTP connection closed"},                                                                                  // 4524
  };
//+------------------------------------------------------------------+

 Массив сообщений ошибок времени выполнения  (раздел ошибок Буферов и Свойств пользовательских индикаторов):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения  (4601 - 4603)        |
//| (Буферы и свойства пользовательских индикаторов)                 |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_custom_indicator[][TOTAL_LANG]=
  {
   {"Недостаточно памяти для распределения индикаторных буферов","Not enough memory for the distribution of indicator buffers"},                   // 4601
   {"Ошибочный индекс своего индикаторного буфера","Wrong indicator buffer index"},                                                                // 4602
   {"Ошибочный идентификатор свойства пользовательского индикатора","Wrong ID of the custom indicator property"},                                  // 4603
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения  (раздел ошибок Account):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения  (4701 - 4758)        |
//| (Account)                                                        |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_account[][TOTAL_LANG]=
  {
   {"Ошибочный идентификатор свойства счета","Wrong account property ID"},                                                                         // 4701
   
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4702
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4703
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4704
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4705
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4706
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4707
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4708
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4709
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4710
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4711
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4712
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4713
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4714
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4715
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4716
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4717
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4718
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4719
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4720
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4721
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4722
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4723
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4724
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4725
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4726
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4727
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4728
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4729
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4730
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4731
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4732
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4733
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4734
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4735
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4736
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4737
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4738
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4739
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4740
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4741
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4742
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4743
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4744
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4745
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4746
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4747
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4748
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4749
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4750
   
   {"Ошибочный идентификатор свойства торговли","Wrong trade property ID"},                                                                        // 4751
   {"Торговля для эксперта запрещена","Trading by Expert Advisors prohibited"},                                                                    // 4752
   {"Позиция не найдена","Position not found"},                                                                                                    // 4753
   {"Ордер не найден","Order not found"},                                                                                                          // 4754
   {"Сделка не найдена","Deal not found"},                                                                                                         // 4755
   {"Не удалось отправить торговый запрос","Trade request sending failed"},                                                                        // 4756
   {"Неизвестный код ошибки","Unknown error code"},                                                                                       // 4757
   {"Не удалось вычислить значение прибыли или маржи","Failed to calculate profit or margin"},                                                     // 4758
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения  (раздел ошибок Индикаторов):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения  (4801 - 4812)        |
//| (Индикаторы)                                                     |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_indicator[][TOTAL_LANG]=
  {
   {"Неизвестный символ","Unknown symbol"},                                                                                                        // 4801
   {"Индикатор не может быть создан","Indicator cannot be created"},                                                                               // 4802
   {"Недостаточно памяти для добавления индикатора","Not enough memory to add the indicator"},                                                     // 4803
   {"Индикатор не может быть применен к другому индикатору","The indicator cannot be applied to another indicator"},                               // 4804
   {"Ошибка при добавлении индикатора","Error applying an indicator to chart"},                                                                    // 4805
   {"Запрошенные данные не найдены","Requested data not found"},                                                                                   // 4806
   {"Ошибочный хэндл индикатора","Wrong indicator handle"},                                                                                        // 4807
   {"Неправильное количество параметров при создании индикатора","Wrong number of parameters when creating an indicator"},                         // 4808
   {"Отсутствуют параметры при создании индикатора","No parameters when creating an indicator"},                                                   // 4809
   {
    "Первым параметром в массиве должно быть имя пользовательского индикатора",                                                                    // 4810
    "The first parameter in the array must be the name of the custom indicator"
   },
   {"Неправильный тип параметра в массиве при создании индикатора","Invalid parameter type in the array when creating an indicator"},              // 4811
   {"Ошибочный индекс запрашиваемого индикаторного буфера","Wrong index of the requested indicator buffer"},                                       // 4812
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения  (раздел ошибок Стакана цен):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения  (4901 - 4904)        |
//| (Стакан цен)                                                     |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_books[][TOTAL_LANG]=
  {
   {"Стакан цен не может быть добавлен","Depth Of Market can not be added"},                                                                       // 4901
   {"Стакан цен не может быть удален","Depth Of Market can not be removed"},                                                                       // 4902
   {"Данные стакана цен не могут быть получены","The data from Depth Of Market can not be obtained"},                                              // 4903
   {"Ошибка при подписке на получение новых данных стакана цен","Error in subscribing to receive new data from Depth Of Market"},                  // 4904
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения  (раздел ошибок Файловых операций):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения  (5001 - 5027)        |
//| (Файловые операции)                                              |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_files[][TOTAL_LANG]=
  {
   {"Не может быть открыто одновременно более 64 файлов","More than 64 files cannot be opened at the same time"},                                  // 5001
   {"Недопустимое имя файла","Invalid file name"},                                                                                                 // 5002
   {"Слишком длинное имя файла","Too long file name"},                                                                                             // 5003
   {"Ошибка открытия файла","File opening error"},                                                                                                 // 5004
   {"Недостаточно памяти для кеша чтения","Not enough memory for cache to read"},                                                                  // 5005
   {"Ошибка удаления файла","File deleting error"},                                                                                                // 5006
   {"Файл с таким хэндлом уже был закрыт, либо не открывался вообще","A file with this handle was closed, or was not opening at all"},             // 5007
   {"Ошибочный хэндл файла","Wrong file handle"},                                                                                                  // 5008
   {"Файл должен быть открыт для записи","The file must be opened for writing"},                                                                   // 5009
   {"Файл должен быть открыт для чтения","The file must be opened for reading"},                                                                   // 5010
   {"Файл должен быть открыт как бинарный","The file must be opened as a binary one"},                                                             // 5011
   {"Файл должен быть открыт как текстовый","The file must be opened as a text"},                                                                  // 5012
   {"Файл должен быть открыт как текстовый или CSV","The file must be opened as a text or CSV"},                                                   // 5013
   {"Файл должен быть открыт как CSV","The file must be opened as CSV"},                                                                           // 5014
   {"Ошибка чтения файла","File reading error"},                                                                                                   // 5015
   {"Должен быть указан размер строки, так как файл открыт как бинарный","String size must be specified, because the file is opened as binary"},   // 5016
   {
    "Для строковых массивов должен быть текстовый файл, для остальных – бинарный",                                                                 // 5017
    "A text file must be for string arrays, for other arrays - binary"
   },
   {"Это не файл, а директория","This is not a file, this is a directory"},                                                                        // 5018
   {"Файл не существует","File does not exist"},                                                                                                   // 5019
   {"Файл не может быть переписан","File can not be rewritten"},                                                                                   // 5020
   {"Ошибочное имя директории","Wrong directory name"},                                                                                            // 5021
   {"Директория не существует","Directory does not exist"},                                                                                        // 5022
   {"Это файл, а не директория","This is a file, not a directory"},                                                                                // 5023
   {"Директория не может быть удалена","The directory cannot be removed"},                                                                         // 5024
   {
    "Не удалось очистить директорию (возможно, один или несколько файлов заблокированы)",                                                          // 5025
    "Failed to clear the directory (probably one or more files are blocked)"
   },
   {"Не удалось записать ресурс в файл","Failed to write a resource to a file"},                                                                   // 5026
   {
    "Не удалось прочитать следующую порцию данных из CSV-файла, так как достигнут конец файла",                                                    // 5027
    "Unable to read the next piece of data from a CSV file, since the end of file is reached"
   },
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения  (раздел ошибок Преобразования строк):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения  (5030 - 5044)        |
//| (Преобразование строк)                                           |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_string[][TOTAL_LANG]=
  {
   {"В строке нет даты","No date in the string"},                                                                                                  // 5030
   {"В строке ошибочная дата","Wrong date in the string"},                                                                                         // 5031
   {"В строке ошибочное время","Wrong time in the string"},                                                                                        // 5032
   {"Ошибка преобразования строки в дату","Error converting string to date"},                                                                      // 5033
   {"Недостаточно памяти для строки","Not enough memory for the string"},                                                                          // 5034
   {"Длина строки меньше, чем ожидалось","The string length is less than expected"},                                                               // 5035
   {"Слишком большое число, больше, чем ULONG_MAX","Too large number, more than ULONG_MAX"},                                                       // 5036
   {"Ошибочная форматная строка","Invalid format string"},                                                                                         // 5037
   {"Форматных спецификаторов больше, чем параметров","Amount of format specifiers more than the parameters"},                                     // 5038
   {"Параметров больше, чем форматных спецификаторов","Amount of parameters more than the format specifiers"},                                     // 5039
   {"Испорченный параметр типа string","Damaged parameter of string type"},                                                                        // 5040
   {"Позиция за пределами строки","Position outside the string"},                                                                                  // 5041
   {"К концу строки добавлен 0, бесполезная операция","0 added to the string end, a useless operation"},                                           // 5042
   {"Неизвестный тип данных при конвертации в строку","Unknown data type when converting to a string"},                                            // 5043
   {"Испорченный объект строки","Damaged string object"},                                                                                          // 5044
  };
//+------------------------------------------------------------------+

 Массив сообщений ошибок времени выполнения  (раздел ошибок Работы с массивами):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения  (5050 - 5063)        |
//| (Работа с массивами)                                             |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_array[][TOTAL_LANG]=
  {
   {"Копирование несовместимых массивов","Copying incompatible arrays"},                                                                           // 5050
   {
    "Приемный массив объявлен как AS_SERIES, и он недостаточного размера",                                                                         // 5051
    "The receiving array is declared as AS_SERIES, and it is of insufficient size"
   },
   {"Слишком маленький массив, стартовая позиция за пределами массива","Too small array, the starting position is outside the array"},             // 5052
   {"Массив нулевой длины","An array of zero length"},                                                                                             // 5053
   {"Должен быть числовой массив","Must be a numeric array"},                                                                                      // 5054
   {"Должен быть одномерный массив","Must be a one-dimensional array"},                                                                            // 5055
   {"Таймсерия не может быть использована","Timeseries cannot be used"},                                                                           // 5056
   {"Должен быть массив типа double","Must be an array of type double"},                                                                           // 5057
   {"Должен быть массив типа float","Must be an array of type float"},                                                                             // 5058
   {"Должен быть массив типа long","Must be an array of type long"},                                                                               // 5059
   {"Должен быть массив типа int","Must be an array of type int"},                                                                                 // 5060
   {"Должен быть массив типа short","Must be an array of type short"},                                                                             // 5061
   {"Должен быть массив типа char","Must be an array of type char"},                                                                               // 5062
   {"Должен быть массив типа string","String array only"},                                                                                         // 5063
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения  (раздел ошибок Работы с OpenCL):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения  (5100 - 5114)        |
//| (Работа с OpenCL)                                                |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_opencl[][TOTAL_LANG]=
  {
   {"Функции OpenCL на данном компьютере не поддерживаются","OpenCL functions are not supported on this computer"},                                // 5100
   {"Внутренняя ошибка при выполнении OpenCL","Internal error occurred when running OpenCL"},                                                      // 5101
   {"Неправильный хэндл OpenCL","Invalid OpenCL handle"},                                                                                          // 5102
   {"Ошибка при создании контекста OpenCL","Error creating the OpenCL context"},                                                                   // 5103
   {"Ошибка создания очереди выполнения в OpenCL","Failed to create a run queue in OpenCL"},                                                       // 5104
   {"Ошибка при компиляции программы OpenCL","Error occurred when compiling an OpenCL program"},                                                   // 5105
   {"Слишком длинное имя точки входа (кернел OpenCL)","Too long kernel name (OpenCL kernel)"},                                                     // 5106
   {"Ошибка создания кернел - точки входа OpenCL","Error creating an OpenCL kernel"},                                                              // 5107
   {
    "Ошибка при установке параметров для кернел OpenCL (точки входа в программу OpenCL)",                                                          // 5108
    "Error occurred when setting parameters for the OpenCL kernel"
   },
   {"Ошибка выполнения программы OpenCL","OpenCL program runtime error"},                                                                          // 5109
   {"Неверный размер буфера OpenCL","Invalid size of the OpenCL buffer"},                                                                          // 5110
   {"Неверное смещение в буфере OpenCL","Invalid offset in the OpenCL buffer"},                                                                    // 5111
   {"Ошибка создания буфера OpenCL","Failed to create an OpenCL buffer"},                                                                          // 5112
   {"Превышено максимальное число OpenCL объектов","Too many OpenCL objects"},                                                                     // 5113
   {"Ошибка выбора OpenCL устройства","OpenCL device selection error"},                                                                            // 5114
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения  (раздел ошибок Работы с WebRequest()):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения  (5200 - 5203)        |
//| (Работа с WebRequest())                                          |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_webrequest[][TOTAL_LANG]=
  {
   {"URL не прошел проверку","Invalid URL"},                                                                                                       // 5200
   {"Не удалось подключиться к указанному URL","Failed to connect to specified URL"},                                                              // 5201
   {"Превышен таймаут получения данных","Timeout exceeded"},                                                                                       // 5202
   {"Ошибка в результате выполнения HTTP запроса","HTTP request failed"},                                                                          // 5203
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения  (раздел ошибок Работы с сетью (сокетами)):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения  (5270 - 5275)        |
//| (Работа с сетью (сокетами))                                      |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_netsocket[][TOTAL_LANG]=
  {
   {"В функцию передан неверный хэндл сокета","Invalid socket handle passed to function"},                                                         // 5270
   {"Открыто слишком много сокетов (максимум 128)","Too many open sockets (max 128)"},                                                             // 5271
   {"Ошибка соединения с удаленным хостом","Failed to connect to remote host"},                                                                    // 5272
   {"Ошибка отправки/получения данных из сокета","Failed to send/receive data from socket"},                                                       // 5273
   {"Ошибка установления защищенного соединения (TLS Handshake)","Failed to establish secure connection (TLS Handshake)"},                         // 5274
   {"Отсутствуют данные о сертификате, которым защищено подключение","No data on certificate protecting the connection"},                          // 5275
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения  (раздел ошибок Пользовательских символов):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения  (5300 - 5310)        |
//| (Пользовательские символы)                                       |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_custom_symbol[][TOTAL_LANG]=
  {
   {"Должен быть указан пользовательский символ","A custom symbol must be specified"},                                                             // 5300
   {"Некорректное имя пользовательского символа","The name of the custom symbol is invalid"},                                                      // 5301
   {"Слишком длинное имя для пользовательского символа","The name of the custom symbol is too long"},                                              // 5302
   {"Слишком длинный путь для пользовательского символа","The path of the custom symbol is too long"},                                             // 5303
   {"Пользовательский символ с таким именем уже существует","A custom symbol with the same name already exists"},                                  // 5304
   {
    "Ошибка при создании, удалении или изменении пользовательского символа",                                                                       // 5305
    "Error occurred while creating, deleting or changing the custom symbol"
   },
   {"Попытка удалить пользовательский символ, выбранный в обзоре рынка","You are trying to delete a custom symbol selected in Market Watch"},      // 5306
   {"Неправильное свойство пользовательского символа","An invalid custom symbol property"},                                                        // 5307
   {"Ошибочный параметр при установке свойства пользовательского символа","A wrong parameter while setting the property of a custom symbol"},      // 5308
   {
    "Слишком длинный строковый параметр при установке свойства пользовательского символа",                                                         // 5309
    "A too long string parameter while setting the property of a custom symbol"
   },
   {"Не упорядоченный по времени массив тиков","Ticks in the array are not arranged in the order of time"},                                        // 5310
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения  (раздел ошибок Экономического календаря):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения  (5400 - 5402)        |
//| (Экономический календарь)                                        |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_calendar[][TOTAL_LANG]=
  {
   {"Размер массива недостаточен для получения описаний всех значений","Array size is insufficient for receiving descriptions of all values"},     // 5400
   {"Превышен лимит запроса по времени","Request time limit exceeded"},                                                                            // 5401
   {"Страна не найдена","Country is not found"},                                                                                                   // 5402
  };
//+------------------------------------------------------------------+

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

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

Массив сообщений кодов возврата торгового сервера MQL4:

//+------------------------------------------------------------------+
#ifdef __MQL4__
//+------------------------------------------------------------------+
//| Массив сообщений кодов возврата торгового сервера MQL4 (0 - 150) |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_ts_ret_code_mql4[][TOTAL_LANG]=
  {
   {"Нет ошибки","No error returned"},                                                             // 0
   {"Нет ошибки, но результат неизвестен","No error returned, but the result is unknown"},         // 1
   {"Общая ошибка","Common error"},                                                                // 2
   {"Неправильные параметры","Invalid trade parameters"},                                          // 3
   {"Торговый сервер занят","Trade server is busy"},                                               // 4
   {"Старая версия клиентского терминала","Old version of the client terminal"},                   // 5
   {"Нет связи с торговым сервером","No connection with trade server"},                            // 6
   {"Недостаточно прав","Not enough rights"},                                                      // 7
   {"Слишком частые запросы","Too frequent requests"},                                             // 8
   {"Недопустимая операция, нарушающая функционирование сервера","Malfunctional trade operation"}, // 9
   
   {"Счет заблокирован","Account disabled"},                                                       // 64
   {"Неправильный номер счета","Invalid account"},                                                 // 65
   
   {"Истек срок ожидания совершения сделки","Trade timeout"},                                      // 128
   {"Неправильная цена","Invalid price"},                                                          // 129
   {"Неправильные стопы","Invalid stops"},                                                         // 130
   {"Неправильный объем","Invalid trade volume"},                                                  // 131
   {"Рынок закрыт","Market is closed"},                                                            // 132
   {"Торговля запрещена","Trade is disabled"},                                                     // 133
   {"Недостаточно денег для совершения операции","Not enough money"},                              // 134
   {"Цена изменилась","Price changed"},                                                            // 135
   {"Нет цен","Off quotes"},                                                                       // 136
   {"Брокер занят","Broker is busy"},                                                              // 137
   {"Новые цены","Requote"},                                                                       // 138
   {"Ордер заблокирован и уже обрабатывается","Order is locked"},                                  // 139
   {"Разрешена только покупка","Buy orders only allowed"},                                         // 140
   {"Слишком много запросов","Too many requests"},                                                 // 141
   {"Неизвестный код возврата торгового сервера","Unknown trading server return code"},     // 142
   {"Неизвестный код возврата торгового сервера","Unknown trading server return code"},     // 143
   {"Неизвестный код возврата торгового сервера","Unknown trading server return code"},     // 144
   {
    "Модификация запрещена, так как ордер слишком близок к рынку",                                 // 145
    "Modification denied because order is too close to market"
   }, 
   {"Подсистема торговли занята","Trade context is busy"},     // 146
   {"Использование даты истечения ордера запрещено брокером","Expirations are denied by broker"},  // 147
   {
    "Количество открытых и отложенных ордеров достигло предела, установленного брокером",          // 148
    "The amount of open and pending orders has reached the limit set by the broker"
   },
   {
    "Попытка открыть противоположный ордер в случае, если хеджирование запрещено",                 // 149
    "An attempt to open an order opposite to the existing one when hedging is disabled"
   },
   {
    "Попытка закрыть позицию по инструменту в противоречии с правилом FIFO",                       // 150
    "An attempt to close an order contravening the FIFO rule"
   },
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения MQL4 (коды в диапазоне 4000 — 4030):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения MQL4 (4000 - 4030)    |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_4000_4030[][TOTAL_LANG]=
  {
   {"Нет ошибки","No error returned"},                                                             // 4000
   {"Неправильный указатель функции","Wrong function pointer"},                                    // 4001
   {"Индекс массива - вне диапазона","Array index is out of range"},                               // 4002
   {"Нет памяти для стека функций","No memory for function call stack"},                           // 4003
   {"Переполнение стека после рекурсивного вызова","Recursive stack overflow"},                    // 4004
   {"На стеке нет памяти для передачи параметров","Not enough stack for parameter"},               // 4005
   {"Нет памяти для строкового параметра","No memory for parameter string"},                       // 4006
   {"Нет памяти для временной строки","No memory for temp string"},                                // 4007
   {"Неинициализированная строка","Not initialized string"},                                       // 4008
   {"Неинициализированная строка в массиве","Not initialized string in array"},                    // 4009
   {"Нет памяти для строкового массива","No memory for array string"},                             // 4010
   {"Слишком длинная строка","Too long string"},                                                   // 4011
   {"Остаток от деления на ноль","Remainder from zero divide"},                                    // 4012
   {"Деление на ноль","Zero divide"},                                                              // 4013
   {"Неизвестная команда","Unknown command"},                                                      // 4014
   {"Неправильный переход","Wrong jump (never generated error)"},                                  // 4015
   {"Неинициализированный массив","Not initialized array"},                                        // 4016
   {"Вызовы DLL не разрешены","DLL calls are not allowed"},                                        // 4017
   {"Невозможно загрузить библиотеку","Cannot load library"},                                      // 4018
   {"Невозможно вызвать функцию","Cannot call function"},                                          // 4019
   {"Вызовы внешних библиотечных функций не разрешены","Expert function calls are not allowed"},   // 4020
   {
    "Недостаточно памяти для строки, возвращаемой из функции",                                     // 4021
    "Not enough memory for temp string returned from function"
   },
   {"Система занята","System is busy (never generated error)"},                                    // 4022
   {"Критическая ошибка вызова DLL-функции","DLL-function call critical error"},                   // 4023
   {"Внутренняя ошибка","Internal error"},                                                         // 4024
   {"Нет памяти","Out of memory"},                                                                 // 4025
   {"Неверный указатель","Invalid pointer"},                                                       // 4026
   {
    "Слишком много параметров форматирования строки",                                              // 4027
    "Too many formatters in the format function"
   },
   {
    "Число параметров превышает число параметров форматирования строки",                           // 4028
    "Parameters count exceeds formatters count"
   },
   {"Неверный массив","Invalid array"},                                                            // 4029
   {"График не отвечает","No reply from chart"},                                                   // 4030
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения MQL4 (коды в диапазоне 4050 — 4075):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения MQL4 (4050 - 4075)    |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_4050_4075[][TOTAL_LANG]=
  {
   {"Неправильное количество параметров функции","Invalid function parameters count"},             // 4050
   {"Недопустимое значение параметра функции","Invalid function parameter value"},                 // 4051
   {"Внутренняя ошибка строковой функции","String function internal error"},                       // 4052
   {"Ошибка массива","Some array error"},                                                          // 4053
   {"Неправильное использование массива-таймсерии","Incorrect series array using"},                // 4054
   {"Ошибка пользовательского индикатора","Custom indicator error"},                               // 4055
   {"Массивы несовместимы","Arrays are incompatible"},                                             // 4056
   {"Ошибка обработки глобальных переменных","Global variables processing error"},                 // 4057
   {"Глобальная переменная не обнаружена","Global variable not found"},                            // 4058
   {"Функция не разрешена в тестовом режиме","Function is not allowed in testing mode"},           // 4059
   {"Функция не разрешена","Function is not allowed for call"},                                    // 4060
   {"Ошибка отправки почты","Send mail error"},                                                    // 4061
   {"Ожидается параметр типа string","String parameter expected"},                                 // 4062
   {"Ожидается параметр типа integer","Integer parameter expected"},                               // 4063
   {"Ожидается параметр типа double","Double parameter expected"},                                 // 4064
   {"В качестве параметра ожидается массив","Array as parameter expected"},                        // 4065
   {
    "Запрошенные исторические данные в состоянии обновления",                                      // 4066
    "Requested history data is in updating state"
   },
   {"Ошибка при выполнении торговой операции","Internal trade error"},                             // 4067
   {"Ресурс не найден","Resource not found"},                                                      // 4068
   {"Ресурс не поддерживается","Resource not supported"},                                          // 4069
   {"Дубликат ресурса","Duplicate resource"},                                                      // 4070
   {"Ошибка инициализации пользовательского индикатора","Custom indicator cannot initialize"},     // 4071
   {"Ошибка загрузки пользовательского индикатора","Cannot load custom indicator"},                // 4072
   {"Нет исторических данных","No history data"},                                                  // 4073
   {"Не хватает памяти для исторических данных","No memory for history data"},                     // 4074
   {"Не хватает памяти для расчёта индикатора","Not enough memory for indicator calculation"},     // 4075
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения MQL4 (коды в диапазоне 4099 — 4112):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения MQL4 (4099 - 4112)    |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_4099_4112[][TOTAL_LANG]=
  {
   {"Конец файла","End of file"},                                                                  // 4099
   {"Ошибка при работе с файлом","Some file error"},                                               // 4100
   {"Неправильное имя файла","Wrong file name"},                                                   // 4101
   {"Слишком много открытых файлов","Too many opened files"},                                      // 4102
   {"Невозможно открыть файл","Cannot open file"},                                                 // 4103
   {"Несовместимый режим доступа к файлу","Incompatible access to a file"},                        // 4104
   {"Ни один ордер не выбран","No order selected"},                                                // 4105
   {"Неизвестный символ","Unknown symbol"},                                                        // 4106
   {"Неправильный параметр цены для торговой функции","Invalid price"},                            // 4107
   {"Неверный номер тикета","Invalid ticket"},                                                     // 4108
   {
    "Торговля не разрешена. Необходимо включить опцию \"Разрешить советнику торговать\" в свойствах эксперта", // 4109
    "Trade is not allowed. Enable checkbox \"Allow live trading\" in the Expert Advisor properties"
   },
   {
    "Ордера на покупку не разрешены. Необходимо проверить свойства эксперта",                      // 4110
    "Longs are not allowed. Check the Expert Advisor properties"
   },
   {
    "Ордера на продажу не разрешены. Необходимо проверить свойства эксперта",                      // 4111
    "Shorts are not allowed. Check the Expert Advisor properties"
   },
   {
    "Автоматическая торговля с помощью экспертов/скриптов запрещена на стороне сервера",           // 4112
    "Automated trading by Expert Advisors/Scripts disabled by trade server"
   },
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения MQL4 (коды в диапазоне 4200 — 4220):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения MQL4 (4200 - 4220)    |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_4200_4220[][TOTAL_LANG]=
  {
   {"Объект уже существует","Object already exists"},                                              // 4200
   {"Запрошено неизвестное свойство объекта","Unknown object property"},                           // 4201
   {"Объект не существует","Object does not exist"},                                               // 4202
   {"Неизвестный тип объекта","Unknown object type"},                                              // 4203
   {"Нет имени объекта","No object name"},                                                         // 4204
   {"Ошибка координат объекта","Object coordinates error"},                                        // 4205
   {"Не найдено указанное подокно","No specified subwindow"},                                      // 4206
   {"Ошибка при работе с объектом","Graphical object error"},                                      // 4207
   {"Неизвестный код ошибки","Unknown error code"},                                       // 4208
   {"Неизвестный код ошибки","Unknown error code"},                                       // 4209
   {"Неизвестное свойство графика","Unknown chart property"},                                      // 4210
   {"График не найден","Chart not found"},                                                         // 4211
   {"Не найдено подокно графика","Chart subwindow not found"},                                     // 4212
   {"Индикатор не найден","Chart indicator not found"},                                            // 4213
   {"Неизвестный код ошибки","Unknown error code"},                                       // 4214
   {"Неизвестный код ошибки","Unknown error code"},                                       // 4215
   {"Неизвестный код ошибки","Unknown error code"},                                       // 4216
   {"Неизвестный код ошибки","Unknown error code"},                                       // 4217
   {"Неизвестный код ошибки","Unknown error code"},                                       // 4218
   {"Неизвестный код ошибки","Unknown error code"},                                       // 4219
   {"Ошибка выбора инструмента","Symbol select error"},                                            // 4220
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения MQL4 (коды в диапазоне 4250 — 4266):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения MQL4 (4250 - 4266)    |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_4250_4266[][TOTAL_LANG]=
  {
   {"Ошибка отправки push-уведомления","Notification error"},                                      // 4250
   {"Ошибка параметров push-уведомления","Notification parameter error"},                          // 4251
   {"Уведомления запрещены","Notifications disabled"},                                             // 4252
   {"Слишком частые запросы отсылки push-уведомлений","Notification send too frequent"},           // 4253
   {"Неизвестный код ошибки","Unknown error code"},                                       // 4254
   {"Неизвестный код ошибки","Unknown error code"},                                       // 4255
   {"Неизвестный код ошибки","Unknown error code"},                                       // 4256
   {"Неизвестный код ошибки","Unknown error code"},                                       // 4257
   {"Неизвестный код ошибки","Unknown error code"},                                       // 4258
   {"Неизвестный код ошибки","Unknown error code"},                                       // 4259
   {"Не указан FTP сервер","FTP server is not specified"},                                         // 4260
   {"Не указан FTP логин","FTP login is not specified"},                                           // 4261
   {"Ошибка при подключении к FTP серверу","FTP connection failed"},                               // 4262
   {"Подключение к FTP серверу закрыто","FTP connection closed"},                                  // 4263
   {"На FTP сервере не найдена директория для выгрузки файла ","FTP path not found on server"},    // 4264
   {
    "Не найден файл в директории MQL4\\Files для отправки на FTP сервер",                          // 4265
    "File not found in the MQL4\\Files directory to send on FTP server"
   }, 
   {"Ошибка при передаче файла на FTP сервер","Common error during FTP data transmission"},        // 4266
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения MQL4 (коды в диапазоне 5001 — 5029):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения MQL4 (5001 - 5029)    |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_5001_5029[][TOTAL_LANG]=
  {
   {"Слишком много открытых файлов","Too many opened files"},                                      // 5001
   {"Неверное имя файла","Wrong file name"},                                                       // 5002
   {"Слишком длинное имя файла","Too long file name"},                                             // 5003
   {"Ошибка открытия файла","Cannot open file"},                                                   // 5004
   {"Ошибка размещения буфера текстового файла","Text file buffer allocation error"},              // 5005
   {"Ошибка удаления файла","Cannot delete file"},                                                 // 5006
   {
    "Неверный хендл файла (файл закрыт или не был открыт)",                                        // 5007
    "Invalid file handle (file closed or was not opened)"
   },
   {
    "Неверный хендл файла (индекс хендла отсутствует в таблице)",                                  // 5008
    "Wrong file handle (handle index is out of handle table)"
   },
   {"Файл должен быть открыт с флагом FILE_WRITE","File must be opened with FILE_WRITE flag"},     // 5009
   {"Файл должен быть открыт с флагом FILE_READ","File must be opened with FILE_READ flag"},       // 5010
   {"Файл должен быть открыт с флагом FILE_BIN","File must be opened with FILE_BIN flag"},         // 5011
   {"Файл должен быть открыт с флагом FILE_TXT","File must be opened with FILE_TXT flag"},         // 5012
   {
    "Файл должен быть открыт с флагом FILE_TXT или FILE_CSV",                                      // 5013
    "File must be opened with FILE_TXT or FILE_CSV flag"
   },
   {"Файл должен быть открыт с флагом FILE_CSV","File must be opened with FILE_CSV flag"},         // 5014
   {"Ошибка чтения файла","File read error"},                                                      // 5015
   {"Ошибка записи файла","File write error"},                                                     // 5016
   {
    "Размер строки должен быть указан для двоичных файлов",                                        // 5017
    "String size must be specified for binary file"
   },
   {
    "Неверный тип файла (для строковых массивов-TXT, для всех других-BIN)",                        // 5018
    "Incompatible file (for string arrays-TXT, for others-BIN)"
   },
   {"Файл является директорией","File is directory not file"},                                     // 5019
   {"Файл не существует","File does not exist"},                                                   // 5020
   {"Файл не может быть перезаписан","File cannot be rewritten"},                                  // 5021
   {"Неверное имя директории","Wrong directory name"},                                             // 5022
   {"Директория не существует","Directory does not exist"},                                        // 5023
   {"Указанный файл не является директорией","Specified file is not directory"},                   // 5024
   {"Ошибка удаления директории","Cannot delete directory"},                                       // 5025
   {"Ошибка очистки директории","Cannot clean directory"},                                         // 5026
   {"Ошибка изменения размера массива","Array resize error"},                                      // 5027
   {"Ошибка изменения размера строки","String resize error"},                                      // 5028
   {
    "Структура содержит строки или динамические массивы",                                          // 5029
    "Structure contains strings or dynamic arrays"
   },
  };
//+------------------------------------------------------------------+

Массив сообщений ошибок времени выполнения MQL4 (коды в диапазоне 5200 — 5203):

//+------------------------------------------------------------------+
//| Массив сообщений ошибок времени выполнения MQL4 (5200 - 5203)    |
//| (1) на языке страны пользователя                                 |
//| (2) на международном языке                                       |
//+------------------------------------------------------------------+
string messages_runtime_5200_5203[][TOTAL_LANG]=
  {
   {"URL не прошел проверку","Invalid URL"},                                                       // 5200
   {"Не удалось подключиться к указанному URL","Failed to connect to specified URL"},              // 5201
   {"Превышен таймаут получения данных","Timeout exceeded"},                                       // 5202
   {"Ошибка в результате выполнения HTTP запроса","HTTP request failed"},                          // 5203
  };
#endif 
//+------------------------------------------------------------------+

Данный файл нам необходимо подключить к библиотеке. Так как файл с макроподстановками и перечислениями Defines.mqh уже подключен к библиотеке и виден в любом её месте, то
подключим новый файл Datas.mqh к файлу Defines.mqh — тогда и он точно так же станет виден в любом месте библиотеки:

//+------------------------------------------------------------------+
//|                                                      Defines.mqh |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                             https://mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://mql5.com/ru/users/artmedia70"
//+------------------------------------------------------------------+
//| Включаемые файлы                                                 |
//+------------------------------------------------------------------+
#include "Datas.mqh"
#ifdef __MQL4__
#include "ToMQL4.mqh"
#endif 
//+------------------------------------------------------------------+
//| Макроподстановки                                                 |
//+------------------------------------------------------------------+

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

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

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

Класс для вывода сообщений

Создадим новый файл класса CMessage с именем \MQL5\Include\DoEasy\Services\ Message.mqh.

Сразу же подключим к нему файл Defines.mqh:

//+------------------------------------------------------------------+
//|                                                      Message.mqh |
//|                        Copyright 2018, MetaQuotes Software Corp. |
//|                             https://mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2018, MetaQuotes Software Corp."
#property link      "https://mql5.com/ru/users/artmedia70"
#property version   "1.00"
#property strict    // Нужно для mql4
//+------------------------------------------------------------------+
//| Включаемые файлы                                                 |
//+------------------------------------------------------------------+
#include "..\Defines.mqh"
//+------------------------------------------------------------------+
//| Класс сообщения                                                  |
//+------------------------------------------------------------------+
class CMessage
  {
private:

public:

  };
//+------------------------------------------------------------------+

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

Добавим в приватную секцию класса статические переменные-члены класса и статический метод получения данных из массивов (таблица данных сообщений) по идентификатору сообщения:

//+------------------------------------------------------------------+
//| Класс сообщения                                                  |
//+------------------------------------------------------------------+
class CMessage
  {
private:
   static int        m_global_error;
   static uchar      m_lang_num;
   static string     m_subject;
   static string     m_text;
   static bool       m_log;
   static bool       m_push;
   static bool       m_mail;
//--- Получает сообщение из нужного массива по идентификатору сообщения
   static void       GetTextByID(const int msg_id);
public:

Переменная m_global_error предназначена для хранения кода ошибки при работе методов класса.
В переменную m_lang_num будем записывать номер нужного языка сообщений (0 — русский в данной редакции, 1 — английский, 2, 3, ..., N — любые другие языки, добавляемые пользователем при необходимости).
Переменная m_subject служит для установки заголовка письма сообщения, отправляемого на e-mail адрес функцией SendMail().
В переменную m_text будем получать сообщение из массивов по указанному идентификатору и номеру языка, установленному в переменной m_lang_num.
Переменная m_logхранит глобальный флаг разрешения/запрета вывода сообщений в журнал.
Переменная m_pushхранит глобальный флаг разрешения/запрета отправки Push-уведомлений на мобильное устройство.
Переменная m_mailхранит глобальный флаг разрешения/запрета отправки сообщений на почту.

Метод получения сообщения из массива по идентификатору сообщения записывает в переменную m_text нужное сообщение, на которое указывает его идентификатор (либо из перечисления сообщений библиотеки, либо — код ошибки, возвращаемый функцией GetLastError()).

Добавим в публичную секцию класса необходимые методы:

//+------------------------------------------------------------------+
//| Класс сообщения                                                  |
//+------------------------------------------------------------------+
class CMessage
  {
private:
   static int        m_global_error;
   static uchar      m_lang_num;
   static string     m_subject;
   static string     m_text;
   static bool       m_log;
   static bool       m_push;
   static bool       m_mail;
//--- Получает сообщение из нужного массива по идентификатору сообщения
   static void       GetTextByID(const int msg_id);
public:
//--- (1) Выводит текстовое сообщение в журнал, отправляет Push и e-mail,
//--- (2) Выводит сообщение в журнал по идентификатору, отправляет Push и e-mail,
//--- (3) воспроизводит звуковой файл
   static bool       Out(const string text,const bool push=false,const bool mail=false,const string subject=NULL);
   static bool       OutByID(const int msg_id,const bool code=true);
   static bool       PlaySound(const string file_name);
   //--- Возвращает (1) сообщение, (2) код в формате "(код)"
   static string     Text(const int msg_id);
   static string     Retcode(const int msg_id)     { return "("+(string)msg_id+")";    }
//--- Устанавливает (1) номер языка текстовых сообщений (0 - язык страны пользователя, 1 - английский, 2 ... N - добавляемые пользователем),
//--- (2) заголовок письма,
//--- флаг отправки сообщений (3) в журнал, (4) на мобильное устройство, (5) на почту
   static void       SetLangNum(const uchar num=0) { CMessage::m_lang_num=num;         }
   static void       SetSubject(const string subj) { CMessage::m_subject=subj;         }
   static void       SetLog(const bool flag)       { CMessage::m_log=flag;             }
   static void       SetPush(const bool flag)      { CMessage::m_push=flag;            }
   static void       SetMail(const bool flag)      { CMessage::m_mail=flag;            }
//--- (1) выводит сообщение в журнал по идентификатору, (2) на e-mail, (3) на мобильное устройство
   static void       ToLog(const int msg_id,const bool code=false);
   static bool       ToMail(const string message,const string subject=NULL);
   static bool       Push(const string message);
//--- (1) отправляет файл на FTP, (2) возвращает код ошибки
   static bool       ToFTP(const string filename,const string ftp_path=NULL);
   static int        GetError(void)                { return CMessage::m_global_error;  }
  };
//+------------------------------------------------------------------+

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

Исходя из того, что "Статический член класса требуется явно инициализировать нужным значением, для этого он должен быть объявлен и проинициализирован на глобальном уровне", пропишем в коде за пределами тела класса инициализацию всех его статических переменных:

//+------------------------------------------------------------------+
//| Инициализация статических переменных                             |
//+------------------------------------------------------------------+
uchar  CMessage::m_lang_num=(::TerminalInfoString(TERMINAL_LANGUAGE)==COUNTRY_LANG ? 0 : 1);
int    CMessage::m_global_error=ERR_SUCCESS;
string CMessage::m_subject=::MQLInfoString(MQL_PROGRAM_NAME);
string CMessage::m_text=NULL;
bool   CMessage::m_log=true;
bool   CMessage::m_push=true;
bool   CMessage::m_mail=false;
//+------------------------------------------------------------------+

Здесь мы инициализируем все переменные их значениями по умолчанию:
Номер языка текстовых сообщений устанавливается в зависимости от языка, установленного в терминале. Если язык терминала, возвращаемый при помощи TerminalInfoString( TERMINAL_LANGUAGE), совпадает с языком страны пользователя (в данной редакции — с русским языком), то индекс языка сообщений будет равняться нулю, иначе — язык сообщений будет английским, что соответствует индексу языка 1.
Код ошибки устанавливаем на значение "Нет ошибки".
Заголовок письма для отправки на почту по умолчанию будет именем программы, возвращаемым при помощи MQLInfoString(MQL_PROGRAM_NAME).
Текст сообщения по умолчанию отсутствует, вывод в журнал разрешён, отправка Push-уведомлений разрешена, отправка на почту — запрещена.

Рассмотрим реализацию методов класса.

Метод вывода текстового сообщения в журнал, отправки Push-уведомления и отправки сообщения на e-mail:

//+------------------------------------------------------------------+
//| Выводит сообщение в журнал, отправляет Push и e-mail             |
//+------------------------------------------------------------------+
bool CMessage::Out(const string text,const bool push=false,const bool mail=false,const string subject=NULL)
  {
   bool res=true;
   if(CMessage::m_log)
      ::Print(text);
   if(push)
      res &=CMessage::Push(text);
   if(mail)
      res &=CMessage::ToMail(text,subject);
   return res;
  }
//+------------------------------------------------------------------+

В метод передаётся текст сообщения и флаги, устанавливающие необходимость отправки Push-уведомления и e-mail-сообщения, а также заголовок письма для почтового сообщения.

Сначала проверяется глобальный флаг разрешения вывода сообщений в журнал, и если он поднят, то печатаем сообщение.
Далее проверяем соответствующие флаги, переданные в метод параметрами, для отправки Push-уведомления и отправки сообщения на почту. Если флаги установлены — вызываем соответствующие методы для отправки сообщения. В локальную переменную res записывается результат работы вызываемых методов отправки сообщения. Изначально ей устанавливается значение true. Если хоть один из методов вернёт false, то в переменной будет записано это значение. Из метода возвращается итоговое значение переменной res.

Метод вывода сообщения в журнал по идентификатору сообщения, отправки Push-уведомления и отправки сообщения на e-mail:

//+------------------------------------------------------------------+
//| Выводит сообщение в журнал по идентификатору,                    |
//| отправляет Push и e-mail                                         |
//+------------------------------------------------------------------+
bool CMessage::OutByID(const int msg_id,const bool code=true)
  {
   bool res=true;
   if(CMessage::m_log)
      CMessage::ToLog(msg_id,code);
   else
      CMessage::GetTextByID(msg_id);
   if(CMessage::m_push)
      res &=CMessage::Push(CMessage::m_text);
   if(CMessage::m_mail)
      res &=CMessage::ToMail(CMessage::m_text,CMessage::m_subject);
   return res;
  }
//+------------------------------------------------------------------+

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

Метод, выводящий сообщение в журнал по идентификатору сообщения:

//+------------------------------------------------------------------+
//| Выводит сообщение в журнал по идентификатору сообщения           |
//+------------------------------------------------------------------+
void CMessage::ToLog(const int msg_id,const bool code=false)
  {
   CMessage::GetTextByID(msg_id);
   ::Print(m_text,(!code || msg_id>ERR_USER_ERROR_FIRST-1 ? "" : " "+CMessage::Retcode(msg_id)));
  }
//+------------------------------------------------------------------+

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

Методы отправки сообщения на почту, Push-уведомления на мобильное устройство и файла на FTP-сервер:

//+------------------------------------------------------------------+
//| Отправляет сообщение на почту                                    |
//+------------------------------------------------------------------+
bool CMessage::ToMail(const string message,const string subject=NULL)
  {
   //--- Если в терминале не разрешена отправка сообщений на почту
   if(!::TerminalInfoInteger(TERMINAL_EMAIL_ENABLED))
     {
      //--- выведем об этом сообщение в журнал, запишем код ошибки и вернём false
      CMessage::ToLog(MSG_LIB_TEXT_NOT_MAIL_ENABLED,false);
      CMessage::m_global_error=ERR_MAIL_SEND_FAILED;
      return false;
     }
   //--- Если не удалось отправить сообщение
   if(!::SendMail(subject==NULL ? CMessage::m_subject : subject,message))
     {
      //--- запишем код ошибки, создадим текст описания ошибки, распечатаем его в журнал и вернём false
      CMessage::m_global_error=::GetLastError();
      string txt=CMessage::Text(MSG_LIB_SYS_ERROR)+CMessage::Text(CMessage::m_global_error);
      string code=CMessage::Retcode(CMessage::m_global_error);
      ::Print(txt+" "+code);
      return false;
     }
   //--- Успешно - возвращаем true
   return true;
  }
//+------------------------------------------------------------------+
//| Отправляет Push-уведомления на мобильное устройство              |
//+------------------------------------------------------------------+
bool CMessage::Push(const string message)
  {
   //--- Если в терминале не разрешена отправка Push-уведомлений
   if(!::TerminalInfoInteger(TERMINAL_NOTIFICATIONS_ENABLED))
     {
      //--- выведем об этом сообщение в журнал, запишем код ошибки и вернём false
      CMessage::ToLog(MSG_LIB_TEXT_NOT_PUSH_ENABLED,false);
      CMessage::m_global_error=ERR_NOTIFICATION_SEND_FAILED;
      return false;
     }
   //--- Если не удалось отправить сообщение
   if(!::SendNotification(message))
     {
      //--- запишем код ошибки, создадим текст описания ошибки, распечатаем его в журнал и вернём false
      CMessage::m_global_error=::GetLastError();
      string txt=CMessage::Text(MSG_LIB_SYS_ERROR)+CMessage::Text(CMessage::m_global_error);
      string code=CMessage::Retcode(CMessage::m_global_error);
      ::Print(txt+" "+code);
      return false;
     }
   //--- Успешно - возвращаем true
   return true;
  }
//+------------------------------------------------------------------+
//| Отправляет файл по указанному адресу                             |
//+------------------------------------------------------------------+
bool CMessage::ToFTP(const string filename,const string ftp_path=NULL)
  {
   //--- Если в терминале не разрешена отправка файлов на FTP-сервер
   if(!::TerminalInfoInteger(TERMINAL_FTP_ENABLED))
     {
      //--- выведем об этом сообщение в журнал, запишем код ошибки и вернём false
      CMessage::ToLog(MSG_LIB_TEXT_NOT_FTP_ENABLED,false);
      CMessage::m_global_error=ERR_FTP_SEND_FAILED;
      return false;
     }
   //--- Если не удалось отправить файл
   if(!::SendFTP(filename,ftp_path))
     {
      //--- запишем код ошибки, создадим текст описания ошибки, распечатаем его в журнал и вернём false
      CMessage::m_global_error=::GetLastError();
      string txt=CMessage::Text(MSG_LIB_SYS_ERROR)+CMessage::Text(CMessage::m_global_error);
      string code=CMessage::Retcode(CMessage::m_global_error);
      ::Print(txt+" "+code);
      return false;
     }
   return true;
  }
//+------------------------------------------------------------------+

Все три метода по своей логике идентичны и просты. Вся логика прокомментирована прямо в листинге методов, и оставим её для самостоятельного рассмотрения.

Метод для воспроизведения звукового файла:

//+------------------------------------------------------------------+
//| Воспроизводит звуковой файл                                      |
//+------------------------------------------------------------------+
bool CMessage::PlaySound(const string file_name)
  {
   bool res=::PlaySound(file_name);
   CMessage::m_global_error=(res ? ERR_SUCCESS : ::GetLastError());
   return res;
  }
//+------------------------------------------------------------------+

В переменную res записываем результат работы функции PlaySound(). Если функция отработала верно, то записываем код отсутствия ошибки в переменную m_global_error. В противном случае — записываем в неё код последней ошибки.
В итоге возвращаем значение переменной res, где хранится результат работы функции PlaySound().

Метод, возвращающий текст сообщения по идентификатору:

//+------------------------------------------------------------------+
//| Возвращает текст сообщения по идентификатору сообщения           |
//+------------------------------------------------------------------+
string CMessage::Text(const int msg_id)
  {
   CMessage::GetTextByID(msg_id);
   return m_text;
  }
//+------------------------------------------------------------------+

В метод передаётся идентификатор сообщения. Затем при помощи метода GetTextByID() извлекается нужное сообщение из соответствующего массива текстов и текст сообщения возвращается в вызывающую программу.

Метод, извлекающий текст сообщения по идентификатору сообщения из соответствующего массива текстов:

//+------------------------------------------------------------------+
//| Получение сообщения из массива текстов по идентификатору         |
//+------------------------------------------------------------------+
void CMessage::GetTextByID(const int msg_id)
  {
   CMessage::m_text=
     (
      //--- Ошибки времени выполнения (0, 4001 - 4019)
      msg_id==0                     ?  messages_runtime[msg_id][m_lang_num]                       :
     #ifdef __MQL5__
      msg_id>4000 && msg_id<4020    ?  messages_runtime[msg_id-4000][m_lang_num]                  :
      //--- Ошибки времени выполнения (Графики 4101 - 4116)
      msg_id>4100 && msg_id<4117    ?  messages_runtime_charts[msg_id-4101][m_lang_num]           :
      //--- Ошибки времени выполнения (Графические объекты 4201 - 4205)
      msg_id>4200 && msg_id<4206    ?  messages_runtime_graph_obj[msg_id-4201][m_lang_num]        :
      //--- Ошибки времени выполнения (MarketInfo 4301 - 4305)
      msg_id>4300 && msg_id<4306    ?  messages_runtime_market[msg_id-4301][m_lang_num]           :
      //--- Ошибки времени выполнения (Доступ к истории 4401 - 4407)
      msg_id>4400 && msg_id<4408    ?  messages_runtime_history[msg_id-4401][m_lang_num]          :
      //--- Ошибки времени выполнения (Global Variables 4501 - 4524)
      msg_id>4500 && msg_id<4525    ?  messages_runtime_global[msg_id-4501][m_lang_num]           :
      //--- Ошибки времени выполнения (Пользовательские индикаторы 4601 - 4603)
      msg_id>4600 && msg_id<4604    ?  messages_runtime_custom_indicator[msg_id-4601][m_lang_num] :
      //--- Ошибки времени выполнения (Account 4701 - 4758)
      msg_id>4700 && msg_id<4759    ?  messages_runtime_account[msg_id-4701][m_lang_num]          :
      //--- Ошибки времени выполнения (Индикаторы 4801 - 4812)
      msg_id>4800 && msg_id<4813    ?  messages_runtime_indicator[msg_id-4801][m_lang_num]        :
      //--- Ошибки времени выполнения (Стакан цен 4901 - 4904)
      msg_id>4900 && msg_id<4905    ?  messages_runtime_books[msg_id-4901][m_lang_num]            :
      //--- Ошибки времени выполнения (Файловые операции 5001 - 5027)
      msg_id>5000 && msg_id<5028    ?  messages_runtime_files[msg_id-5001][m_lang_num]            :
      //--- Ошибки времени выполнения (Преобразование строк 5030 - 5044)
      msg_id>5029 && msg_id<5045    ?  messages_runtime_string[msg_id-5030][m_lang_num]           :
      //--- Ошибки времени выполнения (Работа с массивами 5050 - 5063)
      msg_id>5049 && msg_id<5064    ?  messages_runtime_array[msg_id-5050][m_lang_num]            :
      //--- Ошибки времени выполнения (Работа с OpenCL 5100 - 5114)
      msg_id>5099 && msg_id<5115    ?  messages_runtime_opencl[msg_id-5100][m_lang_num]           :
      //--- Ошибки времени выполнения (Работа с WebRequest() 5200 - 5203)
      msg_id>5199 && msg_id<5204    ?  messages_runtime_webrequest[msg_id-5200][m_lang_num]       :
      //--- Ошибки времени выполнения (Работа с сетью (сокетами) 5270 - 5275)
      msg_id>5269 && msg_id<5276    ?  messages_runtime_netsocket[msg_id-5270][m_lang_num]        :
      //--- Ошибки времени выполнения (Пользовательские символы 5300 - 5310)
      msg_id>5299 && msg_id<5311    ?  messages_runtime_custom_symbol[msg_id-5300][m_lang_num]    :
      //--- Ошибки времени выполнения (Экономический календарь 5400 - 5402)
      msg_id>5399 && msg_id<5403    ?  messages_runtime_calendar[msg_id-5400][m_lang_num]         :
      //--- Коды возврата торгового сервера (10004 - 10044)
      msg_id>10003 && msg_id<10045  ?  messages_ts_ret_code[msg_id-10004][m_lang_num]             :
     #else // MQL4
      msg_id>0 && msg_id<10         ?  messages_ts_ret_code_mql4[msg_id][m_lang_num]              :
      msg_id>63 && msg_id<66        ?  messages_ts_ret_code_mql4[msg_id-54][m_lang_num]           :
      msg_id>127 && msg_id<151      ?  messages_ts_ret_code_mql4[msg_id-116][m_lang_num]          :
      msg_id<4000                   ?  messages_ts_ret_code_mql4[26][m_lang_num]                  :
      //--- Ошибки времени выполнения MQL4 (4000 - 4030)
      msg_id<4031                   ?  messages_runtime_4000_4030[msg_id-4000][m_lang_num]        :
      //--- Ошибки времени выполнения MQL4 (4050 - 4075)
      msg_id>4049 && msg_id<4076    ?  messages_runtime_4050_4075[msg_id-4050][m_lang_num]        :
      //--- Ошибки времени выполнения MQL4 (4099 - 4112)
      msg_id>4098 && msg_id<4113    ?  messages_runtime_4099_4112[msg_id-4099][m_lang_num]        :
      //--- Ошибки времени выполнения MQL4 (4200 - 4220)
      msg_id>4199 && msg_id<4221    ?  messages_runtime_4200_4220[msg_id-4200][m_lang_num]        :
      //--- Ошибки времени выполнения MQL4 (4250 - 4266)
      msg_id>4249 && msg_id<4267    ?  messages_runtime_4250_4266[msg_id-4250][m_lang_num]        :
      //--- Ошибки времени выполнения MQL4 (5001 - 5029)
      msg_id>5000 && msg_id<5030    ?  messages_runtime_5001_5029[msg_id-5001][m_lang_num]        :
      //--- Ошибки времени выполнения MQL4 (5200 - 5203)
      msg_id>5199 && msg_id<5204    ?  messages_runtime_5200_5203[msg_id-5200][m_lang_num]        :
     #endif 
      //--- Сообщения библиотеки (ERR_USER_ERROR_FIRST)
      msg_id>ERR_USER_ERROR_FIRST-1 ?  messages_library[msg_id-ERR_USER_ERROR_FIRST][m_lang_num]  : 
      messages_library[MSG_LIB_SYS_ERROR_CODE_OUT_OF_RANGE-ERR_USER_ERROR_FIRST][m_lang_num]
     );
  }
//+------------------------------------------------------------------+

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

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

Осталось дело за малым — найти во всех файлах библиотеки все вхождения строк "TextByLanguage(" и заменить их на "CMessage::Text(", и вписать далее идентификатор сообщения.

Доработка классов библиотеки

Для поиска во всех файлах удобно воспользоваться окном "Поиск в файлах" (Shift+Ctrl+F):


В поле ввода искомой строки ("Найти") вводим "TextByLanguage(", в поле папки для поиска ("В папке") выбираем путь к каталогу библиотеки (у меня это E:\MetaQuotes\MetaTrader 5\MQL5\Include\DoEasy), обязательно ставим флажок "Поиск в подпапках" и нажимаем "Найти".
В итоге, по окончании поиска, во вкладке редактора "Поиск" нам будут выведены пути к файлам, в которых найдена искомая строка.
Осталось открыть каждый из файлов (можно двойным щелчком по строке пути к файлу во вкладке с результатами поиска) и воспользоваться либо просто поиском ( Ctrl+F) опять этой же строки, но уже в каждом отдельном файле, либо поиском с заменой (Ctrl+H) и заменить каждое найденное вхождение строки "TextByLanguage(" на "CMessage::Text(".
В любом случае, после замены нам необходимо ввести вместо текста, находящегося в параметрах TextByLanguage("Этот_текст_заменить","Replace_this_text") на константу идентификатора сообщения. Найти константу просто: нужно выделить русский текст, нажать Ctrl+F (откроется окно поиска), перейти во вкладку с файлом Datas.mqh и нажать в окне поиска "Найти далее". Так как к каждой константе у нас есть комментарий, то будет найден комментарий, который относится к искомой константе. Копируем константу и вводим её в CMessage::Text(НАЙДЕННАЯ_КОНСТАНТА).

Например, в файле BaseObj.mqh у нас найдена строка:

//+------------------------------------------------------------------+
//| Упаковывает ushort-число в переданное long-число                 |
//+------------------------------------------------------------------+
long CBaseObj::UshortToLong(const ushort ushort_value,const uchar index,long &long_value)
  {
   if(index>3)
     {
      ::Print(DFUN,TextByLanguage("Ошибка. Значение \"index\" должно быть в пределах 0 - 3","Error. The \"index\" value must be between 0 - 3"));
      return 0;
     }
   return(long_value |= UshortToByte(ushort_value,index));
  }
//+------------------------------------------------------------------+

После замены она будет выглядеть так:

//+------------------------------------------------------------------+
//| Упаковывает ushort-число в переданное long-число                 |
//+------------------------------------------------------------------+
long CBaseObj::UshortToLong(const ushort ushort_value,const uchar index,long &long_value)
  {
   if(index>3)
     {
      ::Print(DFUN,CMessage::Text(MSG_LIB_SYS_ERROR_INDEX));
      return 0;
     }
   return(long_value |= UshortToByte(ushort_value,index));
  }
//+------------------------------------------------------------------+

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

При попытке компиляции обновлённых файлов библиотеки под MQL4, мы получим несколько ошибок неизвестных констант. Исправим это недоразумение.
Откроем файл \MQL5\Include\DoEasy\ToMQL4.mqh и впишем в него определения неизвестных кодов ошибок MQL5:

//+------------------------------------------------------------------+
//|                                                       ToMQL4.mqh |
//|              Copyright 2017, Artem A. Trishkin, Skype artmedia70 |
//|                         https://www.mql5.com/ru/users/artmedia70 |
//+------------------------------------------------------------------+
#property copyright "Copyright 2017, Artem A. Trishkin, Skype artmedia70"
#property link      "https://www.mql5.com/ru/users/artmedia70"
#property strict
#ifdef __MQL4__
//+------------------------------------------------------------------+
//| Коды ошибок                                                      |
//+------------------------------------------------------------------+
#define ERR_SUCCESS                       (ERR_NO_ERROR)
#define ERR_MARKET_UNKNOWN_SYMBOL         (ERR_UNKNOWN_SYMBOL)
#define ERR_ZEROSIZE_ARRAY                (ERR_ARRAY_INVALID)
#define ERR_MAIL_SEND_FAILED              (ERR_SEND_MAIL_ERROR)
#define ERR_NOTIFICATION_SEND_FAILED      (ERR_NOTIFICATION_ERROR)
#define ERR_FTP_SEND_FAILED               (ERR_FTP_ERROR)
//+------------------------------------------------------------------+

Теперь всё должно компилироваться и под MQL4.

Тест вывода сообщений

Долго не мог придумать что же такое выдумать для наглядного тестирования. В результате пришёл к выводу, что делать-то ничего и не нужно — всё уже сделано. В журнал и так выводятся сообщения. Значит — для того, чтобы проверить правильность их вывода в новом, изменённом варианте хранения и вывода данных, достаточно просто запустить советник из прошлой статьи: \MQL5\Experts\TestDoEasy\Part18\TestDoEasyPart18.mq5.
Сохраним его в новой папке и под новым именем: \MQL5\Experts\TestDoEasy\Part19\TestDoEasyPart19.mq5.
Всё же очень незначительные изменения я в него внёс, но всё касается лишь размеров отслеживаемых изменений и визуального оформления выводимых текстов, поэтому и описывать их тут не будем.

Скомпилируем и запустим советник в тестере в визуальном режиме. В советнике выставлено отслеживание размеров спреда, величины прибыли и средств. Поэтому посмотрим на сообщения об изменении спреда и пересечении его размером величины в 2 пункта. А по увеличению средств открытые позиции закрываются. Обо всём этом, и об открытии/закрытии позиций в журнал должны выводиться соответствующие записи — с ними мы уже знакомы по тестам из прошлых статей. Интерес здесь для нас представляют не сами сообщения как таковые, а правильность вывода этих сообщений, так как они теперь хранятся и выводятся совсем иным образом — все сообщения хранятся в одном месте и выводятся по указанию на их местоположение в базе сообщений.

Итак, смотрим:


Ну что ж. Видим, что все записи о всех событиях у нас выводятся верно, а значит — всё работает так, как задумывалось сделать.

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

Что дальше

Ещё несколько штрихов, и приступим к торговым классам ...

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

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

К содержанию

Статьи этой серии:

Часть 1. Концепция, организация данных
Часть 2. Коллекция исторических ордеров и сделок
Часть 3. Коллекция рыночных ордеров и позиций, организация поиска
Часть 4. Торговые события. Концепция
Часть 5. Классы и коллекция торговых событий. Отправка событий в программу
Часть 6. События на счёте с типом неттинг
Часть 7. События срабатывания StopLimit-ордеров, подготовка функционала для регистрации событий модификации ордеров и позиций
Часть 8. События модификации ордеров и позиций
Часть 9. Совместимость с MQL4 - Подготовка данных
Часть 10. Совместимость с MQL4 - События открытия позиций и активации отложенных ордеров
Часть 11. Совместимость с MQL4 - События закрытия позиций
Часть 12. Класс объекта "аккаунт", коллекция объектов-аккаунтов
Часть 13. События объекта "аккаунт"
Часть 14. Объект "Символ"
Часть 15. Коллекция объектов-символов
Часть 16. События коллекции символов
Часть 17. Интерактивность объектов библиотеки
Часть 18. Интерактивность объекта-аккаунт и любых других объектов библиотеки


Прикрепленные файлы |
MQL5.zip (252.16 KB)
MQL4.zip (252.16 KB)
Парсинг HTML с помощью curl Парсинг HTML с помощью curl

В статье описывается простейшая библиотека с использованием сторонних компонентов для парсинга HTML-кода. Из неё вы узнаете как добраться до данных, которые нальзя получить GET и POST запросами. Мы подберем какой-либо сайт с не слишком объемными страницами и попытаемся получить с него интересную информацию.

Библиотека для простого и быстрого создания программ для MetaTrader (Часть XVIII): Интерактивность объекта-аккаунт и любых других объектов библиотеки Библиотека для простого и быстрого создания программ для MetaTrader (Часть XVIII): Интерактивность объекта-аккаунт и любых других объектов библиотеки

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

Библиотека для простого и быстрого создания программ для MetaTrader (Часть XX): Создание и хранение ресурсов программы Библиотека для простого и быстрого создания программ для MetaTrader (Часть XX): Создание и хранение ресурсов программы

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

Рецепты MQL5 – Стресс-тестирование торговой стратегии с помощью пользовательских символов Рецепты MQL5 – Стресс-тестирование торговой стратегии с помощью пользовательских символов

В статье рассматривается подход по стресс-тестированию торговых стратегий с помощью пользовательских символов. Для этих целей создаётся класс пользовательского символа. С его помощью идёт работа по получению тиковых данных из сторонних источников и изменению свойств символа. По результатам проделанной работы предлагаются варианты изменения торговых условий, в отношении которых проводится тестирование торговой стратегии.