MQL5 Cookbook: Getting Position Properties
Introduction
The previous article called "MQL5 Cookbook: Using Different Print Modes" showed us how we can quickly write a script and print the required information using three different modes. Let us now create a script that will get and display all position properties to the user.
We need to implement it in such a way so as to allow the user to select the appropriate option in the external parameters of the script, as follows: to either only get position properties on one (current) symbol or to run across all open positions (if any) one by one on all symbols. This time, we will view the required information right in the dialog box which is quite convenient and some of you might find this method more useful.
Writing a Script
The beginning of the program is more or less the same as in the previous article (see the code below). We start with the program properties. They are followed by the line with the #define directive and we then assign the program name to the SCRIPT_NAME variable using the MQLInfoString() function and the MQL5_PROGRAM_NAME constant it specifies. More information on all possible values of the MQLInfoString() function can be found in MQL5 Reference.
We continue with enumeration of the modes. If you write a comment for every identifier, the text of such comment will be displayed in the drop-down list in the external parameters. We will implement two options:
- Current symbol - to display position properties on the current symbol only, and
- All symbols - to display position properties on all symbols.
There is going to be only one external parameter (mode) to be used to select the appropriate mode. The comment following the external parameter will also be displayed in the window of external parameters. This will allow us to create more meaningful parameter names. At the same time shorter names of variables would be more convenient in terms of code.
#property copyright "Copyright 2012, http://tol64.blogspot.com" #property link "http://tol64.blogspot.com" #property description "email: hello.tol64@gmail.com" #property version "1.0" #property script_show_inputs //--- #define SCRIPT_NAME MQLInfoString(MQL_PROGRAM_NAME) // Script name //--- // ENUMERATION OF MODES enum ENUM_SYMBOLS_MODE { CURRENT_SYMBOL =0, // Current symbol ALL_SYMBOLS =1 // All symbols }; //--- // INPUT PARAMETERS input ENUM_SYMBOLS_MODE mode=CURRENT_SYMBOL; // Mode
The code continues with global variables. In order for global variables to be accessed from any part of the script, they should be placed outside of the functions (usually at the very beginning of the program).
// GLOBAL VARIABLES long pos_magic=0; // Magic number string pos_symbol=""; // Symbol string pos_comment=""; // Comment double pos_swap=0.0; // Swap double pos_commission=0.0; // Commission double pos_price=0.0; // Current price of the position double pos_cprice=0.0; // Current price of the position double pos_profit=0.0; // Profit/Loss of the position double pos_volume=0.0; // Position volume double pos_sl=0.0; // Stop Loss of the position double pos_tp=0.0; // Take Profit of the position datetime pos_time=NULL; // Position opening time long pos_id=0; // Position identifier ENUM_POSITION_TYPE pos_type=NULL; // Position type //---
In the main program function, we will call only one user-defined function, PrintPositionProperties(), that will perform all required operations:
//+------------------------------------------------------------------+ //| MAIN FUNCTION | //+------------------------------------------------------------------+ void OnStart() { PrintPositionProperties(); }
Let us now take a look at the structure of the user-defined PrintPositionProperties() function step by step. We will first form the base for our further work. It is very simple and when implemented looks as follows:
//+------------------------------------------------------------------+ //| OPENING A DIALOG BOX WITH SYMBOL DATA | //+------------------------------------------------------------------+ void PrintPositionProperties() { int err=0; // Variable for handling errors //--- // If you need to get position properties on the current symbol only if(mode==CURRENT_SYMBOL) { } //--- // If you need to get position properties on all symbols if(mode==ALL_SYMBOLS) { } }
We only have two branches and a local variable err which is responsible for handling errors and is declared at the beginning of the function. Now we need to write use case scenarios for each of the options. Let us start with the first one, i.e. "If you need to get position properties on the current symbol only".
It is very simple. First of all, we need to check if there is a position on the current symbol. This can be done by the PositionSelect() function available in MQL5 which takes the symbol name as the only parameter. To pass the current symbol name we need to either use the Symbol() function or the predefined variable _Symbol that already contains the current symbol name. The PositionSelect() function will return a positive result, if a position on that symbol exists, or a negative result, if there is no position or an error has occurred.
The code with detailed comments for the first option is provided below:
//--- // If a position exists, then... if(PositionSelect(_Symbol)) { // ...get its properties GetPositionProperties(); //--- // Open a dialog box to display all the data we obtained MessageBox("Symbol : "+pos_symbol+"\n"+ "Comment : "+pos_comment+"\n"+ "Magic Number : "+IntegerToString(pos_magic)+"\n"+ "Price Open : "+DoubleToString(pos_price,_Digits)+"\n"+ "Current Price : "+DoubleToString(pos_cprice,_Digits)+"\n"+ "Stop Loss : "+DoubleToString(pos_sl,_Digits)+"\n"+ "Take Profit : "+DoubleToString(pos_tp,_Digits)+"\n"+ "Type : "+PositionTypeToString(pos_type)+"\n"+ "Volume : "+DoubleToString(pos_volume,2)+"\n"+ "Commission : "+DoubleToString(pos_commission,2)+"\n"+ "Swap : "+DoubleToString(pos_swap,2)+"\n"+ "Profit : "+DoubleToString(pos_profit,2)+"\n"+ "Time : "+TimeToString(pos_time)+"\n"+ "Identifier : "+IntegerToString(pos_id)+"", //--- "Message Box",MB_ICONASTERISK); //--- return; } // If there is no position or an error has occurred, report it else { err=GetLastError(); // Get the code of the last registered error //--- if(err>0) // If there is an error { // Print the relevant message MessageBox("Error ("+IntegerToString(err)+") when selecting a position ("+_Symbol+") !\n\n"+ "It is possible that there is no position on this symbol. If this is not the case, please try again.", "Error", MB_ICONWARNING); //--- return; // Exit the function } } //---
In the code above, we can see two more user-defined functions - GetPositionProperties() and PositionTypeToString(). Since we will have to get position properties in various points throughout the program, it will be good to create a separate function in order to reduce the amount of code and thus make it more readable. Below is the code of this function. Be sure to check MQL5 Reference for additional information on the MQL5 functions and identifiers used in GetPositionProperties().
//+------------------------------------------------------------------+ //| GETTING SYMBOL PROPERTIES | //+------------------------------------------------------------------+ void GetPositionProperties() { pos_symbol =PositionGetString(POSITION_SYMBOL); pos_comment =PositionGetString(POSITION_COMMENT); pos_magic =PositionGetInteger(POSITION_MAGIC); pos_price =PositionGetDouble(POSITION_PRICE_OPEN); pos_cprice =PositionGetDouble(POSITION_PRICE_CURRENT); pos_sl =PositionGetDouble(POSITION_SL); pos_tp =PositionGetDouble(POSITION_TP); pos_type =(ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE); pos_volume =PositionGetDouble(POSITION_VOLUME); pos_commission =PositionGetDouble(POSITION_COMMISSION); pos_swap =PositionGetDouble(POSITION_SWAP); pos_profit =PositionGetDouble(POSITION_PROFIT); pos_time =(datetime)PositionGetInteger(POSITION_TIME); pos_id =PositionGetInteger(POSITION_IDENTIFIER); }
The user-defined PositionTypeToString() function converts position type returned as an integer to a string to read format, as shown in the code below:
//+------------------------------------------------------------------+ //| CONVERTING POSITION TYPE TO A STRING | //+------------------------------------------------------------------+ string PositionTypeToString(int position_type) { string str=""; //--- if(position_type==0) { str="buy"; } if(position_type==1) { str="sell"; } //--- return(str); }
So the code for the first option whereby we can view position properties only on the current symbol is ready. It can even be tested right now if you have followed all steps described in the article. Open a position in MetaTrader 5 using standard tools. For this purpose, press F9 and the Order window will open where you can find all necessary options to set position properties before it opens:
Fig. 1. The Order window in the MetaTrader 5 client terminal.
When all properties have been set, select either Sell or Buy and run the script by double-clicking or dragging it onto the chart. A script window will open. The required value (Current symbol) of the Mode parameter has already been set by default. A click on the OK button will open a dialog box displaying all position properties on the current symbol:
Fig. 2. Dialog box with position properties on the current symbol.
Otherwise, if there is no position on the current symbol, an alert box will appear:
Fig. 3. Alert box.
Everything seems to be working as planned and as implemented in the code.
Let us now review the program code that is going to be used if you choose to view all open position properties. The code with detailed comments is shown below:
//--- int digits=0; // Number of decimal places int mb_res=-1; // Variable with the option selected in the dialog box int pos_total=PositionsTotal(); // Number of open positions in the terminal //--- // View properties of all positions in a loop one by one for(int i=0; i<pos_total; i++) { ResetLastError(); // Reset the last error //--- pos_symbol=PositionGetSymbol(i); // Get the symbol name digits=(int)SymbolInfoInteger(pos_symbol,SYMBOL_DIGITS); // Get the number of digits in the price //--- // If a position on this symbol exists, then... if(PositionSelect(pos_symbol)) { // ...get its properties GetPositionProperties(); //--- // Open a dialog box to display all position properties obtained mb_res=MessageBox("Total Positions/Current: "+IntegerToString(pos_total)+"/"+IntegerToString(i+1)+"\n"+ "---------------------------------\n"+ "Symbol: " +pos_symbol+"\n"+ "Comment: " +pos_comment+"\n"+ "Magic Number: " +IntegerToString(pos_magic)+"\n"+ "Price Open: " +DoubleToString(pos_price,digits)+"\n"+ "Current Price: " +DoubleToString(pos_cprice,digits)+"\n"+ "Stop Loss: " +DoubleToString(pos_sl,digits)+"\n"+ "Take Profit: " +DoubleToString(pos_tp,digits)+"\n"+ "Type: " +PositionTypeToString(pos_type)+"\n"+ "Volume: " +DoubleToString(pos_volume,2)+"\n"+ "Commission: " +DoubleToString(pos_commission,2)+"\n"+ "Swap: " +DoubleToString(pos_swap,2)+"\n"+ "Profit: " +DoubleToString(pos_profit,2)+"\n"+ "Time: " +TimeToString(pos_time)+"\n"+ "Identifier: " +IntegerToString(pos_id)+"", //--- "Message Box",MB_CANCELTRYCONTINUE|MB_ICONASTERISK); //--- if(mb_res==IDCANCEL) // If you have clicked Cancel or Close { Print("The program ("+SCRIPT_NAME+") has been terminated by the user!"); return; } // Exit the function //--- // If you have clicked Retry if(mb_res==IDTRYAGAIN) { i--; } // Reset the counter to retry } else // If there is no position or an error has occurred, report it { err=GetLastError(); // Get the code of the last registered error //--- if(err>0) // If there is an error { // Print the relevant message MessageBox("Error ("+IntegerToString(err)+") when selecting a position ("+pos_symbol+") !\n\n"+ "It is possible that there is no position on this symbol. If this is not the case, please try again.", "Error", MB_ICONWARNING); } } } //---
Now we only need to test this option. Let us, for example, open positions on two symbols (AUDUSD and EURUSD). Once we run the script, select the All symbols mode in the drop-down list in the external parameters and click OK, a dialog box will open as shown below:
Fig. 4. Dialog box with position properties for the second option.
Conclusion
As you can see in the figure above, there are three buttons in the dialog box. If you click Retry, the loop counter will be reset and position properties for the symbol currently displayed in the dialog box will be refreshed. If you click Continue, the program will proceed to the next symbol. The Cancel button serves to terminate the program.
It should also be noted that the first line above the list of position properties contains information on the total number of open positions (Total Positions) and current number of the position counter (Current).
That's about it. Feel free to download the source code file attached below which will need to be compiled in MetaEditor.
Translated from Russian by MetaQuotes Ltd.
Original article: https://www.mql5.com/ru/articles/639
- Free trading apps
- Over 8,000 signals for copying
- Economic news for exploring financial markets
You agree to website policy and terms of use
Hi Anatoli,
I only just found these two articles 'cookbook' and am grateful for your efforts.
I have noticed with programs/scripts like this, they do not seem to recognize if there is more than one position on a particular currency pair.
For instance, if I have two positions open on the EURUSD (one sell at 1.2250, and the other sell at 1.2200), then it only recognizes the first one and not the second. I am not sure if this is because something has to tell the program/script that its an account which allows hedging? Do you have any articles that deals with scripts that recognizes multiple positions on the one currency pair?
Many thanks
Dingo
Hi Anatoli,
I only just found these two articles 'cookbook' and am grateful for your efforts.
I have noticed with programs/scripts like this, they do not seem to recognize if there is more than one position on a particular currency pair.
For instance, if I have two positions open on the EURUSD (one sell at 1.2250, and the other sell at 1.2200), then it only recognizes the first one and not the second. I am not sure if this is because something has to tell the program/script that its an account which allows hedging? Do you have any articles that deals with scripts that recognizes multiple positions on the one currency pair?
Many thanks
Dingo
Hey!
I know it's been a while since you posted this. Indeed, I think the first method will only pick up the first order in the pos for the given symbol. To read all trades from a specific symbol, you'd need to adapt the second variant to the script (all trades) and just add an if "filter" to where it procedes only if the order symbol is the same as the current given symbol.
Hope it helps.
-Fernando.