Нулевой входной параметр ChartID в некоторых функциях не вызывает пересчет значений. Если нужны актуальные данные текущего чарта, нужно использовать полноценный ID.
Если считать, что это штатное поведение MT5, а не особенности хака брокера, то
ORDER_STATE_PARTIAL у исторических ордеров не бывает.
Исполненнные ордера всегда имеют статус ORDER_STATE_FILLED.
При частичном исполнении создаются соответствующие новые маркет ордера торговым сервером (ORDER_REASON_CLIENT - даже если исходный ордер выставлен автоматом(EXPERT)).
Старый живой ордер (тикет не изменяется) остается висеть с уменьшенным объемом (ORDER_VOLUME_CURRENT).
Старый живой ордер при этом получает статус ORDER_STATE_PARTIAL. Фактически, этот флаг является результатом сравнения ORDER_VOLUME_CURRENT и ORDER_VOLUME_INITIAL.
Все открываемые позиции получают ID == OrderTicket. Где OrderTicket - тикеты, порождаемые торговым сервером.
Торговая сделка всегда имеет ровно один исторический ордер и его статус ORDER_STATE_FILLED.
Каждый исполненный исторический ордер имеет ровно одну сделку.
У любого исполненного ордера ORDER_VOLUME_INITIAL равен объему, на который он исполнился. Т.е. даже исходный раздербаненный ордер после полного исполнения имеет ORDER_VOLUME_INITITAL равный объему порожденной им сделки.
Время исходного ордера (который частично исполнялся) не меняется и не равно времени его сделки.
В исторической таблице идет сортировка по времени ордеров (ORDER_TIME_SETUP), не сделок. Поэтому если делать HistorySelect от DEAL_TIME, можно не получить в историческую таблицу соответствующий ордер.
HistorySelectByPosition всегда возвращает необходимое множество сделок/ордеров.
Для любой торговой сделки можно вычислить величину проскальзывания.
Недостатки
Не хватает ORDER_REASON_PARTIAL, DEAL_REASON_PARTIAL и POSITION_REASON_PARTIAL. При этом в соответствующих перечислениях эти флаги должны быть помещены сразу после REASON_EXPERT.
Соответствующие маркет-ордера при частичном исполнении лимитных ордеров по своей природе могут иметь отрицательное проскальзывание. Похоже, это ошибка только в типе ордеров и на самом деле маркет-ордера нет - создается только внутри MT5 и не идет наружу.
(не уверен, проверить сложно,по аналогии с частичным закрытием позиций)
Это все работает так:
1) отложенный ордер сработал частично - открылась позиция с Position_ID = Order_Ticket1
2) остаток ордера формируется в новый ордер Order_Ticket2 и ждет своего исполнения, новый Order_Ticket2 != Order_Ticket1, так как не может быть 2 ордера в истории с одинаковыми Order_Ticket
3) остаток ордера исполнился - открылась позиция с Position_ID = Order_Ticket2
в истории два ордера в терминале две позиции, все соответствует
Открываю руками BUY-позицию на двух торговых демо-серверах
RoboForex-MetaTrader 5
2018.02.13 00:02:08.424 '8520459': market buy 1.00 GBPUSD
2018.02.13 00:02:10.101 '8520459': accepted market buy 1.00 GBPUSD
2018.02.13 00:02:10.101 '8520459': deal #90389019 buy 1.00 GBPUSD at 1.38387 done (based on order #107426544)
2018.02.13 00:02:10.101 '8520459': order #107426544 buy 1.00 / 1.00 GBPUSD at 1.38387 done in 1683.949 ms
FXOpen-MT5
2018.02.13 00:00:25.780 '18000903': market buy 1.00 GBPUSD
2018.02.13 00:00:25.912 '18000903': accepted market buy 1.00 GBPUSD
2018.02.13 00:00:25.922 '18000903': market buy 1.00 GBPUSD placed for execution
2018.02.13 00:00:25.942 '18000903': order #896454 buy 1.00 / 1.00 GBPUSD at market done in 154.252 ms
2018.02.13 00:00:25.942 '18000903': deal #80559 buy 1.00 GBPUSD at 1.38387 done (based on order #896454)
Строки одного цвета обозначают одно и то же. Однако, хорошо видно, что они идут в разных очередностях. У Робо сообщение о выполнении приказа приходит после выполнения сделки. А у опенов - ДО! По этой причине OrderSend возвращает удачу, но сделки еще нет. Т.е. получаем несинхронизированность OrderSend с историей
Если ордер отправдяется во внешнюю торговую систему, то торговый сервер MetaTrader 5 не ждет ответа от неё и сразу возвращает результат запроса как "ордер размещен". По этой причине OrderSend всегда вернет deal=0, так как информации о совершенной сделке еще нет. Ловите её в OnTrade или OnTradeTransaction.
OrderSend - отправил ордер на совершение рыночной сделки. Ордер выставлен - для этого надо ознакомиться с Result.order. А вот со сделку(и) никто не дожидается - их может быть много и общее время их исполнения, вообще то не определено.
Зависит от конкретной реализации вывода на стороне брокера. В общем случае не определено.
Поэтому очень рекомендую в качестве теста своего кода использовать и демо-счет на FXOpen-MT5, т.к. он стоит совсем особняком, по сравнению с другими демо.
Например, предлагаю попробовать написать на MQL5 скрипт с такой торговой логикой (MQL4-стиль только для быстрого показа смысла)
в MT5 все совсем не в порядке. Пример, показывающий проблему
// Пример неправильного считывания торгового окружения на каждом тике// Скрипт эмулирует два тика ТС, которая должна открыть одну позицию, если ее нет.#include <Trade/Trade.mqh>
// Возвращает количество позиций по символуint GetAmountPositions( conststring Symb )
{
int Res = 0;
// Этот MQL5-код с ошибкойfor (int i = PositionsTotal() - 1; i >= 0; i--)
if (PositionGetSymbol(i) == Symb)
Res++;
/*
// В MT4 такой код выполняется без ошибки
for (int i = OrdersTotal() - 1; i >= 0; i--)
if (OrderSelect(i, SELECT_BY_POS) && (OrderType() <= OP_SELL) && (OrderSymbol() == Symb))
Res++;
*/return(Res);
}
// Пример OnTickvoid ExampleOnTick()
{
static CTrade Trade;
// Если нет позиции, открываемif (!GetAmountPositions(_Symbol))
Trade.Buy(1);
}
// Эмуляция прихода двух Tick-событийvoidOnStart()
{
ExampleOnTick();
Sleep(10); // Между двумя тиками ~10 мс.
ExampleOnTick();
}
Как думаете, если запустить этот скрипт на символе без позиций, что будет в итоге?
Правильный ответ: будет открыта одна или две позиции.
Причина, почему так происходит. После первого OrderSend появляется маркет-ордер и если до момента его исполнения приходит новый тик, то позиции еще нет и делается второй OrderSend.
В связи с этим не будет правильно работать казалось бы нормальный MT5-шаблон и, как следствие, большинство MT5-советников в кодобазе. При этом почти идентичный MT4-шаблон продолжит пахать без проблем.
Неплохая на первый взгляд идея PositionsTotal несколько омрачается необходимостью в MT5 еще анализировать и OrdersTotal на предмет маркет-ордеров.
В связи с этим не будет правильно работать казалось бы нормальный MT5-шаблон и, как следствие, большинство MT5-советников в кодобазе.
В качестве доказательства этого утверждения можно взять почти любой советник из MT5-кодобазы. Не будем что-то выискивать, а сразу возьмем самый свежий советник на данный момент. Хорошо, что он написан автором с большим MT5-опытом публикаций в КБ.
В исходнике такие строки (свои комментарии выделил)
//+------------------------------------------------------------------+//| Expert tick function |//+------------------------------------------------------------------+voidOnTick()
{
//....int total=0; // для расчета количества открытых советником позиций//....//--- main cyclefor(int i=PositionsTotal()-1;i>=0;i--)
if(m_position.SelectByIndex(i)) // selects the position by index for further access to its propertiesif(m_position.Symbol()==m_symbol.Name() && m_position.Magic()==m_magic)
{
total++; // расчет количества открытых позиций//....if(total==0) // Если нет открытых советником позиций
{
if(!RefreshRates())
{
PrevBars=iTime(1);
return;
}
//--- open BUY if(MACD_MAIN_2>MACD_SIGNAL_2 && MACD_MAIN_4<MACD_SIGNAL_4) // Сигнал на покупку
{
double sl=(InpStopLoss!=0)?m_symbol.Ask()-ExtStopLoss:0.0;
double tp=(InpTakeProfit!=0)?m_symbol.Ask()+ExtTakeProfit:0.0;
OpenBuy(sl,tp); // Отправка маркет-ордера на покупкуreturn;
}
//--- open SELLif(MACD_MAIN_2<MACD_SIGNAL_2 && MACD_MAIN_4>MACD_SIGNAL_4) // Сигнал на продажу
{
double sl=(InpStopLoss!=0)?m_symbol.Bid()+ExtStopLoss:0.0;
double tp=(InpTakeProfit!=0)?m_symbol.Bid()-ExtTakeProfit:0.0;
OpenSell(sl,tp); // Отправка маркет-ордера на продажу
}
}
return;
}
После первого OrderSend появляется маркет-ордер и если до момента его исполнения приходит новый тик, то позиции еще нет и делается второй OrderSend.
Неплохая на первый взгляд идея PositionsTotal несколько омрачается необходимостью в MT5 еще анализировать и OrdersTotal на предмет маркет-ордеров.
Это значит, что в общем случае советник откроет вместо одной позиции две, три и т.д. В зависимости от того, как часто будут приходить тики и сколько времени будут исполняться маркет-ордера.
Поскольку почти все MT5-советники в кодобазе написаны по той же логике, что и MT5-шаблон, то они имеют и ту же ошибку, что в нем содержится. Это касается почти всех MT5-советников в КБ, к сожалению.
При поступлении сигнала противоположная позиция закрывается. Также советник может закрывать половину позиции (параметр Profit for closing half of the position), может переводить позицию в безубыток (параметр Breakeven). Размер открываемой позиции может задавать вручную (параметр Lots) или в процентах риска от свободной маржи (параметр Risk in...
На неттинге одновременно на одном и том же символе может быть открытая позиция и несколько маркет-ордеров любого направления. Например, BUY-позиция и BUY-ордер. Правда, мне не удалось найти такой демо-счет., поскольку везде с асинхронностью действовало правило
Отлично видно и по столбцу времени и по числовым показателям советника, что длительность выполнения торгового приказа никак не сказывается на череде событий OnTradeTransaction. Вся асинхронность летит к чертям! Умудрились же так напортачить. Build 1755.
Например, при выставлении маркет-ордера OrderSendAsync в Терминале маркет-ордер даже на мгновение не появится. Возможно, разработчики решили так сделать для некоторого ускорения.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Как определить замену графика?
fxsaber, 2018.02.08 12:39
Нулевой входной параметр ChartID в некоторых функциях не вызывает пересчет значений. Если нужны актуальные данные текущего чарта, нужно использовать полноценный ID.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
POSITION_TICKET != POSITION_IDENTIFIER
fxsaber, 2018.02.12 20:14
Выводы
Если считать, что это штатное поведение MT5, а не особенности хака брокера, то
Недостатки
ЗЫ Полностью подтвержденная гипотеза
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
POSITION_TICKET != POSITION_IDENTIFIER
Pavel Kolchin, 2018.02.12 13:31
(не уверен, проверить сложно,по аналогии с частичным закрытием позиций)
Это все работает так:
1) отложенный ордер сработал частично - открылась позиция с Position_ID = Order_Ticket1
2) остаток ордера формируется в новый ордер Order_Ticket2 и ждет своего исполнения, новый Order_Ticket2 != Order_Ticket1, так как не может быть 2 ордера в истории с одинаковыми Order_Ticket
3) остаток ордера исполнился - открылась позиция с Position_ID = Order_Ticket2
в истории два ордера в терминале две позиции, все соответствует
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Обсуждение статьи "LifeHack для трейдера: замешиваем ForEach на дефайнах (#define)"
fxsaber, 2018.02.14 10:54
Замер производительности
Результат
Я был абсолютно не прав! SymbolInfoDouble в два раза медленнее SymbolInfoTick.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Обсуждение статьи "LifeHack для трейдера: замешиваем ForEach на дефайнах (#define)"
fxsaber, 2018.02.14 11:58
Некомпетентен. Результат в Тестере
Там, где нужна производительность (Оптимизатор), лучше использовать SymbolInfoDouble. На реале - без разницы.
ЗЫ Замер скорости функций нужно измерять в среде, где производительность важна - Тестер.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Ошибки, баги, вопросы
fxsaber, 2018.02.12 23:10
Открываю руками BUY-позицию на двух торговых демо-серверах
RoboForex-MetaTrader 5
FXOpen-MT5
Строки одного цвета обозначают одно и то же. Однако, хорошо видно, что они идут в разных очередностях. У Робо сообщение о выполнении приказа приходит после выполнения сделки. А у опенов - ДО! По этой причине OrderSend возвращает удачу, но сделки еще нет. Т.е. получаем несинхронизированность OrderSend с историей
Код для FXOpen-MT5
Результат
Данная ситуация имеет следующее объяснение
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Ошибки, баги, вопросы
Rashid Umarov, 2018.02.15 06:25
Если ордер отправдяется во внешнюю торговую систему, то торговый сервер MetaTrader 5 не ждет ответа от неё и сразу возвращает результат запроса как "ордер размещен". По этой причине OrderSend всегда вернет deal=0, так как информации о совершенной сделке еще нет. Ловите её в OnTrade или OnTradeTransaction.
Пример слушателя торговых событий дан в статье С чего начать при создании торгового робота для Московской биржи MOEX - TradeTransactionListener.mq5
OrderSend - отправил ордер на совершение рыночной сделки. Ордер выставлен - для этого надо ознакомиться с Result.order. А вот со сделку(и) никто не дожидается - их может быть много и общее время их исполнения, вообще то не определено.
Зависит от конкретной реализации вывода на стороне брокера. В общем случае не определено.
Поэтому очень рекомендую в качестве теста своего кода использовать и демо-счет на FXOpen-MT5, т.к. он стоит совсем особняком, по сравнению с другими демо.
Например, предлагаю попробовать написать на MQL5 скрипт с такой торговой логикой (MQL4-стиль только для быстрого показа смысла)
Это совсем не просто. Так же рекомендую упомянутый демо-сервер для отработки частичного исполнения.
Удалили пост, где было дано объяснение одной из самых частых ошибок на MT5.
Пост большим был. Не ожидал, что удалят. Хотелось бы услышать причину удаления. Потому как повторно нарваться на удаление - мазохизм.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Организация цикла перебора ордеров
fxsaber, 2018.02.16 09:40
в MT5 все совсем не в порядке. Пример, показывающий проблему
Как думаете, если запустить этот скрипт на символе без позиций, что будет в итоге?
Правильный ответ: будет открыта одна или две позиции.
Причина, почему так происходит. После первого OrderSend появляется маркет-ордер и если до момента его исполнения приходит новый тик, то позиции еще нет и делается второй OrderSend.
В связи с этим не будет правильно работать казалось бы нормальный MT5-шаблон и, как следствие, большинство MT5-советников в кодобазе. При этом почти идентичный MT4-шаблон продолжит пахать без проблем.
Неплохая на первый взгляд идея PositionsTotal несколько омрачается необходимостью в MT5 еще анализировать и OrdersTotal на предмет маркет-ордеров.
Будьте аккуратны!
В связи с этим не будет правильно работать казалось бы нормальный MT5-шаблон и, как следствие, большинство MT5-советников в кодобазе.
В качестве доказательства этого утверждения можно взять почти любой советник из MT5-кодобазы. Не будем что-то выискивать, а сразу возьмем самый свежий советник на данный момент. Хорошо, что он написан автором с большим MT5-опытом публикаций в КБ.
В исходнике такие строки (свои комментарии выделил)
Получаем идентичную ситуацию, что была описана
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Особенности языка mql5, тонкости и приёмы работы
fxsaber, 2018.02.16 19:52
После первого OrderSend появляется маркет-ордер и если до момента его исполнения приходит новый тик, то позиции еще нет и делается второй OrderSend.
Неплохая на первый взгляд идея PositionsTotal несколько омрачается необходимостью в MT5 еще анализировать и OrdersTotal на предмет маркет-ордеров.
Это значит, что в общем случае советник откроет вместо одной позиции две, три и т.д. В зависимости от того, как часто будут приходить тики и сколько времени будут исполняться маркет-ордера.
Поскольку почти все MT5-советники в кодобазе написаны по той же логике, что и MT5-шаблон, то они имеют и ту же ошибку, что в нем содержится. Это касается почти всех MT5-советников в КБ, к сожалению.
На неттинге одновременно на одном и том же символе может быть открытая позиция и несколько маркет-ордеров любого направления. Например, BUY-позиция и BUY-ордер. Правда, мне не удалось найти такой демо-счет., поскольку везде с асинхронностью действовало правило
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Ошибки, баги, вопросы
fxsaber, 2018.02.14 08:58
Вся череда событий OnTradeTransaction идет после завершения OrderSend.
Советник
Руками отправляем торговый приказ.
Лог
2018.02.14 09:41:46.671 '8854170': instant sell 1.00 EURUSD at 1.23673 2018.02.14 09:41:46.853 '8854170': accepted instant sell 1.00 EURUSD at 1.23673 2018.02.14 09:41:46.853 '8854170': deal #192088422 sell 1.00 EURUSD at 1.23673 done (based on order #208541700) 2018.02.14 09:41:46.853 '8854170': order #208541700 sell 1.00 / 1.00 EURUSD at 1.23673 done in 190.608 msРезультат советника
Отлично видно и по столбцу времени и по числовым показателям советника, что длительность выполнения торгового приказа никак не сказывается на череде событий OnTradeTransaction. Вся асинхронность летит к чертям! Умудрились же так напортачить. Build 1755.
Например, при выставлении маркет-ордера OrderSendAsync в Терминале маркет-ордер даже на мгновение не появится. Возможно, разработчики решили так сделать для некоторого ускорения.
Форум по трейдингу, автоматическим торговым системам и тестированию торговых стратегий
Обсуждение статьи "Визуализируем оптимизацию торговой стратегии в MetaTrader 5"
fxsaber, 2018.02.22 08:39
Во фрейм-режиме OnInit, OnDeinit, OnTick, OnTrade, OnTradeTransaction и OnTimer игнорятся. Только OnChartEvent пашет.
Конечно, из-за OnChartEvent-исключения требуется в нем делать обязательную проверку на наличие флага фрейм-режима.