Why SymbolInfoDouble returns le-05

Hi,

My apologies if this has been addressed before:

Print(SymbolInfoDouble("EURUSD",SYMBOL_POINT));

is returning le-05


Print(SymbolInfoDouble("GBPJPY",SYMBOL_POINT)); 

is returning 0.001 which is correct

I cant understand why EURUSD and GBPUSD etc all return le-05?

MT5 version 5 build 1940.

Any help would be greatly appreciated

“le-05” is just a different representation of “0.00001” which is correct fo EUR/USD. It is simply because you are using the default representation of “Print” instead of defining your own.

Thank you for your response.

problem is when i run this:


orderPriceCurrent = PositionGetDouble(POSITION_PRICE_CURRENT);

orderPips = (NormalizeDouble(((PositionGetDouble(POSITION_PRICE_OPEN) - orderPriceCurrent)/SymbolInfoDouble(POSITION_SYMBOL,SYMBOL_TRADE_TICK_VALUE)),SymbolInfoInteger(POSITION_SYMBOL,SYMBOL_DIGITS))/10);

i get an error for diving by zero. I have broken this down and everything gives a correct value except for SymbolInfoDouble(“EURUSD”,SYMBOL_POINT)); It works fine on symbols with 3 digits though.

works perfectly in MQL4 ?

That is absolutely horrible code to read or debug. Use variables and break it up.

Plus that is MQL5 Code, not MQL4 Code. The functions PositionGetDouble() and the enumeration constants POSITION_SYMBOL , POSITION_PRICE_OPEN , etc. are only valid in a MQL5 environment, not MQL4.

Sorry i wasnt very clear… thats been adapted for MQL5. The MQL4 version:

orderPips = MathAbs((NormalizeDouble(((orderPriceCurrent - OrderOpenPrice())/MarketInfo(OrderSymbol(),MODE_POINT)),MarketInfo(OrderSymbol(),MODE_DIGITS)))/10);

That works with all symbols with no problem at all.

MQL5:

orderPips = (NormalizeDouble(((PositionGetDouble(POSITION_PRICE_OPEN) - orderPriceCurrent)/SymbolInfoDouble(POSITION_SYMBOL,SYMBOL_POINT)),SymbolInfoInteger(POSITION_SYMBOL,SYMBOL_DIGITS))/10);

Broken down:

double output = PositionGetDouble(POSITION_PRICE_OPEN) - orderPriceCurrent;

= - 0.002200000 (correct) double output_2 = SymbolInfoDouble(“EURUSD”,SYMBOL_POINT);
= le-05 <- this seems to break it down

int output_3 = SymbolInfoInteger(“EURUSD”,SYMBOL_DIGITS);

= 5 (correct)

Basically im trying to get the pip gain / loss on open orders in MQL5. Ive started converting my MQL4 scripts and have now run into this problem.

Your error is in the use of POSITION_SYMBOL , which is an enumeration constant. If you want to derive the actual symbol then you have use the function to get it and not the enumeration constant.

string position_symbol = PositionGetString( POSITION_SYMBOL );

Also, I was not suggesting that you break it down just for testing purposes, but telling you to properly structure and breakdown the code in the real implementation.

sadly same result…


      string ticket = PositionGetTicket(219405612); (ticket that is currently open)

      double orderPriceCurrent = PositionGetDouble(POSITION_PRICE_CURRENT);

      string position_symbol = PositionGetString( POSITION_SYMBOL );

      double price_difference = PositionGetDouble(POSITION_PRICE_OPEN) - orderPriceCurrent;

      double point = SymbolInfoDouble(position_symbol,SYMBOL_POINT);

      int digits = SymbolInfoInteger(position_symbol,SYMBOL_DIGITS);

      Print("Difference: " + price_difference + " Point: " + point + " Digits: " + digits);

2018.11.09 17:01:11.995 Slave_Reader_CopyTrade_BTI_test (EURUSD,H1) Difference: 0.0 Point: 1e-05 Digits: 5

Your code is riddled with problems.

  1. Print out the value of each variable and step to see where it fails!

  2. The position ticket is a “ulong”, not a “string”.

  3. When printing the point size, use “digits” to properly format it.

  4. Where is the your code to select the position first?

ulong ticket = 219405612;

if( PositionSelectByTicket( ticket ) )
{
   // The rest of the code here

   Print( "Point Size: ", DoubleToString( point, digits ) );
}

In addition to Fernando’s comments, why are you punishing yourself by using all super-verbose low-level abstractions when the standard library has well documented wrappers to handle all that unnecessary repeating yourself. This is how developing in MQL5 should be…

#include <Trade\Trade.mqh>
void OnStart()
{  
   CSymbolInfo s;
   CPositionInfo p;
   for(int i=PositionsTotal()-1; i>=0; --i){
      if(p.SelectByIndex(i) && s.Name(p.Symbol())){
         double pips = p.PriceCurrent() - p.PriceOpen();
         if(p.PositionType() == POSITION_TYPE_SELL)
            pips = -pips;
         pips = s.NormalizePrice(pips / s.Point() / 10);
         printf("%s: %s = %.1f pips", 
            s.Name(), p.TypeDescription(), pips
         );
      }
   }
}

I have extracted segments for testing.


      ulong ticket = PositionSelectByTicket(219405612);

      string position_symbol = PositionGetString(POSITION_SYMBOL);

      double orderPriceCurrent = PositionGetDouble(POSITION_PRICE_CURRENT);      

      double price_difference = PositionGetDouble(POSITION_PRICE_OPEN) - orderPriceCurrent;

      double point = SymbolInfoDouble(position_symbol,SYMBOL_POINT);

      int digits = SymbolInfoInteger(position_symbol,SYMBOL_DIGITS);

      Print("Difference: " + price_difference + " Point: " + point + " Digits: " + digits);

OUTPUT: 2018.11.09 17:14:02.667 Slave_Reader_CopyTrade_BTI_test (EURUSD,H1) Difference: -0.000220000000000109 Point: 1e-05 Digits: 5

All works up till then normally.

If it wasn’t obvious, you cannot concatenate strings to doubles. Furthermore, you need to either use DoubleToString when casting double to string type OR use a format specifier in conjunction with StringFormat/printf

You are still doing it wrong. PositionSelectByTicket does not return a ticket, it returns a “boolean” which should be checked, as shown in my sample code. You even ignored the formatting example.

I know you mean well and want to help, but if the OP barely understands the basics of procedural programming, how do you expect him to fathom libraries, classes and OOP?

Let him first grasp the basics before complicating things for him with advanced coding techniques.

here is the actual code complete with all other statements. everything works as it should with the exception of the pip calculation. It worked fine on MQL4 for 3 years and I am only battling now as I have to convert to MQL5. As I said, everything else updates as it should.

 for(uint i=0;i<total;i++) { 

                  //--- return order ticket by its position in the list 

                  if((ticket=PositionGetTicket(i))>0){ 

                     //--- return order properties 

                        open_price    =PositionGetDouble(POSITION_PRICE_OPEN); 

                        time_setup    =(datetime)PositionGetInteger(POSITION_TIME); 

                        symbol        =PositionGetString(POSITION_SYMBOL); 

                        order_magic   =PositionGetInteger(POSITION_MAGIC); 

                        initial_volume=PositionGetDouble(POSITION_VOLUME); 

                        type          =EnumToString(ENUM_ORDER_TYPE(PositionGetInteger(POSITION_TYPE))); 

                     //--- prepare and show information about the order        

                        

                        //Print(ORDER_PRICE_CURRENT);

                           double orderProfit = PositionGetDouble(POSITION_PROFIT);

                           double orderSwap = PositionGetDouble(POSITION_SWAP);

                           double orderCommission = PositionGetDouble(POSITION_COMMISSION);

                           double orderStoploss = PositionGetDouble(POSITION_SL);

                           double orderTakeProfit = PositionGetDouble(POSITION_TP);

                           double orderPriceCurrent;

                           double orderPriceClose;

                           int orderTicket = ticket;

                           int orderInProfit;

                           int orderType;

                           int tradeDirection;

                           int tradeStatus;

                                 

                           if(type == 0){tradeDirection = 0; orderType = 0;}

                           if(type == 1){tradeDirection = 1; orderType = 1;}

                           string orderOpenTime = PositionGetInteger(POSITION_TIME);

                           string orderCloseTime = DEAL_ENTRY_OUT;

                           string orderVolume = PositionGetDouble(POSITION_VOLUME);          

            

                           if(orderCloseTime > 1){tradeStatus = 0;} else {tradeStatus = 1;}

                           orderPriceCurrent = PositionGetDouble(POSITION_PRICE_CURRENT);

                           if(tradeStatus  == 0){orderPriceClose = PositionGetDouble(POSITION_PRICE_CURRENT);} else {orderPriceClose = "";}     

                           

                           //check if ticket exists with same account number and if open

                           string rowQuery2 = "SELECT number, ticket FROM transactions_slave WHERE number = '"+accountNumber+"' && ticket = '"+orderTicket+"' LIMIT 1";

                           long row_result2 = MySqlCursorOpen(dbConnectId, rowQuery2);         

                           

                           //if not found, then insert into database (order open from M30 etc), set flag = 1

                           if(MySqlCursorRows(row_result2) == 0){

                           

                              //write to database

                              string rowQuery3 = "INSERT INTO `transactions_slave` (ticket, symbol, type, volume, price, slippage, stoploss, takeprofit, comment_open, comment_close, magicnumber, expiration, arrow_colour, period, status, spread, verify_status, number) VALUES ('"+orderTicket+"','"+PositionGetString(POSITION_SYMBOL)+"','"+type+"','"+PositionGetDouble(POSITION_VOLUME)+"','"+PositionGetDouble(POSITION_PRICE_OPEN)+"','','"+PositionGetDouble(POSITION_SL)+"','"+PositionGetDouble(POSITION_TP)+"','"+PositionGetString(POSITION_COMMENT)+"','""','"+PositionGetInteger(POSITION_MAGIC)+"','','clr','"+Period()+"','1','','1','"+accountNumber+"') ";  

                              long insert_result3 = MySqlExecute(dbConnectId, rowQuery3);      

                           

                           } else {

                           

                              int point_compat = 10;

                              if(_Digits == 3 || _Digits == 5) point_compat = 10;

                              double orderPips;

                              string position_symbol = PositionGetString(POSITION_SYMBOL);

                              

                              if(orderType == 0){ //buy order

                                 orderPips = MathAbs((NormalizeDouble(((orderPriceCurrent - PositionGetDouble(POSITION_PRICE_OPEN))/SymbolInfoDouble(position_symbol,SYMBOL_POINT)),SymbolInfoInteger(position_symbol,SYMBOL_DIGITS)))/point_compat); //price 2 is current, price 1 is open

                                 if(orderPriceCurrent < PositionGetDouble(POSITION_PRICE_OPEN)){orderPips = orderPips * -1;}

                              }                   

                              if(orderType == 1){ // sell order

                                 orderPips = MathAbs((NormalizeDouble(((PositionGetDouble(POSITION_PRICE_OPEN) - orderPriceCurrent)/SymbolInfoDouble(position_symbol,SYMBOL_POINT)),SymbolInfoInteger(position_symbol,SYMBOL_DIGITS)))/point_compat); //price 1 is open, price 2 is current

                                 if(orderPriceCurrent > PositionGetDouble(POSITION_PRICE_OPEN)){orderPips = orderPips * -1;}

                              }

                              

                              //Print("Open Price:" +OrderOpenPrice()+ "Current Price: " +orderPriceCurrent+ "Pips: " +orderPips);         

                              

                              //if ticket does exit then update info

                              string rowQuery4 = "UPDATE transactions_slave SET volume = '"+orderVolume+"', pips = '"+orderPips+"', type = '"+orderType+"', profit = '"+orderProfit+"', swap = '"+orderSwap+"', commission = '"+orderCommission+"', stoploss = '"+orderStoploss+"', takeprofit = '"+orderTakeProfit+"', price_current = '"+orderPriceCurrent+"', order_open_time = '"+orderOpenTime+"', order_close_time = '"+orderCloseTime+"', price_close = '"+orderPriceClose+"', verify_status = '1' WHERE ticket = '"+orderTicket+"' LIMIT 1";  

                              long row_result4 = MySqlExecute(dbConnectId, rowQuery4);

                           }

                           MySqlCursorClose(row_result2); 

                     

                     //do this in same loop

                  //}

                   }

                   

                }

