Calculate profit/loss for open Positions based on set SL

 

Hello All,

I have been struggling to create a MQL5 function to return the equity change for a position based on it's SL set. I have something that seems to almost work but the exchange rate conversion to account currency does not work, and in another instance I am two decimal places too much to the left. If anyone can assist please help, my brain is hurting. 


/*
_dAccountEquityLockedIn()
#########################
Takes all open positions's SL into consideration and calculates the locked in account equity. 
*/
double _dAccountEquityLockedIn() {

        double dPositionsEquityInAccountCurrency = 0;
        for (int i=0;i<PositionsTotal();i++) { 
                int iPositionTicket = PositionGetTicket(i);
                
                // detect if there are positions 
                if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY ) {
                        double dExchangeRateToAccountCurrency=1/SymbolInfoDouble(PositionGetString(POSITION_SYMBOL),SYMBOL_TRADE_TICK_VALUE);
                        
                        double dPositionOpenOneLotValue = SymbolInfoDouble(Symbol(),SYMBOL_TRADE_CONTRACT_SIZE) * PositionGetDouble(POSITION_PRICE_OPEN);
                        double dPositionOpenValue = dPositionOpenOneLotValue * PositionGetDouble(POSITION_VOLUME) ;
                        
                        double dPositionSLOneLotValue = SymbolInfoDouble(Symbol(),SYMBOL_TRADE_CONTRACT_SIZE) * PositionGetDouble(POSITION_SL);
                        double dPositionSLValue = dPositionSLOneLotValue * PositionGetDouble(POSITION_VOLUME) ;
                        
                        double dEquityChange = dExchangeRateToAccountCurrency * (dPositionSLValue - dPositionOpenValue);
                        
                        dPositionsEquityInAccountCurrency += dEquityChange;
                }
        }
        return dPositionsEquityInAccountCurrency;
}
 

As per 'https://www.mql5.com/en/docs/constants/environment_state/marketinfoconstants#enum_symbol_calc_mode' I have simplified the code to:

double dPriceChange =  (PositionGetDouble(POSITION_SL) - PositionGetDouble(POSITION_PRICE_OPEN))
                       * PositionGetDouble(POSITION_VOLUME) * SymbolInfoDouble(Symbol(),SYMBOL_TRADE_CONTRACT_SIZE);

However one instrument (US500Index) has the decimal in wrong place, instead of `2.84` profit as per MetaTrader5 UI the debug log outputs `0.28`. I examined the specifications and compared it to a working one 'USTECHIndex' and can not determine why, would anyone have some ideas?

Documentation on MQL5: Standard Constants, Enumerations and Structures / Environment State / Symbol Properties
Documentation on MQL5: Standard Constants, Enumerations and Structures / Environment State / Symbol Properties
  • www.mql5.com
To obtain the current market information there are several functions: SymbolInfoInteger(), SymbolInfoDouble() and SymbolInfoString(). The first parameter is the symbol name, the values of the second function parameter can be one of the identifiers of ENUM_SYMBOL_INFO_INTEGER, ENUM_SYMBOL_INFO_DOUBLE and ENUM_SYMBOL_INFO_STRING. Some symbols...
 
danielsokolowsk:

Hello All,

I have been struggling to create a MQL5 function to return the equity change for a position based on it's SL set. I have something that seems to almost work but the exchange rate conversion to account currency does not work, and in another instance I am two decimal places too much to the left. If anyone can assist please help, my brain is hurting. 


It's over complicated.

Tick value already takes into consideration contract size.

The position SL has nothing to do with current PL on open positions.

If you want help please post a code that compiles and that we can try. 

 

Below is the code distilled to minimum, in plain English I am attempting to find out my locked in equity change based on SL for long positions. Or put it another way, I'd like to get the same value shown when you drag a SL line around in the UI, it tells you in pips and account base currency the profit or loss.

My tries are not working, the debug output should be $-8.19 but I am getting following results depending on the approach I am trying...I'm sure the answer is going to be one of those slap on the forehead moments. 


2018.01.30 22:09:31.616 DS_DevelopmentHelper2 (NAS100,D1)       `NAS100`, `dEquityChange=-8.186000000000059`, `dPriceChange=-81.85999999999967`, `dTEMP=-818.5999999999967`

2018.01.30 22:12:54.019 DS_DevelopmentHelper2 (AUDCAD,D1)       `AUDCAD`, `dEquityChange=-0.0006020000000000074`, `dPriceChange=-60.19999999999914`, `dTEMP=-0.0007418506199999893`


Indicator Code

int OnInit() {
   return(INIT_SUCCEEDED);
}
  
