Типичные ошибки и способы их устранения при работе с торговым окружением - страница 2

 

fxsaber:

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

Правильный вариант на простом примере...

Список ордеров, как и список поз, не обновляется мгновенно. imho без Sleep-костыля не обойтись.

Наверно более правильно таки через OnTradeTransaction

 
Aleksey Lebedev:

Список ордеров, как и список поз, не обновляется мгновенно. imho без Sleep-костыля не обойтись.

Наверно более правильно таки через OnTradeTransaction

Если есть проблема ожидания обновления торгового окружения, то чем поможет Sleep? Он либо поможет, либо не поможет.

Значит подход должен быть с другой стороны: отправили приказ на открытие позиции или установку отложенного ордера - нужно дождаться результата, и не отправлять больше никаких приказов на открытие или установку. Значит нужен флаг, которым мы сами управляем, а не доверяем Sleep'у, который лишь даёт задержку выполнения программы, но не проверяет результат торгового запроса, отправленный самой программой, которая и должна знать что ей после этого делать - ставить флаг и работать уже по логике ожидания результата. Дождались результата - сняли флаг.

 
Artyom Trishkin:

Вопрос: что будет, если после отсылки торгового приказа до следующего тика маркет-ордер не будет выставлен сервером?

Будет ровно то же, что и на MT4 - если ничего нет, то это считано не будет.


Можно говорить о нескольких причинах появления такого торгового приказа

  1. Сторонние OrderSend или OrderSendAsync - не из программы, в которой считываем торговое окружение. Может даже не из того Терминала, в котором запущена программа. В таком случае ничего сделать нельзя. Все ровно так же, как в MT4 при таких ситуациях.
  2. Свои OrderSend или OrderSendAsync - запущены из программы, в которой считывается и торговое окружение. В случае с OrderSend все однозначно, т.к. OrderSend закончит свое выполнение с четким результатом. В случае же с OrderSendAsync можно поступить двояко - передать данные следующим событиям согласно первой парадигме, либо сделать OrdersAsyncWait() (кода у меня нет), как это делается при симуляции штатной асинхронной передачи данных в MT4 (реализация через несколько торговых потоков).
Наверное, стоит несколько слов сказать об OrderSendAsync в MT4. Там на любом этапе выполнения программы можно видеть занятость соответствующего торгового потока и чем именно он занят. В этом смысле такая кастомная асинхронность в MT4 дает гораздо больше возможностей, чем штатная в MT5. Но в MT4 она реализовывается через запусков "клиентов" на каждом чарте, т.е. дорого. В MT5 возможно написание такого же функционала и даже без множества чартов - запуск скрипта на OBJ_CHART-объекте, но там будет все же небольшая задержка. Т.е. чуть-чуть OrderSendAsyncCustom проиграет по скорости выполнения штатной OrderSendAsync, но это все равно будет гораздо быстрее OrderSend + бонусом все преимущества кастомной реализации.
 
Aleksey Lebedev:

Список ордеров, как и список поз, не обновляется мгновенно. imho без Sleep-костыля не обойтись.

Наверно более правильно таки через OnTradeTransaction

MqlTradeTransaction может понадобиться только при выборе соответствующей парадигмы при работе с OrderSendAsync. В остальных случаях OnTradeTransaction == OnTrade по смыслу и играет роль не больше, чем OnTick или OnTimer.


Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий

Типичные ошибки и способы их устранения при работе с торговым окружением

fxsaber, 2018.02.19 22:36

Есть две парадигмы работы с торговым окружением, написания советников.

  1. Событийные входы (OnTick, OnTimer и т.д.) зависят друг от друга. Есть информация, которую ОБЯЗАТЕЛЬНО (не для ускорения, вроде кеша, а для работоспособности) нужно иметь между событиями. Например, нужно сохранить результат OrderSendAsync и использовать его в OnTradeTransaction. Кеши - это НЕ обязательная информация и используются только для ускорения. Поэтому их не учитываем сразу.
  2. Событийные входы (OnTick, OnTimer и т.д.) НЕ зависят друг от друга. Каждый вход с чистого листа. Примерно, как Скрипт, который Вы запускаете самостоятельно на каждое событие.

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

 
fxsaber:

