Правильно ли я понял, что BYPASS.CheckHistory (и, соотв-но BYPASS.Is) определяют рассинхронизацию только на ордерах, открывающих позиции?
Я смотрю этот код:
1. Например, если есть 1 поза, я ее закрываю. Ордер на закрытия исполнился, появился в истории. По нему прошла сделка, появилась в истории. Но PositionsTotal пока =1, т.е. окружение не синхронизировано.
Вы все верно поняли. Это сделано намеренно. Т.к. позиция, которая закрыта, но еще не отражена, как закрытая, не в состоянии что-либо испортить.
Иногда может.
Абстрактно, может быть ситуация, когда терминал говорит мне, что у меня есть длинная поза 1лот , я хочу сделать короткую нетто-позу -1лот путем открытия хеджирующей короткой позы. Я посылаю ордер на продажу 2 лота. По факту оказывается, что длинная поза на тот момент уже была закрыта, у меня нетто-позиция -2лота.
В классе TRADESID (и вообще во многих библиотеках) меня смущает один момент - может ли история изменяться?
Например, в RefreshOrders мы берем из истории все ордера от LastTotalOrders по HistoryOrdersTotal и обновляем LastTotalOrders. А что, если в исторической таблице ордеров будут какие-то изменения в ордерах ДО LastTotalOrders? Например, будут удалены или заменены какие-то ордера, типа уже открытая поза будет отменена брокером/ДЦ и соотв-е ордера будут выкинуты из истории.
Аналогично в таблице сделок могут быть добавлены в прошлое какие-то неторговые операции, или удалены сделки, а какие-то сделки добавлены задним числом (в том же месте истории сделок).
3. вызвать GetSumByPositionsID(PositionsID, GetSumByPositionID2). Если во время п.2 история была изменена, то результат будет отличаться от "классического варианта" GetSumByPositionsID(PositionsID, GetSumByPositionID).
b. В контексте ByPass проблемы с TradesID быть не должно, но может быть проблема с логикой самого ByPass. Сценарий такой:
1. в какой-то момент работы эксперта/скрипта был вызван очередной ByPass.Is().
2. прошло какое-то (большое или маленькое) время и ДЦ удалил из истории один или несколько ордеров (и может быть 1/несколько сделок).
3. еще через какое-то время программа послала ордер Buy market.
4. сразу или почти сразу программа вызвала снова ByPass.Is(). к этому моменту ордер успел отработаться и попал в историю, но поза еще не посчиталась в PositionsTotal().
5. запуск CheckHistory:
- сначала проверяются сделки. Если история сделок была укорочена в п.2, то TotalDeals <=PrevTotalDeals. Если история не менялась, но сделка по нашему приказу из п.3 еще не успела попасть в историю - тот же результат. Тогда Res==true.
- далее проверяются ордера. Т.к. история ордеров укорочена, то TotalOrders<=PrevTotalOrders. CheckHistory возвращает true.
6. В итоге ByPass.Is() показывает true, хотя PositionsTotal() еще не обновился.
Чтобы свести вероятность такого сценария к минимуму, можно попробовать делать так: если мы планируем послать рыночный ордер и после него сразу проверить ByPass.Is(), то надо перед отправкой ордера тоже вызвать ByPass.Is().
Также мне кажется в TradesID.RefreshOrders() лучше добавить проверку:
if (this.LastTotalOrders > Total) this.LastTotalOrders = Total;
аналогично логике ByPass.CheckHistory. (И в RefreshDeals тоже)
3. вызвать GetSumByPositionsID(PositionsID, GetSumByPositionID2). Если во время п.2 история была изменена, то результат будет отличаться от "классического варианта" GetSumByPositionsID(PositionsID, GetSumByPositionID).
Если история дописалась - нет проблем.
Если история задним числом изменилась: удалили ордер/сделку. То TradesID вернет неизвестный результат. Т.к. мы не знаем, в какое место исторической таблицы MT5 попадают (пусть и с прошлым временем) правки задним числом. Я бы не закладывался на такое развитие событий, потому что оно, мягко говоря, странное. Все же торговая история - это Документ. В частности, банки его принимают в качестве объяснения происхождения крупных сумм при снятии денег банковским переводом. Ежесуточно стейт высылается брокером на почту и т.д. Правки задним числом - это больше техническая возможность, нежели реальная.
2. прошло какое-то (большое или маленькое) время и ДЦ удалил из истории один или несколько ордеров (и может быть 1/несколько сделок).
Выше написал по этому поводу. Вижу техническую возможность.
ENUM_TRADE_TRANSACTION_TYPE
Идентификатор
Описание
TRADE_TRANSACTION_DEAL_UPDATE
Изменение сделки в истории. Возможны ситуации, когда ранее исполненная сделка изменяется на сервере. Например, сделка была изменена во внешней торговой системе (бирже), куда она была выведена брокером.
TRADE_TRANSACTION_DEAL_DELETE
Удаление сделки из истории. Возможны ситуации, когда ранее исполненная сделка удаляется на сервере. Например, сделка была удалена во внешней торговой системе (бирже), куда она была выведена брокером.
TRADE_TRANSACTION_HISTORY_UPDATE
Изменение ордера, находящегося в истории ордеров. Данный тип предусмотрен для расширения функциональности на стороне торгового сервера.
TRADE_TRANSACTION_HISTORY_DELETE
Удаление ордера из истории ордеров. Данный тип предусмотрен для расширения функциональности на стороне торгового сервера.
TRADE_TRANSACTION_POSITION
Изменение позиции, не связанное с исполнением сделки. Данный тип транзакции свидетельствует именно о том, что позиция была изменена на стороне торгового сервера. У позиции может быть изменен объем, цена открытия, а также уровни Stop Loss и Take Profit. Информация об изменениях передается в структуреMqlTradeTransactionчерез обработчик OnTradeTransaction. Изменение позиции (добавление, изменение или ликвидация) в результате совершения сделки не влечет за собой появление транзакции TRADE_TRANSACTION_POSITION.
Понятия не имею, сталкивался ли кто-то с такими значениями (верхние четыре). Ну и выделенное звучит совсем странно. Возможно, в Документации ошибка.
Правильно ли я понял, что BYPASS.CheckHistory (и, соотв-но BYPASS.Is) определяют рассинхронизацию только на ордерах, открывающих позиции?
Я смотрю этот код:
1. Например, если есть 1 поза, я ее закрываю. Ордер на закрытия исполнился, появился в истории. По нему прошла сделка, появилась в истории. Но PositionsTotal пока =1, т.е. окружение не синхронизировано.
Тогда (OldOrders[Size - 1] != PositionID) == true
(::HistoryDealGetInteger(Deals[Size - 1], DEAL_ENTRY) != DEAL_ENTRY_IN) == true
соотв-но .CheckHistory и .Is дадут true, чего быть не должно.
2. Даже если сделки пока нет в истории, это условие
будут выполняться, т.к. PositionSelectByTicket(PositionID) еще истинно. IsPosDeal выдаст true.
Вы все верно поняли. Это сделано намеренно. Т.к. позиция, которая закрыта, но еще не отражена, как закрытая, не в состоянии что-либо испортить.
Вы все верно поняли. Это сделано намеренно. Т.к. позиция, которая закрыта, но еще не отражена, как закрытая, не в состоянии что-либо испортить.
Иногда может.
Абстрактно, может быть ситуация, когда терминал говорит мне, что у меня есть длинная поза 1лот , я хочу сделать короткую нетто-позу -1лот путем открытия хеджирующей короткой позы. Я посылаю ордер на продажу 2 лота. По факту оказывается, что длинная поза на тот момент уже была закрыта, у меня нетто-позиция -2лота.
В классе TRADESID (и вообще во многих библиотеках) меня смущает один момент - может ли история изменяться?
Например, в RefreshOrders мы берем из истории все ордера от LastTotalOrders по HistoryOrdersTotal и обновляем LastTotalOrders. А что, если в исторической таблице ордеров будут какие-то изменения в ордерах ДО LastTotalOrders? Например, будут удалены или заменены какие-то ордера, типа уже открытая поза будет отменена брокером/ДЦ и соотв-е ордера будут выкинуты из истории.
Аналогично в таблице сделок могут быть добавлены в прошлое какие-то неторговые операции, или удалены сделки, а какие-то сделки добавлены задним числом (в том же месте истории сделок).
может ли история изменяться?
Может.
1.и что тогда делать?
2. как это отловить?
3. или просто периодически пересоздавать объект TradesID ?
Напишите гипотетический сценарий, где после изменения истории больше не годится TradesID.
Напишите гипотетический сценарий, где после изменения истории больше не годится TradesID.
a. Если говорить не в контексте ByPass, а на примере Вашего скрипта TradesID_Examples:
1.вызвать GetSumByPositionsID(PositionsID, GetSumByPositionID2)
2. подождать какое-то время
3. вызвать GetSumByPositionsID(PositionsID, GetSumByPositionID2). Если во время п.2 история была изменена, то результат будет отличаться от "классического варианта" GetSumByPositionsID(PositionsID, GetSumByPositionID).
b. В контексте ByPass проблемы с TradesID быть не должно, но может быть проблема с логикой самого ByPass. Сценарий такой:
1. в какой-то момент работы эксперта/скрипта был вызван очередной ByPass.Is().
2. прошло какое-то (большое или маленькое) время и ДЦ удалил из истории один или несколько ордеров (и может быть 1/несколько сделок).
3. еще через какое-то время программа послала ордер Buy market.
4. сразу или почти сразу программа вызвала снова ByPass.Is(). к этому моменту ордер успел отработаться и попал в историю, но поза еще не посчиталась в PositionsTotal().
5. запуск CheckHistory:
- сначала проверяются сделки. Если история сделок была укорочена в п.2, то TotalDeals <=PrevTotalDeals. Если история не менялась, но сделка по нашему приказу из п.3 еще не успела попасть в историю - тот же результат. Тогда Res==true.
- далее проверяются ордера. Т.к. история ордеров укорочена, то TotalOrders<=PrevTotalOrders. CheckHistory возвращает true.
6. В итоге ByPass.Is() показывает true, хотя PositionsTotal() еще не обновился.
Чтобы свести вероятность такого сценария к минимуму, можно попробовать делать так: если мы планируем послать рыночный ордер и после него сразу проверить ByPass.Is(), то надо перед отправкой ордера тоже вызвать ByPass.Is().
Также мне кажется в TradesID.RefreshOrders() лучше добавить проверку:
аналогично логике ByPass.CheckHistory. (И в RefreshDeals тоже)
a. Если говорить не в контексте ByPass, а на примере Вашего скрипта TradesID_Examples:
1.вызвать GetSumByPositionsID(PositionsID, GetSumByPositionID2)
2. подождать какое-то время
3. вызвать GetSumByPositionsID(PositionsID, GetSumByPositionID2). Если во время п.2 история была изменена, то результат будет отличаться от "классического варианта" GetSumByPositionsID(PositionsID, GetSumByPositionID).
2. прошло какое-то (большое или маленькое) время и ДЦ удалил из истории один или несколько ордеров (и может быть 1/несколько сделок).
Выше написал по этому поводу. Вижу техническую возможность.
ENUM_TRADE_TRANSACTION_TYPE
Идентификатор
Описание
TRADE_TRANSACTION_DEAL_UPDATE
Изменение сделки в истории. Возможны ситуации, когда ранее исполненная сделка изменяется на сервере. Например, сделка была изменена во внешней торговой системе (бирже), куда она была выведена брокером.
TRADE_TRANSACTION_DEAL_DELETE
Удаление сделки из истории. Возможны ситуации, когда ранее исполненная сделка удаляется на сервере. Например, сделка была удалена во внешней торговой системе (бирже), куда она была выведена брокером.
TRADE_TRANSACTION_HISTORY_UPDATE
Изменение ордера, находящегося в истории ордеров. Данный тип предусмотрен для расширения функциональности на стороне торгового сервера.
TRADE_TRANSACTION_HISTORY_DELETE
Удаление ордера из истории ордеров. Данный тип предусмотрен для расширения функциональности на стороне торгового сервера.
TRADE_TRANSACTION_POSITION
Изменение позиции, не связанное с исполнением сделки. Данный тип транзакции свидетельствует именно о том, что позиция была изменена на стороне торгового сервера. У позиции может быть изменен объем, цена открытия, а также уровни Stop Loss и Take Profit. Информация об изменениях передается в структуре MqlTradeTransaction через обработчик OnTradeTransaction. Изменение позиции (добавление, изменение или ликвидация) в результате совершения сделки не влечет за собой появление транзакции TRADE_TRANSACTION_POSITION.