int OnCalculate(const int iSeriesTotal,
                const int prev_calculated,
                const datetime &time[],
                const double &aOpen[],
                const double &aHigh[],
                const double &aLow[],
                const double &aClose[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
        string sComment = "";
        
        sComment += "\n`_dAccountEquityLockedIn()=" + _dAccountEquityLockedIn() + "`";
        
        Comment(sComment);
        return(iSeriesTotal);
}



/*
Deinitialization
================

The OnDeinit() function is called during deinitialization and is the Deinit event handler. 
*/
void OnDeinit(const int reason) {
} 


/*
_dAccountEquityLockedIn()
#########################
Takes all open positions's SL into consideration and calculates the locked in account equity. 
*/
double _dAccountEquityLockedIn() {

        double dPositionsEquityInAccountCurrency = 0;
        for (int i=0;i<PositionsTotal();i++) { 
                int iPositionTicket = PositionGetTicket(i);
                
                if (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY ) {

                        // almost working below
                        double dExchangeRateToAccountCurrency=1/SymbolInfoDouble(PositionGetString(POSITION_SYMBOL),SYMBOL_TRADE_TICK_VALUE); //TODO: is this correct to use SYMBOL_TRADE_TICK_VALUE_LOSS
                        double dPositionOpenOneLotValue = SymbolInfoDouble(Symbol(),SYMBOL_TRADE_CONTRACT_SIZE) * PositionGetDouble(POSITION_PRICE_OPEN);
                        double dPositionOpenValue = dPositionOpenOneLotValue * PositionGetDouble(POSITION_VOLUME) ;
                        
                        double dPositionSLOneLotValue = SymbolInfoDouble(Symbol(),SYMBOL_TRADE_CONTRACT_SIZE) * PositionGetDouble(POSITION_SL);
                        double dPositionSLValue = dPositionSLOneLotValue * PositionGetDouble(POSITION_VOLUME) ;
                        
                        double dEquityChange = dExchangeRateToAccountCurrency * (dPositionSLValue - dPositionOpenValue);

                        // try 3
                        double dPriceChange =  
                                (PositionGetDouble(POSITION_SL) - PositionGetDouble(POSITION_PRICE_OPEN))
                                * PositionGetDouble(POSITION_VOLUME) * SymbolInfoDouble(Symbol(),SYMBOL_TRADE_CONTRACT_SIZE);
                        
                        
                        // try 4 after 
                        double dTEMP = ((PositionGetDouble(POSITION_SL) - PositionGetDouble(POSITION_PRICE_OPEN)) / SymbolInfoDouble(Symbol(),SYMBOL_TRADE_TICK_VALUE)) * PositionGetDouble(POSITION_VOLUME);
                        
                        Print(
                        
                                "`" + PositionGetString(POSITION_SYMBOL) 
                                + "`, `dEquityChange=" + dEquityChange 
                                + "`, `dPriceChange=" + dPriceChange 
                                + "`, `dTEMP=" + dTEMP 
                                + "`"
                                );

                // dPositionsEquityInAccountCurrency += dEquityChange;


                }
        }
        return dPositionsEquityInAccountCurrency;
}
 
void OnStart()
  {
//---
   int total=PositionsTotal();
   for(int i=0;i<total;i++)
     {
      ulong ticket      = PositionGetTicket(i);
      int dir           = (PositionGetInteger(POSITION_TYPE)==POSITION_TYPE_BUY ? 1 : -1);
      string symbol     = PositionGetString(POSITION_SYMBOL);
      double tv         = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_VALUE_LOSS);
      double ts         = SymbolInfoDouble(symbol,SYMBOL_TRADE_TICK_SIZE);      
      double sldistance = dir*(PositionGetDouble(POSITION_SL)-PositionGetDouble(POSITION_PRICE_OPEN));
      double pl         = (sldistance/ts)*tv*PositionGetDouble(POSITION_VOLUME);;
      //---      
      printf("%s SL is %.2f %s",symbol,pl,AccountInfoString(ACCOUNT_CURRENCY));
     }   
  }

However one instrument (US500Index) has the decimal in wrong place, instead of `2.84` profit as per MetaTrader5 UI the debug log outputs `0.28`. 

Please note that the value returned for tick value is not always reliable. That's broker's responsibility to set it correctly. In such case, you will have to calculate it yourself.

Example on Alpari-MT5 (real account) :

2018.01.30 22:54:20.064 226033 (SPX500,H1) SPX500 tv 1.00000 ts 0.10000 USD  should be 10.0

2018.01.30 22:54:34.811 226033 (XAUUSD,H1) XAUUSD tv 0.01000 ts 0.00100 USD should be 0.1

 
Alain Verleyen:

.... In such case, you will have to calculate it yourself

A small hint how to calculate by myself?

Thank you very much.
 
Frika:

A small hint how to calculate by myself?

Thank you very much.
Define precisely what is the value of a tick. Then code it.