tracking positions/orders by identifier in code?

 

Hi,

the story: in hedging mode I have several orders and positions at a time. If something happens (order is placed, order becomes a position, position takes profit, order is deleted because of circumstances, ...) my current way of handling things is to fetch all orders and positions (with OrdersTotal() / PositionsTotal()) and looping over all of them to do the things necessary. I don't like this approach, because if something happens, it happens to one order/position at a time - but I have to fetch all and loop over all. Furthermore I have unnecessary redundant calls to OrdersTotal() / PositionsTotal() with network traffic involved.

Is this approach best practice?

I thougt about using the OnTrade() and OnTradeTransaction(...) event handler to build an array for storing ticket numbers of all orders/positions within my EA. Because then I could avoid looping and fetching of all orders/positions, say something like:
Hey, an OnTrade event occurred, now I getOrdPosByTicketFromArray(ticketNo); doThings(); removeThatFromArray(ticketNo); and so on _within_ my EA, therefore faster and w/o network traffic.

But the OnTrade() event does not handle any request/response params (so I can't get the underlying ticket number) and the OnTradeTransaction(...) events seem to be complicated since there are several transaction events for one operation (from my point of view): I notice "order becomes position" but there are 4 or 5 transaction events fired that needs to be handled. And the order of that events is uncertain, also.

So my questions are:

  • is there a lib that simplifies the OnTradeTransaction?
  • is there a simpler way to handle orders and positions by an identifier (ticketNo?) within EA code that I did not see, yet?
  • is the best and most reliable way to handle this with fetching and looping like stated in "the story" above?
  • am I thinking too much about that?


Thanks for any hints and best regards,
Alex

 
Alex:

Hi,

the story: in hedging mode I have several orders and positions at a time. If something happens (order is placed, order becomes a position, position takes profit, order is deleted because of circumstances, ...) my current way of handling things is to fetch all orders and positions (with OrdersTotal() / PositionsTotal()) and looping over all of them to do the things necessary. I don't like this approach, because if something happens, it happens to one order/position at a time - but I have to fetch all and loop over all. Furthermore I have unnecessary redundant calls to OrdersTotal() / PositionsTotal() with network traffic involved.

Is this approach best practice?

I thougt about using the OnTrade() and OnTradeTransaction(...) event handler to build an array for storing ticket numbers of all orders/positions within my EA. Because then I could avoid looping and fetching of all orders/positions, say something like:
Hey, an OnTrade event occurred, now I getOrdPosByTicketFromArray(ticketNo); doThings(); removeThatFromArray(ticketNo); and so on _within_ my EA, therefore faster and w/o network traffic.

But the OnTrade() event does not handle any request/response params (so I can't get the underlying ticket number) and the OnTradeTransaction(...) events seem to be complicated since there are several transaction events for one operation (from my point of view): I notice "order becomes position" but there are 4 or 5 transaction events fired that needs to be handled. And the order of that events is uncertain, also.

So my questions are:

  • is there a lib that simplifies the OnTradeTransaction?
  • is there a simpler way to handle orders and positions by an identifier (ticketNo?) within EA code that I did not see, yet?
  • is the best and most reliable way to handle this with fetching and looping like stated in "the story" above?
  • am I thinking too much about that?


Thanks for any hints and best regards,
Alex

No need to over think this, just keep it simple.

Use this: https://www.mql5.com/en/docs/standardlibrary/tradeclasses/cpositioninfo/cpositioninfoselectbymagic
This will allow you to select by the instrument and magic number.
There are other ways of course, but that should help you with your problem.

- Jack

Documentation on MQL5: Standard Library / Trade Classes / CPositionInfo / SelectByMagic
Documentation on MQL5: Standard Library / Trade Classes / CPositionInfo / SelectByMagic
  • www.mql5.com
Standard Library / Trade Classes / CPositionInfo / SelectByMagic - Reference on algorithmic/automated trading language for MetaTrader 5
 
So my questions are:
  • is there a lib that simplifies the OnTradeTransaction?
  • is there a simpler way to handle orders and positions by an identifier (ticketNo?) within EA code that I did not see, yet?
  • is the best and most reliable way to handle this with fetching and looping like stated in "the story" above?
  • am I thinking too much about that?


My opinion is that OnTradeTransaction() is what you want. My understanding is that this event gives you the on-the-fly updates you need. (No looping, and probably as close to real-time as you can expect to get.)

As for a lib that simplifies it, I don't think there is one; but you probably don't need it.In this thread, toward the bottom of page one, chinaski posts a library of functions that convert all the enumerated types to strings. He has OnTradeTransaction() call a function dump_MqlTradeTransaction(). From that, I found it relatively straightforward to find the bits and pieces I needed.

My need was fairly simple: for a single currency pair, tell me the profit & swap if the trade closed due to SL or TP. It sounds like you have a more complex problem because you have multiple currencies, but I believe all the data is available to you in the MqlTradeTransaction object.

Good luck

 
Anthony Garot:


My opinion is that OnTradeTransaction() is what you want. My understanding is that this event gives you the on-the-fly updates you need. (No looping, and probably as close to real-time as you can expect to get.)

As for a lib that simplifies it, I don't think there is one; but you probably don't need it.In this thread, toward the bottom of page one, chinaski posts a library of functions that convert all the enumerated types to strings. He has OnTradeTransaction() call a function dump_MqlTradeTransaction(). From that, I found it relatively straightforward to find the bits and pieces I needed.

My need was fairly simple: for a single currency pair, tell me the profit & swap if the trade closed due to SL or TP. It sounds like you have a more complex problem because you have multiple currencies, but I believe all the data is available to you in the MqlTradeTransaction object.

Good luck


The OP was looking for a specific identifier, why not just use the built in MAGIC number since that's what it's for?

ALEX:
<EDITED FOR SPACE>.... is there a simpler way to handle orders and positions by an identifier (ticketNo?) within EA code that I did not see, yet?

The order magic number is a built in identifier specific to doing what the OP wants.

There are numerous ways to do this, but the magic number is probably the simplest solution for this instance.

Just keep it simple, use the built in function.

- Jack

 
Jack Thomas:

No need to over think this, just keep it simple.

Use this: https://www.mql5.com/en/docs/standardlibrary/tradeclasses/cpositioninfo/cpositioninfoselectbymagic
This will allow you to select by the instrument and magic number.
There are other ways of course, but that should help you with your problem.

- Jack

I would like to ask you, please, to stop using different colors and bold for all your text. Thanks.

 

Hi, 

thank you for your replies! Unfortunately it does not take me any further.
Just to clarify: I talk about _one_ symbol with _many_ orders and positions at a time (MT5 terminal in hedging mode).


Use this: https://www.mql5.com/en/docs/standardlibrary/tradeclasses/cpositioninfo/cpositioninfoselectbymagic

That does not help, since it does the same as I did already: select all and loop over it.


The OP was looking for a specific identifier, why not just use the built in MAGIC number since that's what it's for?

Does not help either: if I could use the magic, I could use the ticket number as well. I cannot access any order/position information in the simple OnTrade() event function. There are no params, so I cant figure out which order/pos is responsible for fireing that event in a simple way I think. So no ticket, no magic, nothing, just: yeah something happened on any of your positions/orders.


Therefore I have to use OnTradeTransaction(...), because the transactions contain the ticket number, I could use this as identifier. But as i told before, that seems to be complicated. Why?
An example:
Let's say I have one open long position (L1), and a pending short order (S1).
If L1 takes profit, the transactions x1, x2, x3 are fired.
If S1 becomes a position, the transactions y1, y2, y3, y4, y5 are fired.

So if L1-take-profit and S1-trigger-price are near to each other (or think of fast markets or OrderSendAsync()) it could happen, that the transactions fired are: x1,y1,y2,x3,y4,x2,y3,y5. As the documentation states: the order of transactions is _not certain_. If I understand correctly, the transactions order can be totally mixed. Thats why I say it seems to be complicated.


[...]In this thread, toward the bottom of page one, chinaski posts[...]

This does only dump the transaction information, but does not go further <= and that's what I'm looking for.

I'm dreaming about an example, where someone "collects" and evaluates all the transactions (x1,y1,y2,x3,y4,x2,y3) and gives as an result:
- ok, pending order with ticket 123456 is a position now, doAnythingWithIt();
- and ok, open position with ticket 98765 took profit and is out now; doAnyThingElseWithThat();

But I think, this is really complicated and it's better to stay with selecting and looping :-)

Best regards,
Alex

 
Alex:

Ahhh just wait: I think I can use the MqlTradeRequest and MqlTradeResult params from OnTradeTransaction() to get the information I need. I was focussed on the transactions  too much, sorry for that!

Roger that. Now you have it.
 

Hi,

no its not working after all. Grrr, just dumped the OnTradeTransaction stuff and:

If I add a new pending there is a request and a response I can use simply, but if a pending order becomes a position, there is no request and no response. So adding is simple but changing is complicated as I wrote above. 

Going crazy here... fetching and looping ... !?

 
Maybe start from this article?
 
Alex:

no its not working after all. Grrr, just dumped the OnTradeTransaction stuff and:

If I add a new pending there is a request and a response I can use simply, but if a pending order becomes a position, there is no request and no response. So adding is simple but changing is complicated as I wrote above.

Maybe this code example will help.

MqlTradeTransaction contains all the things.

I've outlined a few conditionals for when certain things happen. You could fire off your own code at that point, e.g.doAnythingWithIt() and doAnyThingElseWithThat().

Use this code at your own risk. Caveat emptor and all that.

void  OnTradeTransaction(
    const MqlTradeTransaction&    trans,        // trade transaction structure
    const MqlTradeRequest&        request,      // request structure
    const MqlTradeResult&         result        // result structure
    )
{
    static ulong position = 0;

    if (
            (ENUM_DEAL_ENTRY)HistoryDealGetInteger(trans.deal,DEAL_ENTRY) == DEAL_ENTRY_IN && 
            trans.type == TRADE_TRANSACTION_ORDER_ADD &&
            trans.order_type == ORDER_TYPE_BUY_LIMIT
        )
    {
        Print(StringFormat("A BUY_LIMIT pending order [%d] has been added.", trans.order ));
    }
    if ( 
            (ENUM_DEAL_ENTRY)HistoryDealGetInteger(trans.deal,DEAL_ENTRY) == DEAL_ENTRY_IN && 
            trans.type == TRADE_TRANSACTION_DEAL_ADD && 
            trans.order == trans.position
        )
    {
        position = trans.order;
        Print(StringFormat("A limit order [%d] has been executed.", position));
    }
    if ( 
            (ENUM_DEAL_ENTRY)HistoryDealGetInteger(trans.deal,DEAL_ENTRY) == DEAL_ENTRY_IN && 
            trans.type == TRADE_TRANSACTION_DEAL_ADD &&
            trans.order != trans.position &&
            trans.position == position
        )
    {
        Print(StringFormat("More has been added to position [%d].", position));
    }
    if ( 
            (ENUM_DEAL_ENTRY)HistoryDealGetInteger(trans.deal,DEAL_ENTRY) == DEAL_ENTRY_OUT && 
            trans.type == TRADE_TRANSACTION_DEAL_ADD && 
            trans.position == position
        )
    {
        Print(StringFormat("Position [%d] has been closed.", position));
    }
}


 

Thank you both for link and sample! Will check that the next days, but I think it looks good!