Будет ровно то же, что и на MT4 - если ничего нет, то это считано не будет.

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

Логика должна быть в советнике примерно такой:

  1.  Получили сигнал на открытие позиции или установку отложенного ордера
  2. Проверили количество ордеров/позиций, не подходит для открытия новой - выход (к п.1)
  3.  Проверили флаг ожидания ответа сервера:
    1. Флаг стоит - выход (к п.1)
    2. Флаг опущен - идём дальше
  4. Флаг ожидания опущен - отправляем торговый приказ (количество попыток ограничено) и проверяем код возврата
    1. Приказ выполнен - ставим флаг ожидания
    2. Приказ не выполнен - вызываем функцию корректировки торгового приказа и идём к пп.4
  5. Флаг ожидания поднят - проверяем изменение торгового окружения
    1. Торговое окружение не изменилось - выход (к п.1)
    2. Торговое окружение изменилось - отложенный ордер выставлен или открыта позиция - снимаем флаг ожидания и выход (к п.1)
 
Artyom Trishkin:

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

Хорошо бы прочесть полностью пост.

Логика должна быть в советнике примерно такой:

  1.  Получили сигнал на открытие позиции или установку отложенного ордера
  2. Проверили количество ордеров/позиций, не подходит для открытия новой - выход (к п.1)
  3.  Проверили флаг ожидания ответа сервера:
    1. Флаг стоит - выход (к п.1)
    2. Флаг опущен - идём дальше
  4. Флаг ожидания опущен - отправляем торговый приказ (количество попыток ограничено) и проверяем код возврата
    1. Приказ выполнен - ставим флаг ожидания
    2. Приказ не выполнен - вызываем функцию корректировки торгового приказа и идём к пп.4
  5. Флаг ожидания поднят - проверяем изменение торгового окружения
    1. Торговое окружение не изменилось - выход (к п.1)
    2. Торговое окружение изменилось - отложенный ордер выставлен или открыта позиция - снимаем флаг ожидания и выход (к п.1)

Флаг ожидания возможен только для второго случая и OrderSendAsync. Для OrderSend флаг ожидания совсем не нужен. OrderSendAsync без флага ожидания - OrdersAsyncWait().

Любую теорию можно проверить на практике

Руководствуюсь практическими результатами.
 
fxsaber:

Хорошо бы прочесть полностью пост.

Флаг ожидания возможен только для второго случая и OrderSendAsync. Для OrderSend флаг ожидания совсем не нужен. OrderSendAsync без флага ожидания - OrdersAsyncWait().

Любую теорию можно проверить на практике

Руководствуюсь практическими результатами.

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

 
Artyom Trishkin:

Ну я и писал для асинхронного режима.

Развернутый ответ был дан изначально.

 
fxsaber:

Развернутый ответ был дан изначально.

Плохо наверное его прочитал :)

Не увидел в нём шагов для обхода ошибки множественных открытий. Лишь общие "парадигмы" ;)

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

Думать нужно как лучше будет.

 
Artyom Trishkin:

флаг проверяется в функции (обёртке) открытия позиций/установки отложенных ордеров. А может и в функции отслеживания сигналов.

Мне гораздо больше нравится решение через OrdersAsyncWait(), когда выход из On-функции осуществляется всегда без подвешенного состояния. Тогда следующее считывание торгового окружения с чистого листа максимально актуально.

Использование OrderSendAsync всегда должно быть целесообразным. Единственная ситуация, где это имеет место быть - по одному сигналу отправка нескольких (> 1) независимых друг от друга торговых приказов. Поэтому во всех остальных случаях городить OrderSendAsync никогда не имеет смысла.


ЗЫ Есть отдельная тема, где OrderSendAsync очень актуальна - мультисоветники: несколько независимых ТС в одном советнике. Там уже OrderSend подходит редко и даже OrderAsyncWait( const string Symb ) не годится, поскольку никакие Sleep недопустимы в принципе.