Retrieve profit by position, best practice?

 
Hey all!

I have doubts about the best way to handle working with the trade history.

I'm aware a single position can result in multiple deals when closing it. For example, if I'm looking for coding a martingale system based on closed trades, what would be the best approach to handle reading the trade history?

So far I've found some examples that either read just deals, but most of them operate on the assumption a position will be closed in a single deal, or the https://www.mql5.com/en/code/27683 library (or similar approaches), that add up various deals groupped by position, however, by design (at least I think), it involves iterating multiple times on the history to retrieve all deals from a position, which I'm not sure is just the way we gotta do it on MT5, or if it's a bad practice as there's a better way similar to MT4 where you just get the history tallied up on a per-trade basis, in MT5 lingo, it'd be per-position basis.

Another question I have about trade history is, if I open a 10 lots trade, and then decide to close 5 lots out of it, would that result in a new position ID, both in the remaining half running, and in the deal(s) associated with the closed half, or both the closed half and the running half will be associated with the same position ID?

Thanks in advanced, I'm still learning about MQL5 and the best ways to migrate code from MQL4 to it, so any guidance is appreciated.
 

If you don't already know the Position ID, then you can scan through the Orders history to get a list of Position ID's.

Then use each position ID with HistorySelectByPosition() to get access to all the deals for that position.

You can then scan through the resulting set with HistoryDealGetTicket(), of the the total number returned by HistoryDealsTotal().

 
Fernando Jose Velasco Borea: Another question I have about trade history is, if I open a 10 lots trade, and then decide to close 5 lots out of it, would that result in a new position ID, both in the remaining half running, and in the deal(s) associated with the closed half, or both the closed half and the running half will be associated with the same position ID?

No, on MT5, the position ID does not change after a parcial close.

 
Fernando Carreiro #:

If you don't already know the Position ID, then you can scan through the Orders history to get a list of Position ID's.

Then use each position ID with HistorySelectByPosition() to get access to all the deals for that position.

You can then scan through the resulting set with HistoryDealGetTicket(), of the the total number returned by HistoryDealsTotal().

If I don't know the position ID, and rather want to iterate on closed positions, what would be the best approach?
 
Fernando Jose Velasco Borea #: If I don't know the position ID, and rather want to iterate on closed positions, what would be the best approach?

I've already answered ... "If you don't already know the Position ID, then you can scan through the Orders history to get a list of Position ID's."

For a better understanding, please read the following ...

Articles

Orders, Positions and Deals in MetaTrader 5

MetaQuotes, 2011.02.01 16:13

Creating a robust trading robot cannot be done without an understanding of the mechanisms of the MetaTrader 5 trading system. The client terminal receives the information about the positions, orders, and deals from the trading server. To handle this data properly using the MQL5, it's necessary to have a good understanding of the interaction between the MQL5-program and the client terminal.
 
Fernando Carreiro #:

I've already answered ... "If you don't already know the Position ID, then you can scan through the Orders history to get a list of Position ID's."

For a better understanding, please read the following ...

Oh, my bad, for some reason I didn't noticed the "don't". So, to summarize:

-Scan the closed orders with HistoryOrdersTotal()

-Iterate through the orders and retrieve the associated ticket with HistoryOrderGetTicket() given that the order was a market order and not a pending order

-Select all related deals with HistorySelectByPosition(<ticket>)

-Iterate on them using HistoryDealsTotal().

Would that be the workflow?

 
Fernando Jose Velasco Borea #:

Oh, my bad, for some reason I didn't noticed the "don't". So, to summarize:

-Scan the closed orders with HistoryOrdersTotal()

-Iterate through the orders and retrieve the associated ticket with HistoryOrderGetTicket() given that the order was a market order and not a pending order

-Select all related deals with HistorySelectByPosition(<ticket>)

-Iterate on them using HistoryDealsTotal().

Would that be the workflow?

Almost but not quite ...

First you have to select the total orders to scan:

HistorySelect

Retrieves the history of transactions and orders for the specified period of the server time

Then you can retrieve the total Order count and iterate over them using:

HistoryDealsTotal

Returns the number of deals in the history

HistoryDealGetTicket

Returns a ticket of a corresponding deal in the history

And for each iteration, retrieve the Position ID with:

OrderGetInteger

Returns the requested property of the order (datetime or int)

ORDER_POSITION_ID

Position identifier that is set to an order as soon as it is executed. Each executed order results in a deal that opens or modifies an already existing position. The identifier of exactly this position is set to the executed order at this moment.

You have to collect ALL the Positions IDs first before proceeding. You cannot do the next step on each iteration or else that will mess up the cache.

So, only once you have collected all the position IDs, can you then use:

HistorySelectByPosition

Requests the history of deals with a specified position identifier.

And proceed with scanning the deals with:

HistoryDealsTotal

Returns the number of deals in the history

HistoryDealGetTicket

Returns a ticket of a corresponding deal in the history

 
Fernando Carreiro #:

Almost but not quite ...

First you have to select the total orders to scan:

HistorySelect

Retrieves the history of transactions and orders for the specified period of the server time

Then you can retrieve the total Order count and iterate over them using:

HistoryDealsTotal

Returns the number of deals in the history

HistoryDealGetTicket

Returns a ticket of a corresponding deal in the history

And for each iteration, retrieve the Position ID with:

OrderGetInteger

Returns the requested property of the order (datetime or int)

ORDER_POSITION_ID

Position identifier that is set to an order as soon as it is executed. Each executed order results in a deal that opens or modifies an already existing position. The identifier of exactly this position is set to the executed order at this moment.

You have to collect ALL the Positions IDs first before proceeding. You cannot do the next step on each iteration or else that will mess up the cache.

So, only once you have collected all the position IDs, can you then use:

HistorySelectByPosition

Requests the history of deals with a specified position identifier.

And proceed with scanning the deals with:

HistoryDealsTotal

Returns the number of deals in the history

HistoryDealGetTicket

Returns a ticket of a corresponding deal in the history

Thanks!!

So, I've been putting some brain juice into this. Since each deal has a position ID associated, would it be reasonable to use an approach like this:

-Create a struct globally with two fields, one for the position ID and another as an array to store the deal ticket (or even an array to store another structure with the desired deal info). Let's name this history_positions.

-Create an array of history_positions.

-Iterate on all deals on history

-Extract the position ID and save it on a temp variable

-Save the position ID as a new instance of the position_history structure, and save the deal ticket to that same structure array for the deals.

-If on the next iteration the position ID matches the one in the temp var, we're on a deal from the same position, thus, the deal info would be saved to the same structure instance.

-If it doesn't match, a new instance will be created and the temp var would be updated with the new position ID.

I guess that'd work but the catch is since partial closes doesn't alter the position ID, it might lead to duplicates, or if for some reason the deal order in the history gets alternated between positions, it'd also lead to problems. Perhaps that could be solved by searching the array for existing an position ID first, or creating a temp array just for the seen positions ID so it's faster to search on them, but it'd defeat the purpose of avoiding the doble iteration.

Another more fancy approach I can think of is instead of creating an array of the structure, create a linked list or hash table, but I'm just not sure if the performance in runtime would be just too small to justify the code complexity.

Just thinking out loud here, happy to hear your thoughts!
Reason: