07/11/2024

Почти конструктор для создания советника

 

Почти конструктор для создания советника

С самого начала у меня была цель использовать Стандартную библиотеку. Помню свою первую задачу — это реализовать самый простейший функционал: подключить торговый класс CTrade и выполнить метод Buy или Sell. Стандартная библиотека была выбрана из-за короткого и лаконичного полученного кода. Короткий код ниже, выполненный в виде скрипта, открывает позицию BUY объёмом 1.0 лот:

Постепенно требования росли, я сталкивался с торговыми ошибками почти каждый раз при написании очередного советника. Мне всё больше хотелось написать правильный код и навсегда забыть про эти ошибки. А потом вышла очень значимая статья Какие проверки должен пройти торговый робот перед публикацией в Маркете. К моменту выхода статьи я уже осознавал всю необходимость в надежных функциях контроля за исполнением торговых приказов. С этого момента я стал постепенно обзаводиться проверенными функциями, которые при помощи метода ‘copy->paste‘ можно легко вставить в советник и использовать.

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

ПОМНИТЕ: MQL5 стиль подразумевает, что хендл индикатора создаётся ОДИН РАЗ и делается это, как правило, в OnInit

А также функции получения данных с индикатора. Примерно с версии 2.XXX я начал вести две ветки развития конструктора — обычный процедурный код, и код в виде класса (главная задача класса — это реализация мультивалютных экспертов).

А конструктор развивался — в него постепенно добавлялись самые популярные настройки:

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

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

Для ежедневного использования решено было собрать все самые популярные функции и полный набор входных параметров в советник ‘Trading engine 3.mq5’ — по сути, это готовый советник, который заменяет много рутинной работы. Остаётся под каждый конкретный случай добавить или удалить функции или изменить взаимодействие между блоками кода.

1. Функционал советника после конструктора

Советник созданный конструктором имеет сразу очень много настроек, компонуя которые можно создавать уникальные стратегии. В версии 4.XXX применяются такие правила:

  • используется текущий символ (символ на графике которого запущен советник)
  • Take Profit, Stop Loss и Trailing во входных параметрах задаются в Points. Points — размер пункта текущего инструмента в валюте котировки, например, для пары ‘EURSD’ 1.00055-1.00045=10 points.

Что такое ‘points’ всегда можно увидеть на графике символа, если перетащить инструмент Перекрестие:

