how to reliably get current bid/ask?

To add comments, please log in or register
Dwaine Hinds
280
Dwaine Hinds  
As customary, many of us will use:
SymbolInfoDouble(NULL,SYMBOL_BID);

or

SymbolInfoDouble(NULL,SYMBOL_ASK);

or

MarketInfo(NULL,MODE_ASK);

and those will work ok most of the time, however, for some of us they return 0 while implemented in the Strategy Tester. I am presenting here an alternative that, I hope, will be more consistent(both live and testing) and that will be more suited to multicurrency situations. This has worked for me:

//+------------------------------------------------------------------+
//| SymbolInfoDouble2                                                      |
//+------------------------------------------------------------------+
/*
 Calculate latest received prices such as ask,bid...
*/
double SymbolInfoDouble2(string name, ENUM_SYMBOL_INFO_DOUBLE prop_id, ENUM_TIMEFRAMES ChartTimeframe=0)
{
 MqlRates rates[2];//rates[100]; //change this according to the situation but i think 100 bars is sufficient for this. 
 int copied=-1,i=0,h=0,StartPos=0,BarCount=1;
 bool result=false;
 string out,AppliedPrice="high";
 double data_val=0,currentspread=0,result_val=0; 
 copied=CopyRates(name,ChartTimeframe,StartPos,BarCount,rates); 
      //transfer copied bars to result array
     if(copied >= BarCount) 
     {  
      i = BarCount;
         while(BarCount > 0 && i > 0) //use a if statement here
         { 
          i--;
          out=IntegerToString(i)+" tick time:"+TimeToString(rates[i].time); 
             if(AppliedPrice == "open")
             {
              data_val = rates[i].open;
             }
             else if(AppliedPrice == "high")
             {
              data_val = rates[i].high;
             }
             else if(AppliedPrice == "low")
             {
              data_val = rates[i].low;
             }
             else if(AppliedPrice == "close")
             {
              data_val = rates[i].close;
             } 
          currentspread = (double)rates[i].spread;   
              
             //remember currentspread = ask-bid;              
             if(prop_id == SYMBOL_BID)
             {
              result_val = data_val;
             }  
             //therefore currentspread + bid = ask; 
             else if(prop_id == SYMBOL_ASK)
             {
              result_val = currentspread + data_val;
             }    
             else if(prop_id == SYMBOL_POINT)
             {
              //i don't need this, maybe someone can complete here
             }                                                             
         }   
      //Print("Bars copied: "+IntegerToString(copied));   
     } 
     else Print("SymbolInfoDouble2 failed to get historical data for the symbol ",name);
 return result_val;      
}
//+------------------------------------------------------------------+
//| End of SymbolInfoDouble2                                               |
//+------------------------------------------------------------------+


Example usage1:

double ask = SymbolInfoDouble2(NULL,SYMBOL_ASK); //variable "ask" now has the latest ask price that has been downloaded.
Just use SymbolInfoDouble2() the same way like SymbolInfoDouble(). Now there are more capabilities to add but this is sufficient for me.
lippmaje
1055
lippmaje  

It's recommended to use SymbolInfoTick to query current Bid and Ask. Not sure though if CopyRates will do it better, and it will be slower for sure.

    MqlTick tick;
    if(!SymbolInfoTick(_Symbol,tick)) { Print("no tick data available, error = ",GetLastError()); ExpertRemove(); return; }
    double Ask=tick.ask;
    double Bid=tick.bid;
Dwaine Hinds
280
Dwaine Hinds  
lippmaje:

It's recommended to use SymbolInfoTick to query current Bid and Ask. Not sure though if CopyRates will do it better, and it will be slower for sure.

I just tested "SymbolInfoTick(_Symbol,tick)" and it gave me the same result as "SymbolInfoDouble2", so I guess I will have to agree with you that it might be quicker. 

William Roeder
20233
William Roeder  
SymbolInfoDouble(NULL,SYMBOL_BID);

or

SymbolInfoDouble(NULL,SYMBOL_ASK);

or

MarketInfo(NULL,MODE_ASK);
Don't use NULL.
  • You can use NULL in place of _Symbol only in those calls that the documentation specially says you can. iHigh does, iCustom does, MarketInfo does not. OrderSend does not.
  • Don't use NULL (except for pointers where you explicitly check for it.) Use _Symbol and _Period, that is minimalist as possible and more efficient.
  • Zero is the same as PERIOD_CURRENT which means _Period. Don't hard code numbers.
To add comments, please log in or register