POSITION_TICKET != POSITION_IDENTIFIER - страница 2

 

А мне странно, что никак не могу получить ID. Ети строки возврощают Тикет

HistoryOrderGetInteger(Order,ORDER_POSITION_ID)
HistoryDealGetInteger(Deal,DEAL_POSITION_ID)

А в историю так :

Здесь : Позиция=66702123 (записал в коментар, совпадает с Тикет ордера на открытия), а ID=6737227 - что на порядок меньше . Почему ?

 
Ivan Ivanov:

А мне странно, что никак не могу получить ID. Ети строки возврощают Тикет

А в историю так :

Здесь : Позиция=66702123 (записал в коментар, совпадает с Тикет ордера на открытия), а ID=6737227 - что на порядок меньше . Почему ?

Почему Вы решили, что предоставленной информации достаточно для ответа?

 
Alexey Viktorov:

Давайте по-порядку:

"Отложенный ордер сработал частично - открылась позиция с Position_ID = Order_Ticket." - Это всегда соответствует? Независимо от того что открыта только часть ордера?

Если "ДА" то всё в соответствии с документацией.

"Остаток ордера исполнился - открылась позиция с Position_ID != Order_Ticket." - А тикету какого ордера должно соответствовать? Тому, часть которого уже исполнена, или тому который остался после частичного исполнения? И с каким вы сравнивали?

(не уверен, проверить сложно,по аналогии с частичным закрытием позиций)

Это все работает так:

1) отложенный ордер сработал частично - открылась позиция с Position_ID = Order_Ticket1

2) остаток ордера формируется в новый ордер Order_Ticket2 и ждет своего исполнения, новый Order_Ticket2   !=  Order_Ticket1, так как не может быть 2 ордера в истории с одинаковыми Order_Ticket

3) остаток ордера исполнился  - открылась позиция с Position_ID = Order_Ticket2

в истории два ордера в терминале две позиции, все соответствует

 
Pavel Kolchin:

2) остаток ордера формируется в новый ордер Order_Ticket2 и ждет своего исполнения, новый Order_Ticket2   !=  Order_Ticket1, так как не может быть 2 ордера в истории с одинаковыми Order_Ticket

Не просто так есть ORDER_STATE_PARTIAL. Т.е. новый ордер с остатком не создается. При частичном исполнении Сделка может быть еще без Ордера в Истории.

Rashid Umarov:
Не сплю, на вахте.

Ждемс.

 
Ivan Ivanov:

А мне странно, что никак не могу получить ID. Ети строки возврощают Тикет

А в историю так :

Здесь : Позиция=66702123 (записал в коментар, совпадает с Тикет ордера на открытия), а ID=6737227 - что на порядок меньше . Почему ?

на картинке не тот ID о котором вы думаете


 
Лучшее частичное исполнение лимитных ордеров (включая TP) - MT4. Там тикеты пересоздаются.
 
fxsaber:

Не просто так есть ORDER_STATE_PARTIAL. Т.е. новый ордер с остатком не создается. 

я думал об этом, так же есть такая надпись


но мне кажется что просто кто-то не хотел разжёвывать и написал общий принцип

на самом деле первый ордер исполняется в том объеме в котором смог, и он уже в истории

а остатки формируются в новый ордер, и тогда уже ему присваивается статус ORDER_STATE_PARTIAL

 
Pavel Kolchin:

на самом деле первый ордер исполняется в том объеме в котором смог, и он уже в истории

а остатки формируются в новый ордер и уже ему присваивается статус ORDER_STATE_PARTIAL

Это был бы лучший вариант. Если ордера в Истории могут иметь ORDER_STATE_PARTIAL, то, скорее всего, так и есть.

 

Добился частичного исполнения. Выставил BuyLimit на 1 лот через скрипт.

Вкладка Позиции

Позиции

Ордера/Сделки

Ордера/Сделки

Журнал

