Background: As long as you never use the OrderSendAsync() -function, and always use the OrderSend() -function instead, there is no problem.
But if you want to speed up things and use OrderSendAsync() -function, there is a problem: At the time the OrderSendAsync() -function returns, the server has not yet processed your order. And, that's really the whole point of why OrderSendAsync() -function exists! This means that since the server has not yet processed your order, also the ulong ticket has not been assigned yet.
So, it is impossible to match orders sent using OrderSendAsync() -function and the deals that are done as a result of those orders.
Many other MQL5 -functions take the ulong ticket -parameter, as an example the CTrade method PositionClose:
bool PositionClose(const ulong ticket,const ulong deviation=ULONG_MAX);
This dilemma is exactly the reason why many commercial documents have TWO fields: "Our reference" and "Your reference".
The OrderSendAsync() -function really should have been designed so, that it has "Customer's reference" as an input field, and then MQL5 should have included a helper function, that takes "Customer's reference" as input, and gives "Broker's reference" as a result.
Unfortunately, MetaQuotes corp. missed this detail, making OrderSendAsync() -function less useful than it should be.
I will present one possible solution to this problem, but at the same time I want to ask: Has anyone come up with a better solution to this same problem.
Possible solution: Use the 64-bit magic value in a way different from what it was originally designed to be used for:
The MqlTradeRequest -structure (parameter to OrderSendAsync) contains this field:
ulong magic; // Expert Advisor ID (magic number)
Use only the High 32 bits of this magic as the "Expert Advisor ID". Then use the Low 32 bits of this magic as "Customer reference".
Unfortunately, this means that the CTrade -class needs a lot of redesign, due to the fact that instead of using the magic number as a single 64-bit integer, it is now used as a container for two separate 32-bit integers.
So, while the above could be one possible solution to this problem:
Has anyone come up with a better solution to this same problem ?
The question is whether you need to store all the ulong's
somehow or not.
If not (e.g., there is a need in some condition to close all buys regardless of any other conditions) - simply looping over open deals and closing the corresponding ones (filter by magic, symbol, direction, etc.) seems quite an easy solution.
If there's a need in keeping data of the open trades (e.g., to attach entry, initial SL, initial trail, level to move to breakeven, whatsoever) - I would use MqlTradeRequest.comment
to send async requests and then catch the results in OnTradeTransaction(..)
to create CDeal : public CObject
with all the necessary data like MqlTradeResult.deal
and comments to make a match.