¿Cuál es la estructura básica de un indicador personalizado?

 

Saludos. Estoy aprendiendo a hacer indicadores en MQL5. Quiero conocer la estructura general de un indicador.

Para hacer esto, estoy diseñando el siguiente indicador (solo resta el ATR de dos velas anteriores al valor del ATR de la vela anterior), pero no se está mostrando, es decir, aunque al compilar no indica que falte algo, una vez que selecciono el indicador personalizado para incorporarlo, en diario dice que el indicador fue cargado exitosamente, y se carga, pero no se ve ninguna linea.

Aquí el código:


//+------------------------------------------------------------------+
//|                                 ATR.mq4 |
//|                    Copyright 2014,J |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2014,J"
#property link      ""
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 DodgerBlue
//--- buffers
double Buffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexStyle(0,DRAW_LINE);
  
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
   double ATR1, ATR2;
   ATR1=iATR(NULL, 14, PERIOD_CURRENT, 1);
   ATR2=iATR(NULL, 14, PERIOD_CURRENT, 1);
  
//---
 
   Buffer[0]=ATR1-ATR2;
  
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

 
trader201:

Saludos. Estoy aprendiendo a hacer indicadores en MQL5. Quiero conocer la estructura general de un indicador.

Para hacer esto, estoy diseñando el siguiente indicador (solo resta el ATR de dos velas anteriores al valor del ATR de la vela anterior), pero no se está mostrando, es decir, aunque al compilar no indica que falte algo, una vez que selecciono el indicador personalizado para incorporarlo, en diario dice que el indicador fue cargado exitosamente, y se carga, pero no se ve ninguna linea.

Aquí el código:


//+------------------------------------------------------------------+
//|                                 ATR.mq4 |
//|                    Copyright 2014,J |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright 2014,J"
#property link      ""
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 DodgerBlue
//--- buffers
double Buffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   SetIndexStyle(0,DRAW_LINE);
  
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| 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[])
  {
   double ATR1, ATR2;
   ATR1=iATR(NULL, 14, PERIOD_CURRENT, 1);
   ATR2=iATR(NULL, 14, PERIOD_CURRENT, 1);
  
//---
 
   Buffer[0]=ATR1-ATR2;
  
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

El error está en cómo manejas el puntero del indicador (iATR()).

Tienes que "apuntar" a los datos del indicador en OnInit(), al principio, una sóla vez, y luego cargarlos, cuando los necesitas, en OnCalculate() con CopyBuffer().

Con la expresión Buffer[0]= ATR1-ATR2 no calculas nada puesto que ATR1 Y ATR2 son dos valores booleanos devueltos por iATR() según se haya ejecutado con éxito o no la operación. Además, tampoco generas el bucle de carga de datos del indicador en cada vela.

Te adjunto un resumen de código de indicador que genera un canal-ATR

void OnInit()
{
   /.../
   SetIndexBuffer(0, MAbuffer, INDICATOR_DATA);
   SetIndexBuffer(1, supATRBuffer,INDICATOR_DATA);           //---- set supATRBuffer[] and infATRBuffer[] dynamic arrays into indicator buffers
   SetIndexBuffer(2, infATRBuffer,INDICATOR_DATA);           
   
   ArraySetAsSeries(MAbuffer, true);                         //---- indexing the elements in the buffer as timeseries
   ArraySetAsSeries(supATRBuffer, true);
   ArraySetAsSeries(infATRBuffer, true);

   /.../
   
   ResetLastError();
   puntATR= iATR(simb, 0, ATRperiodo);
   puntMA= iMA(simb, PERIOD_CURRENT, MAperiodoTrab, 0, MODE_SMA, precioAplic);
   if(puntATR==INVALID_HANDLE || puntMA==INVALID_HANDLE) infoError(GetLastError(), "Canal ATR "+__FUNCTION__);
   
   /.../
   
}
  
int OnCalculate(const int rangoTotal,
                const int preCalculado,
                const int inicio,          
                const double &precio[])    
{
   int vela, limite,aCopiar;
   double ATR[], atr;
                                                         //comprobando si el número de barras es suficiente para el cálculo
   if(BarsCalculated(puntMA)<rangoTotal || BarsCalculated(puntATR)<rangoTotal || rangoTotal<minRangoTotal) return(0);
   ArraySetAsSeries(ATR,true);
   limite= rangoTotal-preCalculado;                      //inicializa el índice para el cálculo de nueva barra
   if(preCalculado>rangoTotal || preCalculado<=0) limite= rangoTotal-minRangoTotal-1; //inicializa el índice para el cálculo de todas las barras
   aCopiar= limite+1;
   if(CopyBuffer(puntATR, 0, 0, aCopiar, ATR)<=0) return(0);
   if(CopyBuffer(puntMA, 0, 0, aCopiar, MAbuffer)<=0) return(0);

   for(int vela= limite; vela>=0; vela--)
   {
      atr= factorATR*ATR[vela];
      supATRBuffer[vela]= MAbuffer[vela]+atr;
      infATRBuffer[vela]= MAbuffer[vela]-atr;
   }
   return(rangoTotal);
}
 
josemiguel1812:

El error está en cómo manejas el puntero del indicador (iATR()).

Tienes que "apuntar" a los datos del indicador en OnInit(), al principio, una sóla vez, y luego cargarlos, cuando los necesitas, en OnCalculate() con CopyBuffer().

Con la expresión Buffer[0]= ATR1-ATR2 no calculas nada puesto que ATR1 Y ATR2 son dos valores booleanos devueltos por iATR() según se haya ejecutado con éxito o no la operación. Además, tampoco generas el bucle de carga de datos del indicador en cada vela.

Te adjunto un resumen de código de indicador que genera un canal-ATR

Gracias!