Итак, входные параметры советника, который получается после использования конструктора:

  • «Trading settings» — торговые параметры
    • Working timeframe— рабочий таймфрейм. Может отличаться от таймфрейма графика, на котором запущен эксперт. Является таймфреймом, на котором создаётся индикатор (если в индикаторе явно не указан другой таймфрейм). Также используется для отслеживания момента рождения нового бара (для случаев, когда нужно искать торговый сигнал только в момент рождения нового бара или когда нужно запустить Трейлинг только в момент рождения нового бара).
    • Stop Loss — Стоп лосс, если задать 0, то это означает выключить параметр.
    • Take Profit — Тейк профит, если задать 0 , это означает выключить параметр.
    • Trailing on . — два варианта, когда проверять возможность Трейлинга: ‘bar #0 (at every tick)‘ — на каждом тике или ‘bar #1 (on a new bar)‘ — только в момент рождения нового бара.
    • Search signals on . — два варианта, когда проводить поиск торгового сигнала: ‘bar #0 (at every tick)‘ — на каждом тике или ‘bar #1 (on a new bar)‘ — только в момент рождения нового бара.
    • Trailing Stop (min distance from price to Stop Loss) — Трейлинг стоп, минимальное расстояние между ценой и Стоп лосс позиции. Трейлинг начинает работать только если позиция прибыльная и цена отошла от цены открытия на расстояние ‘Trailing Stop’ + ‘Trailing Step’. Как работает трейлинг показано в картинках в коде TrailingStop.
    • Trailing Step — шаг трейлинга.
    • Money management lot: Lot OR Risk — выбор системы расчета лота. Лот может быть как постоянный (‘ Money management‘ установить в ‘Constant lot‘ и задать размер лота в ‘ The value for «Money management«‘) и динамический — в процентах риска на сделку (‘ Money management‘ установить в ‘Risk in percent for a deal‘ и задать процент риска в ‘ The value for «Money management«‘). Также можно задать постоянный лот равный минимальному лоту — ‘ Money management‘ установить в ‘Lots Min‘.
    • The value for «Money management» — значение для ‘ Money management
    • Trade mode: — выбор режима торговли. Может быть ‘Allowed only BUY positions‘ (разрешается открывать только позиции BUY), ‘Allowed only SELL positions‘ (разрешается открывать только позиции SELL) и ‘Allowed BUY and SELL positions‘ (разрешается открывать и позиции BUY и позиции SELL)
    • DEMA: averaging period
    • DEMA: horizontal shift
    • DEMA: type of price
    • Use time control — флаг, вкл/выкл Time control
    • Start Hour — часы начала периода
    • Start Minute — минуты начала периода
    • End Hour — часы окончания периода
    • End Minute — минуты окончания периода
    • Pending: Expiration, in minutes (‘0’ -> OFF) — время жизни отложенного ордера (‘0’ означает, что параметр выключен).
    • Pending: Indent — отступ отложенного ордера от текущей цены (используется в случае, когда цена отложенного ордера не задаётся явно)
    • Pending: Maximum spread (‘0’ -> OFF) — максимальный спред ( ‘0’ означает, что параметр выключен). Если текущий спред больше заданного, то отложенный ордер не выставляется (советник ждёт кога спред уменьшится)
    • Pending: Only one pending — флаг, вкл/выкл, в рынке разрешён только один отложенный ордер
    • Pending: Reverse pending type — флаг, вкл/выкл, реверс отложенного ордера
    • Pending: New pending -> delete previous ones — если есть приказ на выставление отложенного ордера, то предварительно удаляются все остальные отложенные ордера
    • Positions: Only one — флаг, вкл/выкл, в рынке разрешается иметь только одну позицию
    • Positions: Reverse — флаг, вкл/выкл, реверс торгового приказа
    • Positions: Close opposite — флаг, вкл/выкл, если есть торговый приказ, предварительно закрываются все позиции и только потом исполняется приказ
    • Print log — флаг, вкл/выкл, выводить расширенную информацию по операциям и ошибкам
    • Coefficient (if Freeze==0 Or StopsLevels==0) — коэффициент, учитывающий Стоп левел
    • Deviation — заданное проскальзывание
    • Magic number — уникальный идентификатор советника

    2. Общий алгоритм конструктора

    На глобальном программном уровне (в «шапке» советника) объявляется массив ‘SPosition’ ( ‘SPosition’ — имя массива) , состоящий из структур ‘STRUCT_POSITION’. При старте этот массив имеет нулевой размер, после отработки торгового сигнала массив также возвращается в нулевой размер.

    Из OnTick вызывается функция ‘SearchTradingSignals‘ — при наличии сигнала (сигнал получаем, если в рынке нет открытых позиций) эта функция формирует торговый приказ (создаёт для каждого торгового приказа одну структуру ‘STRUCT_POSITION’ в массиве. Также в OnTick проверяется наличие торгового приказа — проверяется размер массива ‘SPosition: если он больше нуля, значит есть торговый приказ и этот торговый приказ пересылается на выполнение в ‘OpenBuy‘ или в ‘OpenSell‘. Контроль за исполнением торгового приказа осуществляется в OnTradeTransaction :

    general algorithm (simple)

    Рис. 2. Общий алгоритм (простой)

    Всегда подразумевается, что советник работает по текущему символу — то есть по символу на чей график установлен советник. Пример: советник размещён на графике ‘USDPLN’, значит, советник работает по символу ‘USDPLN’.

    2.1. Структура ‘STRUCT_POSITION’

    Данная структура — это сердце советника, она выполняет сразу две роли: в структуре есть поля, в которые записывается торговый приказ (запись проводится в ‘ SearchTradingSignals ‘) и в структуре есть поля для контроля за выполнением торгового приказа (контроль проводится в OnTradeTransaction ).

    Одни поля отвечают за торговый приказ, а другие поля — за контроль над исполнением торгового приказа. Cтруктура содержит конструктор — специальную функцию ‘ STRUCT_POSITION() ‘, которая вызывается при создании объекта структуры и инициализирует элементы структуры.

    Поля торгового приказа:

    • pos_type — тип позиции, которую нужно открыть (может быть ‘POSITION_TYPE_BUY’ или ‘POSITION_TYPE_SELL’)
    • volume — объем позиции. Если указан объём ‘0.0’, значит объём позиции будет браться из группы входных параметров ‘Position size management (lot calculation)’
    • lot_coefficient — если этот коэффициент больше ‘0.0’, значит, объём позиции будет умножен на этот коэффициент

    Поля контроля над исполнением торгового приказа

    • waiting_transaction — флаг означающий, что торговый приказ выполнен успешно и необходимо ждать подтверждения
    • waiting_order_ticket — номер ордера, который получен при выполнения торгового приказа
    • transaction_confirmed — флаг отмечающий, что выполнение торгового приказа подтверждено

    После поднятия флага в поле ‘transaction_confirmed‘ торговый приказ удаляется из структуры. Таким образом, если в работе советника нет торгового приказа, структура имеет нулевой размер. Подробнее про поля структуры и про контроль в главе ‘Ловим транзакцию — упрощенный код We catch the transaction’.

    Почему именно такой алгоритм

    Казалось бы, достаточно проверить метод Buy на возврат ‘true‘ или ‘false‘ и в случае ‘true‘ решить, что торговый приказ выполнен. И во многих случаях такой подход сработает, но встречаются моменты, когда возврат ‘true‘ не дает гарантии результата, о чём, кстати, говорится в документации к методам Buy и Sell:

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

    А окончательное и точное подтверждение об выполнении торговой операции может служить наличие записи в торговой истории. Поэтому и был выбран такой алгоритм: при успешном выполнении метода проверяем ResultDeal (тикет сделки), проверяем ResultRetcode (код результата выполнения запроса) и запоминаем ResultOrder (тикет ордера). А тикет ордера отлавливаем в OnTradeTransaction ).

    3. Добавляем стандартный индикатор — работа с файлом ‘Indicators Code.mq5’

    Для удобства работы готовые блоки кода (объявление переменный для хранения хендлов, входные параметры, создание хендлов) собраны в советнике ‘Indicators Code.mq5’. Входные параметры индикаторов и п еременные для хранения хендлов расположены в «шапке» советника, создание хендлов, как и полагается, прописано в OnInit. Нюанс: имена переменных для хранения хендлов формируются по следующему шаблону: ‘handle_’ + ‘индикатор’, например ‘handle_iStdDev’. Вся работа с ‘Indicators Code.mq5’ сводится к операциям ‘copy-paste’.

    ПОМНИТЕ: MQL5 стиль подразумевает, что хендл индикатора создаётся ОДИН РАЗ и делается это (как правило) в OnInit

    3.1. Пример добавления индикатора ‘iRVI’ (Relative Vigor Index, RVI)

    Создадим советник ‘Add indicator.mq5’. В редакторе MetaEditor вызываем ‘MQL Wizard’, например, кликом по кнопке New, и выбираем ‘Expert Advisor (template)’

    Expert Advisor (template)

    Рис. 3. ‘MQL Wizard’ -> ‘Expert Advisor (template)’

    На следующем шаге я настоятельно рекомендую добавить хотя бы один входной параметр

    Expert Advisor (template)

    Рис. 4. ‘Expert Advisor (template)’ -> ‘Add parameter’

    Такой приём автоматически добавляет в код строки для блока входных параметров :

    ‘MQL Wizard’ создал пустой советник, теперь добавим в него индикатор ‘iRVI’ (Relative Vigor Index, RVI). В ‘Indicators Code.mq5’ проводим поиск ‘ handle_iRVI’ (поиск вызывается через ‘ctrl’ + ‘F’). Поиск находит переменную, в которой хранится хендл:

    iRVI

    Рис. 5. handle RVI

    Найденную строку копируем и вставляем в советник ‘Add indicator’ в шапку :

    Продолжаем поиск и находим блок создания хендла:

    iRVI

    Рис. 6. handle iRVI

    Найденные строки копируем и вставляем в советник ‘Add indicator’ в OnInit :

    Теперь добавим входные параметры индикатора. В ‘Indicators Code.mq5’ делаем клик средней кнопкой мышки, например, на ‘ Inp_RVI_period’ — нас перебросит сразу в блок входных параметров:

    iRVI

    Рис. 7. handle iRVI

    Копируем строки и вставляем во входные параметры :

    Если скомпилировать, то получим ошибки: компилятор ругается на ‘m_symbol‘ и на ‘m_init_error‘. И это правильно — так как эти переменные есть в коде, который получаем после работы конструктора, а советник ‘Add indicator’ создан исключительно для демонстрации работы с файлом ‘Indicators Code.mq5’.

    4. Добавляем пользовательский индикатор

    Добавим пользовательский индикатор MA on DeMarker. Во-первых — это пользовательский индикатор, во-вторых, этот индикатора использует group. По аналогии с предыдущим разделом создадим советник ‘ Add custom indicator’. После этого нужно из пользовательского индикатора скопировать входные параметры и вставить в советник:

    Найдём в файле ‘Indicators Code.mq5’ переменную ‘handle_iCustom’ — переменную для хранения хендла пользовательского индикатора и вставим в советник:

    Найдём в файле ‘Indicators Code.mq5’ в OnInit() блок создания хендла пользовательского индикатора и вставим в советник:

    Здесь придётся потрудиться. Нужно прописать таймфрейм (‘InpWorkingPeriod’), путь к индикатору (предполагаем, что индикатор лежит в корне папки ‘Indicators’) и входные параметры:

    5. Ловим транзакцию — упрощенный код We catch the transaction

    ВНИМАНИЕ: Это советник — упрощенная версия. Многие функции имеет сокращенный код по сравнению с полноценным конструктором

    Если в рынке нет позиций открытых данным советником, то записываем торговый приказ на открытие позиции BUY. Подтверждение, что позиция открыта, распечатываем из OnTradeTransaction и из OnTick . Поиск и запись торгового приказа в функции ‘SearchTradingSignals‘:

    Если в рынке нет позиций открытых советником и если размер массива ‘SPosition’ равен нулю, увеличиваем размер массива на единицу — таким образом создаём один объект структуры ‘STRUCT_POSITION’, что в свою очередь вызывает конструктор ‘STRUCT_POSITION()’. После вызова конструктора элементы структуры инициализированы (например, volume — объем позиции стоит в ‘0.0’ — значит объём позиции будет браться из группы входных параметров ‘Position size management (lot calculation)’). Остаётся в структуру записать только тип торгового приказа — в данном случае этот приказ можно прочитать как: «Открыть позицию BUY».

    После записи торгового приказа массив ‘SPosition’ состоит из одной структуры и элементы этой структуры имеют такие значения:

    Элемент Значение Примечание
    pos_type POSITION_TYPE_BUY записан в ‘ SearchTradingSignals
    volume 0.0 проинициализирован в конструкторе структуры
    lot_coefficient 0.0 проинициализирован в конструкторе структуры
    waiting_transaction false проинициализирован в конструкторе структуры
    waiting_order_ticket 0 проинициализирован в конструкторе структуры
    transaction_confirmed false проинициализирован в конструкторе структуры

    5.1. На новом тике попадаем в OnTick

    Общий принцип действия в OnTick:

    В начале OnTick проверяем размер массива ‘SPosition’ (это массив структур ‘STRUCT_POSITION’). Если размер массива больше нуля — начинаем обход к нулю, при этом доступно два сценария:

    • если у структуры флаг ‘waiting_transaction‘ в ‘true‘ (что означает была выполнена подготовка торгового приказа и необходимо ждать подтверждения), проверяем флаг ‘transaction_confirmed
      • если он ‘false‘, значит, транзакция ещё не подтверждена (например, такое может быть, если торговый приказ отдан, поступил новый тик, а в OnTradeTransaction ещё нет подтверждения). Тогда мы распечатывает сообщение об этом и выходим по return — ждём нового тика в надежде, что на новом тике информация обновится
      • если он ‘true‘, значит, транзакция подтверждена — тогда мы удаляем из массива эту структуру и выходим по return

      если у структуры флаг ‘waiting_transaction‘ в ‘false‘ (что означает — этот торговый приказ только-что был записан и ещё не выполнялся) — взводим флаг ‘waiting_transaction‘ и переправляем приказ в ‘OpenPosition‘. Заметьте, что блок кода можно было бы упростить до вида

      Продолжаем отслеживание, напомню блок кода:

      Только что торговый приказ был записан в структуру (в функции ‘SearchTradingSignals‘) и флаг ‘waiting_transaction‘ стоит в ‘false‘ — значит взводим флаг ‘waiting_transaction‘ в ‘true‘ и передаём в функцию ‘OpenPosition ‘ параметр ‘i’ — это порядковый номер структуры в массиве. ‘OpenPosition‘. Так как тип торгового приказа у нас ‘POSITION_TYPE_BUY’ — передаём порядковый номер структуры в функцию ‘OpenBuy‘.

      5.2. Функция ‘OpenBuy’

      Задача функции — пройти предварительные проверки, отослать торговый запрос на открытие позиции BUY и отследить сразу результат.

      Первая проверка — проверка SYMBOL_VOLUME_LIMIT

      SYMBOL_VOLUME_LIMIT Максимально допустимый для данного символа совокупный объем открытой позиции и отложенных ордеров в одном направлении (покупка или продажа). Например, при ограничении в 5 лотов можно иметь открытую позицию на покупку объемом 5 лотов и выставить отложенный ордер Sell Limit объемом 5 лотов. Но при этом нельзя выставить отложенный ордер Buy Limit (поскольку совокупный объем в одном направлении превысит ограничение) или выставить Sell Limit объемом более 5 лотов.

      Если проверку не прошли, то удаляем элемент структуры из массива ‘SPosition’.

      Получаем размер свободной маржи, которая останется после торговой операции (FreeMarginCheck), размер маржи, необходимой для торговой операции (MarginCheck). После этого защищаемся — всегда страхуемся и оставляем после операции сумму как минимум равной FreeMarginCheck:

      Если проверку не прошли — распечатываем переменную ‘ free_margin_check‘ и удаляем элемент структуры из массива ‘SPosition’.

      Проверка номер три — bool результат операции Buy

      Если метод Buy возвратил результат ‘false‘ — распечатываем ошибку и записываем в поле ‘waiting_transaction‘ значение ‘false‘ (самая распространённая причина — ошибка 10004, requote) — таким образом на новом тике будет предпринята попытка снова открыть позицию BUY. Если же результат ‘true‘ (ниже показан блок кода, когда метод Buy возвратил результат ‘ true ‘ )

      то проверяем ResultDeal (тикет сделки).

      Если тикет сделки равен нулю — проверяем ResultRetcode (код результата выполнения запроса). Получили код возврата ‘10009’ (например торговый приказ был отослан во внешнюю торговую систему, например на Биржу и поэтому тикет сделки равен нулю) — значит в поле ‘waiting_transaction‘ записываем ‘true‘, а в поле ‘waiting_order_ticket‘ записываем ResultOrder (тикет ордера), иначе (код возврата не равен ‘10009’) — в поле ‘ waiting_transaction ‘ записываем ‘ false ‘ и распечатываем сообщение об ошибке.

      Если же тикет сделки не равен нулю (например исполнение происходит на этом торговом сервере), то проводим аналогичные проверки кода возврата и аналогично записываем значения в поля ‘ waiting_transaction ‘ и ‘ waiting_order_ticket ‘.

      5.3. OnTradeTransaction

      В случае, когда торговый приказ был отослан удачно, необходимо дождаться подтверждения о том, что сделка прошла и она записана в торговую историю. В OnTradeTransaction работаем с переменной ‘trans‘ (структура имеющая тип MqlTradeTransaction). В структуре нас интересует только два поля — ‘deal‘ и ‘type‘ :

      Как только в OnTradeTransaction словили транзакцию TRADE_TRANSACTION_DEAL_ADD (добавление сделки в историю), осуществляем проверку : пытаемся выбрать сделку в истории через HistoryDealSelect — если выбрать сделку не удалось, печатаем ошибку, если же сделка существует в торговой истории, то начинаем в цикле обход массива ‘SPosition’. В цикле смотрим только те структуры, у которых поле ‘waiting_transaction‘ стоит в ‘true‘ и поле ‘waiting_order_ticket‘ равно тикету ордера выбранной нами сделки . Если обнаружено совпадение, записываем с поле ‘transaction_confirmed‘ значение ‘true‘ — это означает, что торговый приказ выполнен и подтвержден.

      На новом тике попадаем в OnTick и там структура, у которой стоит ‘true‘ в поле ‘transaction_confirmed‘, будет удалена из массива ‘SPosition’. Таким образом, был выдан торговый приказ и этот торговый приказ был отслежен до момента, когда он появится в торговой истории.

      6. Создаём советник (сигналы на открытие позиций) при помощи конструктора

      Перед созданием любого советника нужно продумать саму торговую стратегию. Рассмотрим простую стратегию по индикатору i DEMA ( Double Exponential Moving Average, DEMA) — эта стратегия по умолчанию прописана в конструкторе. Сигнал на открытие позиции ищем только в момент рождения нового бара, а сам торговый сигнал — это индикатор, который последовательно повышается или понижается:

      DEMA Strategy

      Рис. 8. DEMA Strategy

      Помните: любую стратегию можно сильно видоизменить, если настраивать параметры. Например можно оставить Тейк профит и Стоп лосс, но выключить Трейлинг. Или наоборот: выключить Тейк профит и Стоп лосс, а Трейлинг оставить. Или ограничить в какую сторону торговать — разрешить только BUY или только SELL. А можно включить ‘Time control‘ и ограничить торговлю в ночные часы или наоборот настроить торговлю только в ночные часы. Также сильно можно изменить торговую систему настраивая параметры из группы ‘Additional features‘.

      В общем костяк торговой стратегии строится в функции ‘SearchTradingSignals‘, а все остальные параметры — это «прощупывание» рынка в поисках оптимальных подходов.

      Итак, создаём новый файл — заготовку советника (выполните шаги обозначенные на рисунках 3 и 4). На шаге 4 необходимо дать уникальное имя советнику — пусть это будет ‘iDEMA Full EA.mq5’. Получили вот такую заготовку:

      Теперь копируем весь код из файла ‘Trading engine 3.mq5’ и вставляем вместо строк . Нужно отредактировать «шапку советника». После операции вставки получилась такая «шапка»:

      Приводим «шапку» в такой вид:

      Если скомпилировать — не будет ни одной ошибки. Полученный советник даже сможет торговать.

      6.1. Функция ‘SearchTradingSignals’

      Это самая главная функция, которая отвечает за проверку наличия торговых приказов. Рассмотрим эту функцию по блокам.

      Не более одной позиции на баре:

      Проверка торгового временного диапазона:

      Получение данных с индикатора. Данные с индикатора получаем в массив ‘dema‘, которому при помощи ArraySetAsSeries устанавливается обратный порядок индексации (элемент массива [0] будет соответствовать самому правому бару на графике). Данные получаем через пользовательскую функцию ‘iGetArray’:

      Сигнал на открытие позиции BUY. Если нужно (переменная ‘ InpReverse ‘ хранит значение входного параметра ‘Positions: Reverse’) — то торговый сигнал будет перевернут. Если есть ограничение в какую сторону торговать (переменная ‘ InpTradeMode ‘ хранит значение входного параметра ‘Trade mode:‘), то это ограничение будет учтено:

      Блок кода для сигнала SELL аналогичен.

      7. Создаём советник (сигналы на размещение отложенного ордера) при помощи конструктора

      Имя советника будет ‘iDEMA Full EA Pending.mq5’ — для этого откройте советник ‘iDEMA Full EA.mq5’ и сохраните его под новым именем.

      Сначала всегда разрабатывается торговая стратегия и только потом, под эту стратегию, реализуется код. Немного изменим стратегию, которая использовалась в главе 6. Создаём советник (сигналы на открытие позиций) при помощи конструктора — вместо сигнала на открытие позиции BUY будет сигнал на размещение отложенного ордера Buy stop, а вместо сигнала на открытие позиции SELL — отложенный ордер Sell stop. Для отложенных ордеров будут использоваться такие параметры:

      • Pending: Expiration, in minutes (‘0’ -> OFF) — время жизни отложенного ордера (‘0’ означает, что параметр выключен) -> 600
      • Pending: Indent — отступ отложенного ордера от текущей цены (используется в случае, когда цена отложенного ордера не задаётся явно) -> 50
      • Pending: Maximum spread (‘0’ -> OFF) — максимальный спред ( ‘0’ означает, что параметр выключен). Если текущий спред больше заданного, то отложенный ордер не выставляется (советник ждёт кога спред уменьшится) -> 12
      • Pending: Only one pending — флаг, вкл/выкл, в рынке разрешён только один отложенный ордер -> true
      • Pending: Reverse pending type — флаг, вкл/выкл, реверс отложенного ордера -> false
      • Pending: New pending -> delete previous ones — если есть приказ на выставление отложенного ордера, предварительно удаляются все остальные отложенные ордера -> true

      Функция ‘SearchTradingSignals‘ примет такой вид:

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

      Мы получили торговый сигнал, но он сработал (отложенный ордер был размещён) только тогда, когда спред стал ниже заданного:

      iDEMA Full EA Pending

      Рис. 9. iDEMA Full EA Pending

      Файлы, прикрепленные к статье:

      Название Тип файла Описание
      Indicators Code Советник Содержит переменные для хранения хендлов, входные параметры индикаторов, блоки создания индикаторов
      Add indicator.mq5 Советник Пример работы с файлом ‘Add indicator.mq5’ — добавляем стандартный индикатор
      Add custom indicator.mq5 Советник Пример добавления пользовательского индикатора
      Trading engine 4.mq5 Советник Конструктор
      iDEMA Full EA.mq5 Советник Советник созданный при помощи конструктора — сигналы на открытие позиций
      iDEMA Full EA Pending.mq5 Советник Советник созданный при помощи конструктора — сигналы на размещение отложенных ордеров

      Заключение

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

      Источник https://www.mql5.com/ru/articles/9717

      Источник

      Источник

      Источник