Wrong "Open Time" in "For each Closed Position" ...
-
... when writing to file.


-
Here is an easy way to reproduce this error:
Compile this shared project:
https://fxdreema.com/shared/FhPzvdenePull the EA "Issue Writing Open Time" into the chart of an MT5-instance that has a history of trades.
The output file with the erroneous "Open Time" is written to folder \MQL5\Files.
-
ADDENDUM: The time that is writen as Open Time of the trade (always the same) is the account open time. The fix might be quick and easy.
-
WORKAROUND attempt:
Idea: At position open, save the time in a hash map (ticketNumber, openTime). Later, after the end of a backtest, access openTime from the hash map and write it to the file instead of the erroneous value from the loop “For each Closed Position”.
See the source code of a function that acts like an object managing a hash map below. Added this to the functions area of Custom Blocks. This part of the workaround is tested and working well.
HOWEVER: I learned something new. Something, that disabled this workaround completely: In MT5, we have different “ticket numbers” for deals, orders and positions. Specifically, the ticket number I can access directly after position open is not the same as the one in the loop “For each Closed Position”. I didn’t find any way to map those two ticket numbers with the fxDreema UI. If you know a way, please share.
Therefore, WORKAROUND TWO is this: Develop an independent function writing the complete CSV-file with the position history and call it in “on Deinit”.
A fix of the bug described above would be appreciated.
Here is the code on the function managing a hash map. You may like to modify its hash and value types according to your needs. Furthermore, at the moment, the “action” parameter is not used. It’s a template for all kinds of hash maps. Use a copy of this function with different name for each hash map that you need.
double hashMap(int hash=-1, double value=-1, string action=NULL) /* * This is a template for a function acting as a simple object * managing a hash map. For usage as custom code in fxDreema, for * example. Copy this function for each hashMap that you need, rename * it according to the content and adapt the types of hash and value * as desired. * * In this template, the hash values must be numbers >= 0 (!) * * Returns (a) 0 if all went well, or (b) the requested value belonging * to a hash key, or (c) -1 in case of an error or "hash key not found". */ { static int hashArray[]; static double valueArray[]; static const int RESERVE_SIZE=3000; // // Action "return map size" // if(hash==-1 && value==-1 && action==NULL) return(ArraySize(hashArray)); // // Action "add element" // if(hash>-1 && value>-1 && action==NULL) { int i; int size=ArraySize(hashArray); for(i=0; i<size; i++) if(hashArray[i]==hash) break; if(i<size) // Found => Invalid { PrintFormat(">>>>> Error in %s(): hash=%i existing.",__FUNCSIG__,hash); return(-1); } int newSize=ArraySize(hashArray)+1; ArrayResize(hashArray,newSize,RESERVE_SIZE); ArrayResize(valueArray,newSize,RESERVE_SIZE); hashArray[newSize-1]=hash; valueArray[newSize-1]=value; return(0); } // // Action "get element" // if(hash>-1 && value==-1 && action==NULL) { int i; int size=ArraySize(hashArray); for(i=0; i<size; i++) if(hashArray[i]==hash) break; if(i<size) // Found return(valueArray[i]); else // Not found return(-1); } // // Action "unidentified" // return(-1); } -
ADDENDUM regarding WORKAROUND TWO:
Problem was: How to get a list of deals for a position in MQL5. There is a function HistorySelectByPosition() but no simple way to get a position ID (PID). What a mess this is in MQL5! The same thing is so easy in MQL4.
After extensive search I found only one resource explaining how to obtain a PID and where it comes from.
Writing A Simple Script In Mql4 Is Not So Simple In Mql5
https://www.youtube.com/watch?v=pPcjKLNZL88
https://youtu.be/pPcjKLNZL88?t=2244 (with time code)
by Jimdandy1958BTW, I even joined Patreon to thank Jim for this one. Big thanks!!
Anyhow, Not so easy to get a singular open time for a (eventually) closed position. Could have a couple of partial closes in between, for example. Which time counts?
In MT4, the “order history” (position history in MT5) splits each partial close in a separate position, which is nice and easy. In MT5, we have to program that ourselves. Have fun, admin, making open and close time work. I am working on my workaround function for writing a "position history" (MT5 speak) to a CSV file.
PS: I am still hoping, there is something I missed and there is an elegant way to achieve this (o:
-
@Sparrow I just worked on a bug, reported in another topic (https://fxdreema.com/forum/topic/16239/for-each-closed-position-block-is-not-working), and the problem was exactly that Open Time for closed positions didn't work properly. I think this is fixed now. Sorry that it took few days, I worked on some JavaScript things these days.
I see you are interested in MQL5 a little bit, so I can tell you what was the problem. I have these custom MQL4-like function in MQL5, one of which is OrderOpenTime().
This function has some
ifin it, because it can work with positions, closed positions or pending orders. When it works with closed positions, there is a variabletypethat equals to3, so we end up in... else if (type == 3) .... The code there is like this:ulong positionId = HistoryDealGetInteger(OrderTicket(), DEAL_POSITION_ID); HistorySelectByPosition(positionId); // <<< THIS WAS NOT HERE, I ADDED IT TODAY ulong ticket = HistoryDealGetTicket(0); time = (datetime)HistoryDealGetInteger(ticket, DEAL_TIME); HistoryTradesTotalReset();Note my THIS WAS NOT HERE, I ADDED IT TODAY comment there, this is the code that was missing and causing the bug.
OrderTicket()would be the ticket of a deal, selected by "For each Closed Position", but this is a deal that is OUT, it's the final closing deal. We want the open time, and to get this information we want to get the first IN deal from this same position. To do this we need to get thisDEAL_POSITION_IDnumber, then to useHistorySelectByPosition()and from there to get that first IN deal.
But some days ago, when worked to fix some other problems, I forgot to putHistorySelectByPosition()in this particular function, or I deleted it by mistake. There is one similar functionOrderOpenPrice()and there I hadHistorySelectByPosition(). I knew that both functions are the same when it comes to loading these deals, and these few rows of code should be exactly the same in both functions, but somehow this one row of code went missing inOrderOpenPrice(). -
Many thanks, @fxDreema. All tested and working well now. Including the profit calculation including swap and commission.
Super happy also with your explanations. When a master explains the issues, everything appears more structured.
fxDreema = premium product, service and support!