2018.02.12 19:32:41.632 '18000903': buy limit 1.00 EURUSD at 1.22712
2018.02.12 19:32:41.887 '18000903': accepted buy limit 1.00 EURUSD at 1.22712
2018.02.12 19:32:41.887 '18000903': buy limit 1.00 EURUSD at 1.22712 placed for execution
2018.02.12 19:32:41.897 '18000903': order #896204 buy limit 1.00 / 1.00 EURUSD at 1.22712 done in 268.406 ms
2018.02.12 19:32:41.967 '18000903': deal #80363 buy 0.01 EURUSD at 1.22712 done (based on order #896205)
2018.02.12 19:32:42.030 '18000903': deal #80364 buy 0.01 EURUSD at 1.22712 done (based on order #896206)
2018.02.12 19:32:42.070 '18000903': deal #80365 buy 0.01 EURUSD at 1.22712 done (based on order #896207)
2018.02.12 19:32:42.112 '18000903': deal #80366 buy 0.01 EURUSD at 1.22712 done (based on order #896208)
2018.02.12 19:32:42.152 '18000903': deal #80367 buy 0.01 EURUSD at 1.22712 done (based on order #896209)
2018.02.12 19:32:42.182 '18000903': deal #80368 buy 0.01 EURUSD at 1.22712 done (based on order #896210)
2018.02.12 19:32:42.222 '18000903': deal #80369 buy 0.01 EURUSD at 1.22712 done (based on order #896211)
2018.02.12 19:32:42.269 '18000903': deal #80370 buy 0.01 EURUSD at 1.22712 done (based on order #896212)
2018.02.12 19:32:42.299 '18000903': deal #80371 buy 0.01 EURUSD at 1.22712 done (based on order #896213)
2018.02.12 19:32:42.339 '18000903': deal #80372 buy 0.01 EURUSD at 1.22712 done (based on order #896214)
2018.02.12 19:32:42.369 '18000903': deal #80373 buy 0.01 EURUSD at 1.22712 done (based on order #896215)
2018.02.12 19:32:42.412 '18000903': deal #80374 buy 0.01 EURUSD at 1.22712 done (based on order #896216)
2018.02.12 19:32:42.452 '18000903': deal #80375 buy 0.01 EURUSD at 1.22712 done (based on order #896217)
2018.02.12 19:32:42.493 '18000903': deal #80376 buy 0.01 EURUSD at 1.22712 done (based on order #896218)
2018.02.12 19:32:42.545 '18000903': deal #80377 buy 0.01 EURUSD at 1.22712 done (based on order #896219)
2018.02.12 19:32:42.578 '18000903': deal #80378 buy 0.01 EURUSD at 1.22712 done (based on order #896220)
2018.02.12 19:32:42.618 '18000903': deal #80379 buy 0.01 EURUSD at 1.22712 done (based on order #896221)
2018.02.12 19:32:44.418 '18000903': deal #80380 buy 0.83 EURUSD at 1.22712 done (based on order #896204)


Натравленный скрипт на торговое окружение

#include <MT4Orders.mqh>

#define PRINT(A) Print(#A + " = " + (string)(A))

void OnStart()
{
  for (int i = 0; i < OrdersTotal(); i++)
    if (OrderSelect(i, SELECT_BY_POS))
    {
      OrderPrint();
      
      PRINT(PositionGetInteger(POSITION_IDENTIFIER));
      
      const long DealTicket = OrderTicketOpen();
            
      if (HistoryDealSelect(DealTicket))
      {
        PRINT(HistoryDealGetInteger(DealTicket, DEAL_POSITION_ID));
        Print(EnumToString(OrderOpenReason()));
        
        const long OrderTicket = HistoryDealGetInteger(DealTicket, DEAL_ORDER);        
        PRINT(OrderTicket);
        
        if (HistoryOrderSelect(OrderTicket))
        {
          PRINT(HistoryOrderGetInteger(OrderTicket, ORDER_POSITION_ID));
          Print(EnumToString((ENUM_ORDER_STATE)HistoryOrderGetInteger(OrderTicket, ORDER_STATE)));
        }
      }
    }  
}


Результат

#896204 2018.02.12 19:34:06 buy 0.83 EURUSD 1.22712 0.00000 0.00000 1.22726 -5.09 0.00 11.62 0
PositionGetInteger(POSITION_IDENTIFIER) = 896204
HistoryDealGetInteger(DealTicket,DEAL_POSITION_ID) = 896204
DEAL_REASON_EXPERT
OrderTicket = 896204
HistoryOrderGetInteger(OrderTicket,ORDER_POSITION_ID) = 896204
ORDER_STATE_FILLED
#896205 2018.02.12 19:34:04 buy 0.01 EURUSD 1.22712 0.00000 0.00000 1.22726 -0.06 0.00 0.14 0
PositionGetInteger(POSITION_IDENTIFIER) = 896205
HistoryDealGetInteger(DealTicket,DEAL_POSITION_ID) = 896205
DEAL_REASON_CLIENT
OrderTicket = 896205
HistoryOrderGetInteger(OrderTicket,ORDER_POSITION_ID) = 896205
ORDER_STATE_FILLED
#896206 2018.02.12 19:34:04 buy 0.01 EURUSD 1.22712 0.00000 0.00000 1.22726 -0.06 0.00 0.14 0
PositionGetInteger(POSITION_IDENTIFIER) = 896206
HistoryDealGetInteger(DealTicket,DEAL_POSITION_ID) = 896206
DEAL_REASON_CLIENT
OrderTicket = 896206
HistoryOrderGetInteger(OrderTicket,ORDER_POSITION_ID) = 896206
ORDER_STATE_FILLED
#896207 2018.02.12 19:34:04 buy 0.01 EURUSD 1.22712 0.00000 0.00000 1.22726 -0.06 0.00 0.14 0
PositionGetInteger(POSITION_IDENTIFIER) = 896207
HistoryDealGetInteger(DealTicket,DEAL_POSITION_ID) = 896207
DEAL_REASON_CLIENT
OrderTicket = 896207
HistoryOrderGetInteger(OrderTicket,ORDER_POSITION_ID) = 896207
ORDER_STATE_FILLED
#896208 2018.02.12 19:34:04 buy 0.01 EURUSD 1.22712 0.00000 0.00000 1.22726 -0.06 0.00 0.14 0
PositionGetInteger(POSITION_IDENTIFIER) = 896208
HistoryDealGetInteger(DealTicket,DEAL_POSITION_ID) = 896208
DEAL_REASON_CLIENT
OrderTicket = 896208
HistoryOrderGetInteger(OrderTicket,ORDER_POSITION_ID) = 896208
ORDER_STATE_FILLED
#896209 2018.02.12 19:34:04 buy 0.01 EURUSD 1.22712 0.00000 0.00000 1.22726 -0.06 0.00 0.14 0
PositionGetInteger(POSITION_IDENTIFIER) = 896209
HistoryDealGetInteger(DealTicket,DEAL_POSITION_ID) = 896209
DEAL_REASON_CLIENT
OrderTicket = 896209
HistoryOrderGetInteger(OrderTicket,ORDER_POSITION_ID) = 896209
ORDER_STATE_FILLED
#896210 2018.02.12 19:34:04 buy 0.01 EURUSD 1.22712 0.00000 0.00000 1.22726 -0.06 0.00 0.14 0
PositionGetInteger(POSITION_IDENTIFIER) = 896210
HistoryDealGetInteger(DealTicket,DEAL_POSITION_ID) = 896210
DEAL_REASON_CLIENT
OrderTicket = 896210
HistoryOrderGetInteger(OrderTicket,ORDER_POSITION_ID) = 896210
ORDER_STATE_FILLED
#896211 2018.02.12 19:34:04 buy 0.01 EURUSD 1.22712 0.00000 0.00000 1.22726 -0.06 0.00 0.14 0
PositionGetInteger(POSITION_IDENTIFIER) = 896211
HistoryDealGetInteger(DealTicket,DEAL_POSITION_ID) = 896211
DEAL_REASON_CLIENT
OrderTicket = 896211
HistoryOrderGetInteger(OrderTicket,ORDER_POSITION_ID) = 896211
ORDER_STATE_FILLED
#896212 2018.02.12 19:34:04 buy 0.01 EURUSD 1.22712 0.00000 0.00000 1.22726 -0.06 0.00 0.14 0
PositionGetInteger(POSITION_IDENTIFIER) = 896212
HistoryDealGetInteger(DealTicket,DEAL_POSITION_ID) = 896212
DEAL_REASON_CLIENT
OrderTicket = 896212
HistoryOrderGetInteger(OrderTicket,ORDER_POSITION_ID) = 896212
ORDER_STATE_FILLED
#896213 2018.02.12 19:34:04 buy 0.01 EURUSD 1.22712 0.00000 0.00000 1.22726 -0.06 0.00 0.14 0
PositionGetInteger(POSITION_IDENTIFIER) = 896213
HistoryDealGetInteger(DealTicket,DEAL_POSITION_ID) = 896213
DEAL_REASON_CLIENT
OrderTicket = 896213
HistoryOrderGetInteger(OrderTicket,ORDER_POSITION_ID) = 896213
ORDER_STATE_FILLED
#896214 2018.02.12 19:34:04 buy 0.01 EURUSD 1.22712 0.00000 0.00000 1.22726 -0.06 0.00 0.14 0
PositionGetInteger(POSITION_IDENTIFIER) = 896214
HistoryDealGetInteger(DealTicket,DEAL_POSITION_ID) = 896214
DEAL_REASON_CLIENT
OrderTicket = 896214
HistoryOrderGetInteger(OrderTicket,ORDER_POSITION_ID) = 896214
ORDER_STATE_FILLED
#896215 2018.02.12 19:34:04 buy 0.01 EURUSD 1.22712 0.00000 0.00000 1.22726 -0.06 0.00 0.14 0
PositionGetInteger(POSITION_IDENTIFIER) = 896215
HistoryDealGetInteger(DealTicket,DEAL_POSITION_ID) = 896215
DEAL_REASON_CLIENT
OrderTicket = 896215
HistoryOrderGetInteger(OrderTicket,ORDER_POSITION_ID) = 896215
ORDER_STATE_FILLED
#896216 2018.02.12 19:34:04 buy 0.01 EURUSD 1.22712 0.00000 0.00000 1.22726 -0.06 0.00 0.14 0
PositionGetInteger(POSITION_IDENTIFIER) = 896216
HistoryDealGetInteger(DealTicket,DEAL_POSITION_ID) = 896216
DEAL_REASON_CLIENT
OrderTicket = 896216
HistoryOrderGetInteger(OrderTicket,ORDER_POSITION_ID) = 896216
ORDER_STATE_FILLED
#896217 2018.02.12 19:34:04 buy 0.01 EURUSD 1.22712 0.00000 0.00000 1.22726 -0.06 0.00 0.14 0
PositionGetInteger(POSITION_IDENTIFIER) = 896217
HistoryDealGetInteger(DealTicket,DEAL_POSITION_ID) = 896217
DEAL_REASON_CLIENT
OrderTicket = 896217
HistoryOrderGetInteger(OrderTicket,ORDER_POSITION_ID) = 896217
ORDER_STATE_FILLED
#896218 2018.02.12 19:34:04 buy 0.01 EURUSD 1.22712 0.00000 0.00000 1.22726 -0.06 0.00 0.14 0
PositionGetInteger(POSITION_IDENTIFIER) = 896218
HistoryDealGetInteger(DealTicket,DEAL_POSITION_ID) = 896218
DEAL_REASON_CLIENT
OrderTicket = 896218
HistoryOrderGetInteger(OrderTicket,ORDER_POSITION_ID) = 896218
ORDER_STATE_FILLED
#896219 2018.02.12 19:34:04 buy 0.01 EURUSD 1.22712 0.00000 0.00000 1.22726 -0.06 0.00 0.14 0
PositionGetInteger(POSITION_IDENTIFIER) = 896219
HistoryDealGetInteger(DealTicket,DEAL_POSITION_ID) = 896219
DEAL_REASON_CLIENT
OrderTicket = 896219
HistoryOrderGetInteger(OrderTicket,ORDER_POSITION_ID) = 896219
ORDER_STATE_FILLED
#896220 2018.02.12 19:34:04 buy 0.01 EURUSD 1.22712 0.00000 0.00000 1.22726 -0.06 0.00 0.14 0
PositionGetInteger(POSITION_IDENTIFIER) = 896220
HistoryDealGetInteger(DealTicket,DEAL_POSITION_ID) = 896220
DEAL_REASON_CLIENT
OrderTicket = 896220
HistoryOrderGetInteger(OrderTicket,ORDER_POSITION_ID) = 896220
ORDER_STATE_FILLED
#896221 2018.02.12 19:34:04 buy 0.01 EURUSD 1.22712 0.00000 0.00000 1.22726 -0.06 0.00 0.14 0
PositionGetInteger(POSITION_IDENTIFIER) = 896221
HistoryDealGetInteger(DealTicket,DEAL_POSITION_ID) = 896221
DEAL_REASON_CLIENT
OrderTicket = 896221
HistoryOrderGetInteger(OrderTicket,ORDER_POSITION_ID) = 896221
ORDER_STATE_FILLED


Выводы

Если считать, что это штатное поведение 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 и не идет наружу.
ЗЫ Полностью подтвержденная гипотеза

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

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

в истории два ордера в терминале две позиции, все соответствует

 
fxsaber:

значит можно уверенно сказать что в hedge счетах всегда POSITION_TICKET == POSITION_IDENTIFIER ?

в таком случае по сабжу можно обойтись без перебора (зная тикет сделки - выбрать позицию)

bool netting=!(bool)AccountInfoInteger(ACCOUNT_MARGIN_MODE);

if(netting){
   PositionSelect(HistoryDealGetString(deal_ticket,DEAL_SYMBOL));
}else{
   PositionSelectByTicket(HistoryDealGetInteger(deal_ticket,DEAL_POSITION_ID))
}