//+------------------------------------------------------------------+
//|                                                SpreadSampler.mqh |
//+------------------------------------------------------------------+
#ifndef SPREADSAMPLER_MQH
#define SPREADSAMPLER_MQH

//+------------------------------------------------------------------+
//| CSpreadSampler                                                   |
//| Reads the live spread for a symbol at the exact moment of the    |
//| call. The spread is never cached or stored at registration time, |
//| since a spread sampled once at entry would go stale the instant  |
//| market conditions change, defeating the entire purpose of spread |
//| compensation.                                                    |
//+------------------------------------------------------------------+
class CSpreadSampler
  {
public:
                     CSpreadSampler(void);
                    ~CSpreadSampler(void);

   double            GetCurrentSpread(const string symbol) const;
   double            GetCurrentSpreadPips(const string symbol) const;
  };

//+------------------------------------------------------------------+
//| Constructor                                                      |
//+------------------------------------------------------------------+
CSpreadSampler::CSpreadSampler(void)
  {
  }

//+------------------------------------------------------------------+
//| Destructor                                                       |
//+------------------------------------------------------------------+
CSpreadSampler::~CSpreadSampler(void)
  {
  }

//+------------------------------------------------------------------+
//| GetCurrentSpread                                                 |
//| Returns the live spread in price terms by reading the current    |
//| ask minus bid for the given symbol at the exact moment of the    |
//| call. Spread is not cached or stored at registration time; every |
//| call re-reads the live market so the compensation always reflects|
//| the current condition rather than a stale historical value.      |
//+------------------------------------------------------------------+
double CSpreadSampler::GetCurrentSpread(const string symbol) const
  {
//--- reads live ask and bid at this instant
   double ask = ::SymbolInfoDouble(symbol, SYMBOL_ASK);
   double bid = ::SymbolInfoDouble(symbol, SYMBOL_BID);

//--- returns spread in price terms
   return(ask - bid);
  }

//+------------------------------------------------------------------+
//| GetCurrentSpreadPips                                             |
//| Returns the live spread converted to a pip count. On 3- and      |
//| 5-digit symbols one pip equals ten points, so the price-terms    |
//| spread is divided by ten times the point size rather than by the |
//| raw point, matching the standard broker pip convention.          |
//+------------------------------------------------------------------+
double CSpreadSampler::GetCurrentSpreadPips(const string symbol) const
  {
//--- samples the live spread in price terms first
   double spread = GetCurrentSpread(symbol);

//--- determines pip size: on 3- and 5-digit symbols one pip is ten points
   double point  = ::SymbolInfoDouble(symbol, SYMBOL_POINT);
   int    digits = (int)::SymbolInfoInteger(symbol, SYMBOL_DIGITS);
   double pip_size = (digits == 3 || digits == 5) ? point * 10.0 : point;

   if(pip_size <= 0.0)
      return(0.0);

//--- converts the price-terms spread into a pip count
   return(spread / pip_size);
  }

#endif // SPREADSAMPLER_MQH
//+------------------------------------------------------------------+