Help with Indicators on CExpertSignal derived class

 

Hi,

I created a class using the tutorial https://www.mql5.com/en/articles/367 with Bollinger Bands and ADXW indicators (default from MetaTrader). By now I'm not using input parameters nor long/short signals, only using LongCondition() to test it.

The screenshots are from the log generated by MT using printf and from another platform to check values (both platforms are set with the same input parameters). Values do not match (Bollinger bands values are equal to a past candle, but ADXW are not in both cases).

Candle 15/03/2019 17:45 at log:


Candle 15/03/2019 17:45 at other platform:

Candle 15/03/2019 17:40 at other platform:

Here is the class code:

//+------------------------------------------------------------------+
//|                                                          CAC.mqh |
//|                                                            Tuche |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Tuche"
#property link      ""
#property version   "1.00"
// Tutorial: https://www.mql5.com/en/articles/367

#include <Expert\ExpertSignal.mqh>   // CExpertSignal is in the file ExpertSignal
#property tester_indicator "Examples\\BB.ex5"
#property tester_indicator "Examples\\ADXW.ex5"

//TODO wizard parameters

// wizard description start
//+------------------------------------------------------------------+
//| Description of the class                                         |
//| Title=Sinais completos do indicador A                            |
//| Type=SignalAdvanced                                              |
//| Name=CAC                                                         |
//| ShortName=CAC                                                    |
//| Class=CAC                                                        |
//| Page=Not needed                                                  |
//+------------------------------------------------------------------+
// wizard description end

#define PROXIMA_LINHA "\r\n"

#define LONG_SIGNAL_100  100
#define SHORT_SIGNAL_100 100

#define MATH_POW_ARREDONDA 10

#define BB_PARAMETERS   4
#define ADXW_PARAMETERS 2

#define BB_NUMBUFFERS   4
#define ADXW_NUMBUFFERS 10 

// BB Buffers
#define BB_STDDEV_BUFFER 3
#define BB_TL_BUFFER     1
#define BB_BL_BUFFER     2

// ADXW Buffers
#define ADXW_BUFFER     0
#define ADXW_PDI_BUFFER 1
#define ADXW_NDI_BUFFER 2

