OrderCloseTime() of the 2 closeby orders should be the same as OrderOpenTime() of the new order ... I know that would work in tester the problem is how to be sure it would work correctly in live trading
not realy if OrderCloseTime() = 20:01:15.999 & OrderOpenTime() is gonna be even a split second later ? that means 20:01:16
Well yes that could happen depending on how the server is coded. If I was coding the server side of the OrderCloseBy() function, I would call the time once and assign that timestamp to the closed tickets and the open time of the replacement new ticket, after all the whole thing probably happens in a nano second, but we have no way of knowing what they did.
Thanks for all suggestions!
OrderCloseTime() of the 2 closeby orders should be the same as OrderOpenTime() of the new order ... I know that would work in tester the problem is how to be sure it would work correctly in live trading
This might be not correct.
I did some testing and found out the following
First approach with OrderCloseBy(22610340, 22610342) - the smaller lots are closing the larger lots (Original lot sizes were #22610340 with 3 lots and #22610342 with 1 lot)
OrderTicket | OrderSymbol | OrderType | OrderLots | OrderOpenTime | OrderOpenPrice | OrderCloseTime | OrderClosePrice | OrderComment | OrderMagicNumber |
22610340 | DE30 | 0 | 1 | 1392720003 | 9652.3 | 1392720022 | 9651.8 | partial close | 12345 |
22610342 | DE30 | 1 | 0 | 1392720013 | 96518 | 1392720022 | 9651.8 | close hedge by #22610340 | 12345 |
22610344 | DE30 | 0 | 2 | 1392720003 | 9652.3 | 1392720027 | 9651.5 | partial close | 12345 |
Second approach with OrderCloseBy(22610545, 22610544) - the larger lots are closing the smaller lots (Original lot sizes were #22610544 with 3 lots and #22610545 with 1 lot)
OrderTicket | OrderSymbol | OrderType | OrderLots | OrderOpenTime | OrderOpenPrice | OrderCloseTime | OrderClosePrice | OrderComment | OrderMagicNumber |
22610544 | DE30 | 0 | 0 | 1392723882 | 9641 | 1392723900 | 9641 | close hedge by #22610545 | 12345 |
22610545 | DE30 | 1 | 1 | 1392723892 | 9640.5 | 1392723900 | 9641 | partial close | 12345 |
22610546 | DE30 | 0 | 2 | 1392723882 | 9641 | 1392723906 | 9640.3 | from #22610545 | 12345 |
The matching remainder order were #22610344 on the first approach and #22610546 on the second approach.
The rules to find the matching remainder should be:
The order which is the source for the remaining order is the one with the larger lot size.
The OrderSymbol must be the same (obvious)
The OrderType must be the same (the remainder cannot be an OP_SELL when the origin was an OP_BUY and vice versa)
The order lots of the remaining order must be the difference of the origin lot sizes ( 3 - 1 = 2 in both cases)
The OrderOpenTime and OrderOpenPrice must be the same.
The OrderComment does not help to find the match.
The OrderMagicNumber must be the same (if used).
Depending on these rules here is my approach
int OrderCloseByReturnRemainder(int ticketToClose, int ticketClosing, color arrowColor = CLR_NONE) { int result = 0; int lastError = 0; int selectedValueGroup = 0; double remainderLotsExpected = 0; string symbols[2]; int orderTypes[2]; double lots[2]; datetime openTimes[2]; double openPrices[2]; int magicNumbers[2]; //-------- Section 1 - Take values of the order to be closed if(OrderSelect(ticketToClose, SELECT_BY_TICKET, MODE_TRADES)) { symbols[0] = OrderSymbol(); orderTypes[0] = OrderType(); lots[0] = OrderLots(); openTimes[0] = OrderOpenTime(); openPrices[0] = OrderOpenPrice(); magicNumbers[0] = OrderMagicNumber(); } else { lastError = GetLastError(); } //-------- Section 2 - Take values of the closing order if(lastError == 0) { if(OrderSelect(ticketClosing, SELECT_BY_TICKET, MODE_TRADES)) { symbols[1] = OrderSymbol(); orderTypes[1] = OrderType(); lots[1] = OrderLots(); openTimes[1] = OrderOpenTime(); openPrices[1] = OrderOpenPrice(); magicNumbers[1] = OrderMagicNumber(); } else { lastError = GetLastError(); } } //-------- Section 3 - Verify symbol and magic number if(symbols[0] != symbols[1]) { lastError = -5000; // Symbols does not match } else if(magicNumbers[0] != magicNumbers[1]) { lastError = -5001; // Magic numbers does not match } //-------- Section 4 - Depending on the lot sizes decide which values are expected for the remainder order if(lastError == 0) { remainderLotsExpected = MathAbs(lots[0] - lots[1]); if(lots[0] >= lots[1]) { // The source of the remainder order is the order with the 'ticketToClose' ticket number selectedValueGroup = 0; } else { // The source of the remainder order is the order with the 'ticketClosing' ticket number selectedValueGroup = 1; } } //-------- Section 5 - Perform the OrderCloseBy operation if(lastError == 0) { if(!OrderCloseBy(ticketToClose, ticketClosing, arrowColor)) { lastError = GetLastError(); } } //-------- Section 6 - Identify the remainder order if(lastError == 0) { if(remainderLotsExpected != 0) { for(int i = 0; i < OrdersTotal(); i++) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if(OrderSymbol() == symbols[selectedValueGroup] && OrderType() == orderTypes[selectedValueGroup] && OrderLots() == remainderLotsExpected && OrderOpenTime() == openTimes[selectedValueGroup] && OrderOpenPrice() == openPrices[selectedValueGroup] && OrderMagicNumber() == magicNumbers[selectedValueGroup]) { // Bingo - we got it. result = OrderTicket(); break; } } } if(result == 0) { // We are expecting a remainder order but couldn't find it! // Already closed in the meantime? Unlikely, buth who knows. // Or too strange rules for identification. lastError = -5002; } } else { // There are no remainderLotsExpected - then there will be no remainder order result = 0; } } if(lastError != 0) { result = lastError; } return(result); }
You can test it with following sample.
Uncomment OrderCloseBy... commands to try diferent versions.
You can cut and paste the logfile output to an excel sheet.
int init() { //---- // !!!!!!!!!!!!! EXECUTE JUST ON DEMO ACCOUNT TO PREVENT LOSS !!!!!!!!!!!!!!!!!!!! int i = 0; int remainderTicket = 0; int magicNumber = 12345; int ticket1 = OrderSend(Symbol(), OP_BUY, 3, Ask, 10, 0, 0, "...", magicNumber, 0); Sleep(10000); int ticket2 = OrderSend(Symbol(), OP_SELL, 1, Bid, 10, 0, 0, "...", magicNumber, 0); Sleep(8000); //OrderCloseBy(ticket1, ticket2); //OrderCloseBy(ticket2, ticket1); //remainderTicket = OrderCloseByReturnRemainder(ticket1, ticket2); remainderTicket = OrderCloseByReturnRemainder(ticket2, ticket1); Sleep(5000); for(i = 0; i < OrdersTotal(); i++) { if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) { if(Symbol() == OrderSymbol()) { if(OrderMagicNumber() == magicNumber) { OrderClose(OrderTicket(), OrderLots(), Bid, 20); } } } } Print("OrderTicket\t", "OrderSymbol\t", "OrderType\t", "OrderLots\t", "OrderOpenTime\t", "OrderOpenPrice\t", "OrderCloseTime\t", "OrderClosePrice\t", "OrderComment\t", "OrderMagicNumber"); for(i = 0; i < OrdersHistoryTotal(); i++) { if(OrderSelect(i, SELECT_BY_POS, MODE_HISTORY)) { if(OrderTicket() >= ticket1 && Symbol() == OrderSymbol()) { Print(OrderTicket(), "\t", OrderSymbol(), "\t", OrderType(), "\t", OrderLots(), "\t", OrderOpenTime(), "\t", OrderOpenPrice(), "\t", OrderCloseTime(), "\t", OrderClosePrice(), "\t", OrderComment(), "\t", OrderMagicNumber()); } } } if(remainderTicket == 0) { Print("There is no remaining order."); } else if(remainderTicket < 100000) { Print("OrderCloseByReturnRemainder returns error number ", remainderTicket); } else { Print("Remainder ticket number is #", remainderTicket); } //---- return(0); }
Best regards
Dirk
After the function call, the contents of _LastError are not reset. To reset this variable, you need to call ResetLastError().
My online help in MetaEditor is telling me something else!
int GetLastError( | ) |
The function returns the last occurred error, then the value of
special last_error variable where the last
error code is stored will be zeroized. So, the next call for GetLastError() will
return 0.
And executing of
double p = Bid; OrderSend(Symbol(),OP_SELL,0.1,p,50,NormalizeDouble(p+1000*Point,Digits),0); Alert("First call to GetLastError() returns ", GetLastError()); Alert("Second call to GetLastError() returns ", GetLastError());
against DE30 CFD is giving me this.
First call to GetLastError() returns 131
Seconds call to GetLastError() returns 0
Best regards
Dirk
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Dear all,
there is a problem for me to identify the remaining order of an OrderCloseBy request where the both orders have different lot sizes.
Let me explain on the outtake of the logfile