This updates every 10 seconds:
![image__23|690x137](upload://j0JRVeCSJkKqpHg8Y5yHtcPzxu9.png) 

The only missing info is the pips. Everything else is correct.

OOP isn’t the scary and “advanced” concept every here tries to make it out to be. Heck, my son is even learning it in his python class in middle-school.

If you’re working with MQL5, you can’t get around without knowing OOP, and I would argue that cluttering up your src file with 1000 character lines full of nested function lt to mentally parse than any OOP code I’ve ever seen.

Please trust me when I say this, and I am not the only one saying it: For most users, OOP is too complicated and difficult to understand. It is in fact “scary” for them!

Whether you find it easy or not is besides the point. Most users, even seasoned ones, try to stay away from it. They prefer writing 1000 extra lines of code than to face using OOP. That is just the reality of things!

So please understand that ramming it down throats will not help and it will actually just make them resent it even more.

What I would suggest, is a middle ground, where you present both a Procedural sample as well as the OOP version, so that they can see both and decide for themselves. By seeing both versions, they can then understand the OOP version better and may even be tempted to try develop their skills in OOP. But if you only provide the OOP version, they will most probably just skip over it all together.

I have come from a Java background and honestly I like a challenge but wont go close to OOP. Its just my preference as I find it easier to debug and read later on again.

That is the wrong attitude in proper coding because you could be introducing bugs. Always make sure everything is properly coded and compiling with no errors or warnings before looking for bugs. It will save you time in debugging.

This pip thing is the only thing i cant resolve. Everything else works perfectly after changing over. Yes I know there are errors with conversions etc and I fully respect everyone’s feedback on this.

I totally understand that however it still yields le-05 even with the changes you advised. Even more so if I only use that small portion of code and compile it without the other code. It amazes me that it works perfectly for 3 digits but not 5?