//--- global variables
static string     g_strResumoCandle="";
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
class CAC : public CExpertSignal
  {
private:
   // The indicator as an object
   CiCustom          ciBands;
   CiCustom          ciADXW;

   //--- Configurable module parameters
   //--- input parametrs (BB)
   int               InpBandsPeriod;         // BB Period
   int               InpBandsShift;          // BB Shift
   double            InpBandsDeviations;     // BB Deviation
   //--- input parametrs (BB) FMa
   double            InpBandsMargemEntrada;  // BB Margem de entrada
   double            InpBandsMargemSaida;    // BB Margem de saida
   //--- function (BB) FMa
   bool              bBandsAbriu(const int iIndex);

   //--- input parametrs (ADXW)
   int               InpADXWPeriod;          // ADXW Period
   //--- input parametrs (ADXW) FMa
   int               InpADXWIntensidade;     // ADXW Intensidade
   int               InpADXWLevel;           // ADXW Nivel
   //--- function (ADXW) FMa
   bool              bADXWTendencia(const int iIndex);

   // arredondamento e log
   string            strArredonda(double dNum,const int iDecimal,const bool bArredondado);
   double            dArredonda(double dNum,const int iDecimal);

public:
   //--- Constructor of class
                    ~CAC(void);
   //--- Destructor of class
                     CAC();
   //--- Checking correctness of input data
   bool              ValidationSettings(void);
   //--- Creating indicators and timeseries for the module of signals
   bool              InitIndicators(CIndicators *indicators);
   //--- Access to indicator data
   double            GetDataBands(const int iNumBuffer,const int index) const;
   double            GetDataADXW(const int iNumBuffer,const int index) const;
   //--- Checking buy conditions
   virtual int       LongCondition();
   //--- Checking sell conditions
   virtual int       ShortCondition();

protected:
   //--- Creating BB indicators
   bool              CreateBands(CIndicators *indicators);
   //--- Creating ADXW indicators
   bool              CreateADXW(CIndicators *indicators);
  };
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CAC::CAC() : InpBandsPeriod(8),
             InpBandsShift(0),
             InpBandsDeviations(2),
             InpBandsMargemEntrada(0.75),
             InpBandsMargemSaida(0.75),
             InpADXWIntensidade(0),
             InpADXWLevel(8),
             InpADXWPeriod(32)
  {
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
CAC::~CAC()
  {
  }
//+------------------------------------------------------------------+
//| Checks input parameters and returns true if everything is OK     |
//+------------------------------------------------------------------+
bool CAC::ValidationSettings()
  {
//--- Call the base class method
   if(!CExpertSignal::ValidationSettings())  return(false);
//TODO check them
//--- All checks are completed, everything is ok
   return true;
  }
//+------------------------------------------------------------------+
//| Creates indicators                                               |
//| Input:  a pointer to a collection of indicators                  |
//| Output: true if successful, otherwise false                      |
//+------------------------------------------------------------------+
bool CAC::InitIndicators(CIndicators *indicators)
  {
//--- Standard check of the collection of indicators for NULL
   if(indicators==NULL)                           return(false);
//--- Initializing indicators and timeseries in additional filters
   if(!CExpertSignal::InitIndicators(indicators)) return(false);

//--- Creating BB indicators
   if(!CreateBands(indicators))
     {
      return(false);
     }

//--- Creating ADXW indicators
   if(!CreateADXW(indicators))
     {
      return(false);
     }

//--- Reached this part, so the function was successful, return true
   return(true);
  }
//+------------------------------------------------------------------+
//| Creates the BB indicator                                         |
//+------------------------------------------------------------------+
bool CAC::CreateBands(CIndicators *indicators)
  {
//--- Checking the pointer
   if(indicators==NULL) return(false);
//--- Adding an object to the collection
   if(!indicators.Add(GetPointer(ciBands)))
     {
      printf(__FUNCTION__+": Error adding an object of the BB");
      return(false);
     }
//--- Setting parameters
   MqlParam parameters[BB_PARAMETERS];
//---
   parameters[0].type=TYPE_STRING;
   parameters[0].string_value="Examples\\BB.ex5";
   parameters[1].type=TYPE_INT;
   parameters[1].integer_value=InpBandsPeriod;     // Period
   parameters[2].type=TYPE_INT;
   parameters[2].integer_value=InpBandsShift;      // Shift
   parameters[3].type=TYPE_DOUBLE;
   parameters[3].double_value=InpBandsDeviations;  // Averaging method
//--- Object initialization  
   if(!ciBands.Create(m_symbol.Name(),m_period,IND_CUSTOM,BB_PARAMETERS,parameters))
     {
      printf(__FUNCTION__+": Error initializing the object of the BB");
      return(false);
     }
//--- Number of buffers
   if(!ciBands.NumBuffers(BB_NUMBUFFERS))
     {
      return(false);
     }
//--- Reached this part, so the function was successful, return true
   return(true);
  }
//+------------------------------------------------------------------+
//| Creates the ADXW indicator                                         |
//+------------------------------------------------------------------+
bool CAC::CreateADXW(CIndicators *indicators)
  {
//--- Checking the pointer
   if(indicators==NULL) return(false);
//--- Adding an object to the collection
   if(!indicators.Add(GetPointer(ciADXW)))
     {
      printf(__FUNCTION__+": Error adding an object of the ADXW");
      return(false);
     }
//--- Setting parameters
   MqlParam parameters[ADXW_PARAMETERS];
//---
   parameters[0].type=TYPE_STRING;
   parameters[0].string_value="Examples\\ADXW.ex5";
   parameters[1].type=TYPE_INT;
   parameters[1].integer_value=InpADXWPeriod;     // Period
//--- Object initialization
   if(!ciADXW.Create(m_symbol.Name(),m_period,IND_CUSTOM,ADXW_PARAMETERS,parameters))
     {
      printf(__FUNCTION__+": Error initializing the object of the ADXW");
      return(false);
     }
//--- Number of buffers
   if(!ciADXW.NumBuffers(ADXW_NUMBUFFERS))
     {
      return(false);
     }
//--- Reached this part, so the function was successful, return true
   return(true);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double CAC::GetDataBands(const int iNumBuffer,const int index) const
  {
   return(ciBands.GetData(iNumBuffer,index));
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double CAC::GetDataADXW(const int iNumBuffer,const int index) const
  {
   return(ciADXW.GetData(iNumBuffer,index));
  }
//+------------------------------------------------------------------+
//| Returns the strength of the buy signal                           |
//+------------------------------------------------------------------+
int CAC::LongCondition()
  {
   int signal=0;
//--- For operation with ticks idx=0, for operation with formed bars idx=1
   int idx=StartIndex();

   g_strResumoCandle="Candle:"+PROXIMA_LINHA;

   bBandsAbriu(idx);
   bADXWTendencia(idx);

   printf(g_strResumoCandle);

   return(signal);
  }
//+------------------------------------------------------------------+
//| Returns the strength of the short signal                         |
//+------------------------------------------------------------------+
int CAC::ShortCondition()
  {
   int signal=0;

   return(signal);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool CAC::bBandsAbriu(const int iIndex)
  {
   static bool bRetorno=false;

   const double dBands=dArredonda(GetDataBands(BB_STDDEV_BUFFER,iIndex),4);
   const double dBandsAnterior=dArredonda(GetDataBands(BB_STDDEV_BUFFER,iIndex+1),4);

   g_strResumoCandle += "BB 8+2\t"+strArredonda(GetDataBands(BB_TL_BUFFER,iIndex),4,false)+PROXIMA_LINHA;
   g_strResumoCandle += "BB 8-2\t"+strArredonda(GetDataBands(BB_BL_BUFFER,iIndex),4,false)+PROXIMA_LINHA;

   return bRetorno;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool CAC::bADXWTendencia(const int iIndex)
  {
   bool bRetorno=false;

   const double dADXBuffer=dArredonda(GetDataADXW(ADXW_BUFFER,iIndex),0);
   const double dPDIBuffer=dArredonda(GetDataADXW(ADXW_PDI_BUFFER,iIndex),0);
   const double dNDIBuffer=dArredonda(GetDataADXW(ADXW_NDI_BUFFER,iIndex),0);

   g_strResumoCandle += "DI+\t"+strArredonda(dPDIBuffer,0,true)+PROXIMA_LINHA;
   g_strResumoCandle += "DI-\t"+strArredonda(dNDIBuffer,0,true)+PROXIMA_LINHA;
   g_strResumoCandle += "ADXW\t"+strArredonda(dADXBuffer,0,true)+PROXIMA_LINHA;

   return bRetorno;
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string CAC::strArredonda(double dNum,const int iDecimal,const bool bArredondado)
  {
   if(bArredondado==false)
     {
      dNum=dArredonda(dNum,iDecimal);
     }
   return DoubleToString(dNum,iDecimal);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double CAC::dArredonda(double dNum,const int iDecimal)
  {
   dNum=MathRound(dNum*MathPow(MATH_POW_ARREDONDA,iDecimal));
   return(dNum*MathPow(MATH_POW_ARREDONDA,-iDecimal));
  }
//+------------------------------------------------------------------+
Create Your Own Trading Robot in 6 Steps!
Create Your Own Trading Robot in 6 Steps!
  • www.mql5.com
The world around us is changing rapidly, and we try to keep up with it. We do not have time to learn something new, and this is a normal attitude of a normal human being. Traders are people just like everyone else, they want to get maximum results for the minimum of effort. Specially for traders, MetaEditor 5 offers a wonderful MQL5...
 

Hi all,


I also created an indicator to compare the values I expect (the indicator has the correct values) and where I copied the Bollinger Bands and ADXW code inside it. The indicator saves a \MQL5\Files\log.txt file after closing the testing window. Here is the code:


//+------------------------------------------------------------------+
//|                                                            A.mq5 |
//|                                                            Tuche |
//|                                                                  |
//+------------------------------------------------------------------+
#include <MovingAverages.mqh>

#property copyright "Tuche"
#property link      ""
#property version   "1.26"
#property indicator_chart_window
#property indicator_buffers 16
#property indicator_plots   2

//--- plot Venda
#property indicator_label1  "Sell"
#property indicator_type1   DRAW_ARROW
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  8

//--- plot Compra
#property indicator_label2  "Buy"
#property indicator_type2   DRAW_ARROW
#property indicator_color2  clrLime
#property indicator_style2  STYLE_SOLID
#property indicator_width2  8

#define NEXT_LINE "\r\n"
#define MATH_POW_ARREDONDA 10

extern string  logFile="log.txt";

//--- input BB parameters
input double      BBMargemEntrada=0.75; // Margem de entrada Banda de Bollinger
input double      BBMargemSaida=0.5;   // Margem de saida Banda de Bollinger
int           ExtBandsPeriod=8;     // BB Periodo
int           ExtBandsShift=0;      // BB Periodo
double        ExtBandsDeviations=2; // BB Numero de desvios
int           ExtPlotBegin=0;       // BB Ínicio do plot

//--- input ADXW parameters
int           InpPeriodADXW=8; // ADXW Periodo
int           iADXLevel=32;    // ADXW Nivel

//--- indicator buffers
double         VendaBuffer[];  // sell
double         CompraBuffer[]; // buy

//--- indicator BB buffers
double        ExtMLBuffer[];
double        ExtStdDevBuffer[];
double        ExtTLBuffer[];
double        ExtBLBuffer[];

//---- indicator ADXW buffers
double    ExtADXWBuffer[];
double    ExtPDIBuffer[];
double    ExtNDIBuffer[];
double    ExtPDSBuffer[];
double    ExtNDSBuffer[];
double    ExtPDBuffer[];
double    ExtNDBuffer[];
double    ExtTRBuffer[];
double    ExtATRBuffer[];
double    ExtDXBuffer[];

//--- global variables
static const int  g_iMaxPeriod=20;
datetime          g_dt=NULL;
string            g_strLogFile="";
string            g_strResumoCandle="";
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- log
   LogFile(NULL);

//--- indicator buffers mapping
   SetIndexBuffer(0,VendaBuffer,INDICATOR_DATA);
   SetIndexBuffer(1,CompraBuffer,INDICATOR_DATA);

//--- indicator BB buffers mapping
   SetIndexBuffer(2,ExtMLBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(3,ExtStdDevBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(4,ExtTLBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(5,ExtBLBuffer,INDICATOR_CALCULATIONS);

//--- indicator ADXW buffers mapping
   SetIndexBuffer(6,ExtADXWBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(7,ExtPDSBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(8,ExtNDSBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(9,ExtPDBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(10,ExtNDBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(11,ExtTRBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(12,ExtATRBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(13,ExtDXBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(14,ExtPDIBuffer,INDICATOR_CALCULATIONS);
   SetIndexBuffer(15,ExtNDIBuffer,INDICATOR_CALCULATIONS);

//--- setting a code from the Wingdings charset as the property of PLOT_ARROW
   PlotIndexSetInteger(0,PLOT_ARROW,159);
   PlotIndexSetInteger(1,PLOT_ARROW,159);

   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+ 
//| Expert deinitialization function                                 | 
//+------------------------------------------------------------------+ 
void OnDeinit(const int reason)
  {
   LogFile("End of log.");
   printLog(g_strLogFile);
   return;
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   for(int i=MathMax(g_iMaxPeriod,prev_calculated); i<rates_total; i++)
     {
      g_dt=time[i];

      if(g_dt>=D'2019.03.01') //TODO just to limit the log size
        {
         Bollinger_Func(i,close);

         ADXW_Func(i,close,high,low);

         LogFile("Candle:");
         LogFile("Open: "+(string)open[i]);
         LogFile("Max: "+(string)high[i]);
         LogFile("Min: "+(string)low[i]);
         LogFile("Close: "+(string)close[i]);
         LogFile(g_strResumoCandle);
         g_strResumoCandle="";
        }
     }
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
//| Calculate Standard Deviation                                     |
//+------------------------------------------------------------------+
double StdDev_Func(const int position,const double &price[],const double &MAprice[],const int period)
  {
//--- variables
   double StdDev_dTmp=0.0;
//--- check for position
   if(position<period) return(StdDev_dTmp);
//--- calcualte StdDev
   for(int i=0;i<period;i++) StdDev_dTmp+=MathPow(price[position-i]-MAprice[position],2);
   StdDev_dTmp=MathSqrt(StdDev_dTmp/period);
//--- return calculated value
   return(StdDev_dTmp);
  }
//+------------------------------------------------------------------+
//| Calculate Bollinger                                              |
//| Se os valores de Bollinger nao baterem com o Cartezyan, verificar|
//| se ele esta utilizando o ultimo preco, e nao o preco tipico      |
//+------------------------------------------------------------------+
bool Bollinger_Func(const int i,const double &price[])
  {
//--- middle line
   ExtMLBuffer[i]=SimpleMA(i,ExtBandsPeriod,price);
//--- calculate and write down StdDev
   ExtStdDevBuffer[i]=StdDev_Func(i,price,ExtMLBuffer,ExtBandsPeriod);
//--- upper line TODO pode apagar se nao quiser o resumo do candle
   ExtTLBuffer[i]=ExtMLBuffer[i]+ExtBandsDeviations*ExtStdDevBuffer[i];
//--- lower line TODO pode apagar se nao quiser o resumo do candle
   ExtBLBuffer[i]=ExtMLBuffer[i]-ExtBandsDeviations*ExtStdDevBuffer[i];

   bool bBBAbriu=false;

   g_strResumoCandle += NEXT_LINE;
   g_strResumoCandle += "BB 8+2\t"+strArredonda(ExtTLBuffer[i],4,false)+NEXT_LINE;
   g_strResumoCandle += "BB 8-2\t"+strArredonda(ExtBLBuffer[i],4,false)+NEXT_LINE;

   return bBBAbriu;
  }
//+------------------------------------------------------------------+
//| Calculate ADXW                                                   |
//+------------------------------------------------------------------+
bool ADXW_Func(const int i,const double &price[],const double &high[],const double &low[])
  {
//--- get some data
   double Hi    =high[i];
   double prevHi=high[i-1];
   double Lo    =low[i];
   double prevLo=low[i-1];
   double prevCl=price[i-1];
//--- fill main positive and main negative buffers
   double dTmpP=Hi-prevHi;
   double dTmpN=prevLo-Lo;
   if(dTmpP<0.0) dTmpP=0.0;
   if(dTmpN<0.0) dTmpN=0.0;
   if(dTmpN==dTmpP)
     {
      dTmpN=0.0;
      dTmpP=0.0;
     }
   else
     {
      if(dTmpP<dTmpN) dTmpP=0.0;
      else            dTmpN=0.0;
     }
   ExtPDBuffer[i]=dTmpP;
   ExtNDBuffer[i]=dTmpN;
//--- define TR
   double tr=MathMax(MathMax(MathAbs(Hi-Lo),MathAbs(Hi-prevCl)),MathAbs(Lo-prevCl));
//--- write down TR to TR buffer
   ExtTRBuffer[i]=tr;
//--- fill smoothed positive and negative buffers and TR buffer
   if(i<InpPeriodADXW)
     {
      ExtATRBuffer[i]=0.0;
      ExtPDIBuffer[i]=0.0;
      ExtNDIBuffer[i]=0.0;
     }
   else
     {
      ExtATRBuffer[i]=SmoothedMA(i,InpPeriodADXW,ExtATRBuffer[i-1],ExtTRBuffer);
      ExtPDSBuffer[i]=SmoothedMA(i,InpPeriodADXW,ExtPDSBuffer[i-1],ExtPDBuffer);
      ExtNDSBuffer[i]=SmoothedMA(i,InpPeriodADXW,ExtNDSBuffer[i-1],ExtNDBuffer);
     }
//--- calculate PDI and NDI buffers
   if(ExtATRBuffer[i]!=0.0)
     {
      ExtPDIBuffer[i]=100.0*ExtPDSBuffer[i]/ExtATRBuffer[i];
      ExtNDIBuffer[i]=100.0*ExtNDSBuffer[i]/ExtATRBuffer[i];
     }
   else
     {
      ExtPDIBuffer[i]=0.0;
      ExtNDIBuffer[i]=0.0;
     }
//--- Calculate DX buffer
   double dTmp=ExtPDIBuffer[i]+ExtNDIBuffer[i];
   if(dTmp!=0.0) dTmp=100.0*MathAbs((ExtPDIBuffer[i]-ExtNDIBuffer[i])/dTmp);
   else          dTmp=0.0;
   ExtDXBuffer[i]=dTmp;
//--- fill ADXW buffer as smoothed DX buffer
   ExtADXWBuffer[i]=SmoothedMA(i,InpPeriodADXW,ExtADXWBuffer[i-1],ExtDXBuffer);

   bool bADXTendenica=false;

   const double iExtADXBuffer=dArredonda(ExtADXWBuffer[i],0);
   const double iExtPDIBuffer=dArredonda(ExtPDIBuffer[i],0);
   const double iExtNDIBuffer=dArredonda(ExtNDIBuffer[i],0);

   const string strExtPDIBuffer=strArredonda(iExtPDIBuffer,0,true);
   const string strExtNDIBuffer=strArredonda(iExtNDIBuffer,0,true);
   const string strExtADXBuffer=strArredonda(iExtADXBuffer,0,true);

   g_strResumoCandle += "DI+\t"+strExtPDIBuffer+NEXT_LINE;
   g_strResumoCandle += "DI-\t"+strExtNDIBuffer+NEXT_LINE;
   g_strResumoCandle += "ADXW\t"+strExtADXBuffer+NEXT_LINE;

   return bADXTendenica;
  }
//+------------------------------------------------------------------+
//| Log                                                              |
//+------------------------------------------------------------------+
void LogFile(const string linha)
  {
//if(dt!=NULL && dt>D'2019.02.19') // data temporaria
   if(g_dt!=NULL)
     {
      g_strLogFile+=TimeToString(g_dt);
      g_strLogFile+=": ";
      g_strLogFile+=linha;
      g_strLogFile+=NEXT_LINE;
     }
   else
     {
      g_strLogFile+="Log begin"+NEXT_LINE;
      g_strLogFile+="Symbol: ";
      g_strLogFile+=_Symbol+NEXT_LINE;
      g_strLogFile+="Period: ";
      g_strLogFile+=(string)_Period;
      g_strLogFile+=NEXT_LINE;
     }
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
string strArredonda(double dNum,const int iDecimal,const bool bArredondado)
  {
   if(bArredondado==false)
     {
      dNum=dArredonda(dNum,iDecimal);
     }
   return DoubleToString(dNum,iDecimal);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
double dArredonda(double dNum,const int iDecimal)
  {
   dNum=MathRound(dNum*MathPow(MATH_POW_ARREDONDA,iDecimal));
   return(dNum*MathPow(MATH_POW_ARREDONDA,-iDecimal));
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void printLog(string log)
  {

   int handle=FileOpen(logFile,FILE_BIN|FILE_READ|FILE_WRITE,';');
   if(handle<1)
     {
      Print("LOGGING: Error opening file!");
      return;
     }
   FileWriteString(handle,log,StringLen(log));
   FileClose(handle);
   Print(log);

  }
//+------------------------------------------------------------------+


Thank you for your help.

Regards,

Tuche

Reason: