English Русский 中文 Deutsch 日本語 Português
Características de la creación de indicadores personalizados

Características de la creación de indicadores personalizados

MetaTrader 4Ejemplos | 12 enero 2016, 11:53
1 592 0
MetaQuotes
MetaQuotes

La creación de indicadores personalizados con la plataforma MetaTrader tiene una serie de particularidades.

  • Un programa se considera un indicador personalizado si se adecua a una de estas dos definiciones:

    #property  indicator_chart_window      // se dibuja un indicador en la ventana del gráfico principal

    o

    #property  indicator_separate_window   // se dibuja un indicador en una ventana separada
  • Las siguientes definiciones establecen la escala de la ventana de indicador separada:

    #property  indicator_minimum Min_Value
    #property  indicator_maximum Max_Value
    

    donde "Min_Value" y "Max_Value" son los valores correspondientes. Por ejemplo, estos valores tienen que ser 0 y 100, respectivamente, para el indicador personalizado RSI.

  • El número de arrays que necesita el indicador para realizar el dibujo se define de la siguiente manera:

    #property  indicator_buffers N

    donde N puede tomar valores comprendidos entre 1 y 8.

  • El color de las líneas del indicador se establece con estas definiciones:

    #property  indicator_color1  Silver
    #property  indicator_color2  Red
    ...
    #property  indicator_colorN  <SomeColor>
    

    donde N es el número de arrays de indicador definidos en "#define indicator_buffer".

  • Hay funciones que permiten controlar tanto el proceso de cálculo del indicador como la visualización. A continuación se ilustra lo anterior con el indicador personalizado Ishimoku Kinko Hyo, a modo de ejemplo:

    //+------------------------------------------------------------------+
    //|                                                     Ichimoku.mq4 |
    //|                      Copyright © 2004, MetaQuotes Software Corp. |
    //|                                       https://www.metaquotes.net/ |
    //+------------------------------------------------------------------+
    #property copyright "Copyright © 2004, MetaQuotes Software Corp."
    #property link      "https://www.metaquotes.net/"
     
    #property indicator_chart_window
    #property indicator_buffers 7
    #property indicator_color1 Red
    #property indicator_color2 Blue
    #property indicator_color3 SandyBrown
    #property indicator_color4 Thistle
    #property indicator_color5 Lime
    #property indicator_color6 SandyBrown
    #property indicator_color7 Thistle
    //---- parámetros de entrada
    extern int Tenkan=9;
    extern int Kijun=26;
    extern int Senkou=52;
    //---- búferes del indicador
    double Tenkan_Buffer[];
    double Kijun_Buffer[];
    double SpanA_Buffer[];
    double SpanB_Buffer[];
    double Chinkou_Buffer[];
    double SpanA2_Buffer[];
    double SpanB2_Buffer[];
    //---- comienza el dibujo span_a
    int a_begin;
    //+------------------------------------------------------------------+
    //| Función de inicialización del indicador personalizado            |
    //+------------------------------------------------------------------+
    int init()
      {
    //----
       SetIndexStyle(0,DRAW_LINE);
       SetIndexBuffer(0,Tenkan_Buffer);
       SetIndexDrawBegin(0,Tenkan-1);
       SetIndexLabel(0,"Tenkan Sen");
    //----
       SetIndexStyle(1,DRAW_LINE);
       SetIndexBuffer(1,Kijun_Buffer);
       SetIndexDrawBegin(1,Kijun-1);
       SetIndexLabel(1,"Kijun Sen");
    //----
       a_begin=Kijun; if(a_begin&lt;Tenkan) a_begin=Tenkan;
       SetIndexStyle(2,DRAW_HISTOGRAM,STYLE_DOT);
       SetIndexBuffer(2,SpanA_Buffer);
       SetIndexDrawBegin(2,Kijun+a_begin-1);
       SetIndexShift(2,Kijun);
       SetIndexLabel(2,NULL);
       SetIndexStyle(5,DRAW_LINE,STYLE_DOT);
       SetIndexBuffer(5,SpanA2_Buffer);
       SetIndexDrawBegin(5,Kijun+a_begin-1);
       SetIndexShift(5,Kijun);
       SetIndexLabel(5,"Senkou Span A");
    //----
       SetIndexStyle(3,DRAW_HISTOGRAM,STYLE_DOT);
       SetIndexBuffer(3,SpanB_Buffer);
       SetIndexDrawBegin(3,Kijun+Senkou-1);
       SetIndexShift(3,Kijun);
       SetIndexLabel(3,NULL);
       SetIndexStyle(6,DRAW_LINE,STYLE_DOT);
       SetIndexBuffer(6,SpanB2_Buffer);
       SetIndexDrawBegin(6,Kijun+Senkou-1);
       SetIndexShift(6,Kijun);
       SetIndexLabel(6,"Senkou Span B");
    //----
       SetIndexStyle(4,DRAW_LINE);
       SetIndexBuffer(4,Chinkou_Buffer);
       SetIndexShift(4,-Kijun);
       SetIndexLabel(4,"Chinkou Span");
    //----
       return(0);
      }
    //+------------------------------------------------------------------+
    //| Ichimoku Kinko Hyo                                               |
    //+------------------------------------------------------------------+
    int start()
      {
       int    i,k;
       int    counted_bars=IndicatorCounted();
       double high,low,price;
    //----
       if(Bars&lt;=Tenkan || Bars&lt;=Kijun || Bars&lt;=Senkou) return(0);
    //---- cero inicial
       if(counted_bars&lt;1)
         {
          for(i=1;i&lt;=Tenkan;i++)    Tenkan_Buffer[Bars-i]=0;
          for(i=1;i&lt;=Kijun;i++)     Kijun_Buffer[Bars-i]=0;
          for(i=1;i&lt;=a_begin;i++) { SpanA_Buffer[Bars-i]=0; SpanA2_Buffer[Bars-i]=0; }
          for(i=1;i&lt;=Senkou;i++)  { SpanB_Buffer[Bars-i]=0; SpanB2_Buffer[Bars-i]=0; }
         }
    //---- Tenkan Sen
       i=Bars-Tenkan;
       if(counted_bars>Tenkan) i=Bars-counted_bars-1;
       while(i>=0)
         {
          high=High[i]; low=Low[i]; k=i-1+Tenkan;
          while(k>=i)
            {
             price=High[k];
             if(high&lt;price) high=price;
             price=Low[k];
             if(low>price)  low=price;
             k--;
            }
          Tenkan_Buffer[i]=(high+low)/2;
          i--;
         }
    //---- Kijun Sen
       i=Bars-Kijun;
       if(counted_bars>Kijun) i=Bars-counted_bars-1;
       while(i>=0)
         {
          high=High[i]; low=Low[i]; k=i-1+Kijun;
          while(k>=i)
            {
             price=High[k];
             if(high<price) high=price;
             price=Low[k];
             if(low>price)  low=price;
             k--;
            }
          Kijun_Buffer[i]=(high+low)/2;
          i--;
         }
    //---- Senkou Span A
       i=Bars-a_begin+1;
       if(counted_bars>a_begin-1) i=Bars-counted_bars-1;
       while(i>=0)
         {
          price=(Kijun_Buffer[i]+Tenkan_Buffer[i])/2;
          SpanA_Buffer[i]=price;
          SpanA2_Buffer[i]=price;
          i--;
         }
    //---- Senkou Span B
       i=Bars-Senkou;
       if(counted_bars>Senkou) i=Bars-counted_bars-1;
       while(i>=0)
         {
          high=High[i]; low=Low[i]; k=i-1+Senkou;
          while(k>=i)
            {
             price=High[k];
             if(high&lt;price) high=price;
             price=Low[k];
             if(low>price)  low=price;
             k--;
            }
          price=(high+low)/2;
          SpanB_Buffer[i]=price;
          SpanB2_Buffer[i]=price;
          i--;
         }
    //---- Chinkou Span
       i=Bars-1;
       if(counted_bars>1) i=Bars-counted_bars-1;
       while(i>=0) { Chinkou_Buffer[i]=Close[i]; i--; }
    //----
       return(0);
      }
    //+------------------------------------------------------------------+
    
  • La función "SetIndexStyle" controla los parámetros de dibujo del array indicador. El modo de dibujo DRAW_LINE asume que se dibujan las líneas entre los valores definidos en el array indicador correspondiente. El modo de dibujo DRAW_HISTOGRAM se aplica al indicador de la ventana principal, y también tiene sus características especiales. Se dibuja un histograma entre los valores correspondientes de dos arrays de índices: uno par (SpanA_Buffer) y otro impar (SpanB_Buffer). Se utiliza el color del array de índices cuyo valor sea mayor.

  • La función "SetIndexDrawBegin" especifica el elemento donde empiezan los datos.

  • La función "SetIndexBuffer" permite declarar como array índice un array unidimensional de tipo "double". Con todo lo anterior el sistema ya puede manejar arrays de índices. Por esta razón no es necesario especificar estos arrays.

    //---- búferes del indicador
    double Tenkan_Buffer[];
    double Kijun_Buffer[];
    double SpanA_Buffer[];
    double SpanB_Buffer[];
    double Chinkou_Buffer[];
    double SpanA2_Buffer[];
    double SpanB2_Buffer[];
    

    La función ArrayResize no se puede aplicar a los arrays indicador, puesto que no tiene sentido. Tampoco sirve de nada aplicar la función ArrayInitialize a los arrays del indicador, especialmente en la función 'init', cuando los arrays del indicador todavía no se han asignado. Los arrays del indicador se inicializan automáticamente durante la asignación y la reasignación de la memoria. Se puede utilizar tanto el valor EMPTY_VALUE como el valor especificado en la función SetIndexEmptyValue para inicializar los valores. Los valores vacíos no se muestran.

  • La función "SetIndexLabel" establece el nombre que se muestra en los consejos sobre herramientas y en la ventana de datos junto con el valor correspondiente. Se establece el valor "ValueN" por defecto, donde N es el número del array de índices. Si se transfiere NULL en vez de un nombre, entonces no se mostrará el valor correspondiente ni en los consejos sobre herramientas ni en la ventana de datos. En tal caso, las nubes están sombreadas con un histograma, y limitadas por una línea. Los valores correspondientes de los arrays de la "línea" y el "histograma" son los mismos, y se puede mostrar sólo uno de ellos.

  • La función "IndicatorCounted" permite organizar un cálculo económico del indicador. Esta función devuelve la cantidad de barras cuando se pone en marcha el indicador anterior, es decir, la cantidad de barras que ya se han calculado y que no necesitan recalcularse; esto si no hay errores, o el programa termina de forma anticipada en el lanzamiento anterior. Esta cantidad se reajustará automáticamente a 0 durante la reinicialización del indicador personalizado, o en una actualización significativa de los datos del historial.

  • Veamos ahora otro ejemplo. Indicador personalizado Oscilador Acelerador/Desacelerador:

    //+------------------------------------------------------------------+
    //|                                                  Accelerator.mq4 |
    //|                      Copyright © 2005, MetaQuotes Software Corp. |
    //|                                       https://www.metaquotes.net/ |
    //+------------------------------------------------------------------+
    #property  copyright "Copyright © 2005, MetaQuotes Software Corp."
    #property  link      "https://www.metaquotes.net/"
    //---- configuración del indicador
    #property  indicator_separate_window
    #property  indicator_buffers 3
    #property  indicator_color1  Black
    #property  indicator_color2  Green
    #property  indicator_color3  Red
    //---- búferes del indicador
    double     ExtBuffer0[];
    double     ExtBuffer1[];
    double     ExtBuffer2[];
    double     ExtBuffer3[];
    double     ExtBuffer4[];
    //+------------------------------------------------------------------+
    //| Función de inicialización del indicador personalizado            |
    //+------------------------------------------------------------------+
    int init()
      {
    //---- se utilizan 2 búferes adicionales para contar.
       IndicatorBuffers(5);
    //---- configuración del dibujo
       SetIndexStyle(0,DRAW_NONE);
       SetIndexStyle(1,DRAW_HISTOGRAM);
       SetIndexStyle(2,DRAW_HISTOGRAM);
       IndicatorDigits(Digits+2);
       SetIndexDrawBegin(0,38);
       SetIndexDrawBegin(1,38);
       SetIndexDrawBegin(2,38);
    //---- 4 búferes de indicador para el mapeo
       SetIndexBuffer(0,ExtBuffer0);
       SetIndexBuffer(1,ExtBuffer1);
       SetIndexBuffer(2,ExtBuffer2);
       SetIndexBuffer(3,ExtBuffer3);
       SetIndexBuffer(4,ExtBuffer4);
    //---- nombre de la ventana de datos y etiqueta de la subventana del indicador
       IndicatorShortName("AC");
       SetIndexLabel(1,NULL);
       SetIndexLabel(2,NULL);
    //---- inicialización realizada
       return(0);
      }
    //+------------------------------------------------------------------+
    //| Oscilador Acelerador/Desacelerador                               |
    //+------------------------------------------------------------------+
    int start()
      {
       int    limit;
       int    counted_bars=IndicatorCounted();
       double prev,current;
    //---- la última barra contada se vuelve a contar
       if(counted_bars>0) counted_bars--;
       limit=Bars-counted_bars;
    //---- conteo macd en el primer búfer adicional
       for(int i=0; i&lt;limit; i++)
          ExtBuffer3[i]=iMA(NULL,0,5,0,MODE_SMA,PRICE_MEDIAN,i)-
                        iMA(NULL,0,34,0,MODE_SMA,PRICE_MEDIAN,i);
    //---- conteo de la línea de señal en el segundo búfer adicional
       for(i=0; i<limit; i++)
          ExtBuffer4[i]=iMAOnArray(ExtBuffer3,Bars,5,0,MODE_SMA,i);
    //---- enviar valores entre los dos búferes
       bool up=true;
       for(i=limit-1; i>=0; i--)
         {
          current=ExtBuffer3[i]-ExtBuffer4[i];
          prev=ExtBuffer3[i+1]-ExtBuffer4[i+1];
          if(current>prev) up=true;
          if(current&lt;prev) up=false;
          if(!up)
            {
             ExtBuffer2[i]=current;
             ExtBuffer1[i]=0.0;
            }
          else
            {
             ExtBuffer1[i]=current;
             ExtBuffer2[i]=0.0;
            }
           ExtBuffer0[i]=current;
         }
    //---- hecho
       return(0);
      }
    //+------------------------------------------------------------------+
    
  • La función "IndicatorBuffers" especifica la cantidad de búferes que se utilizan en el cálculo del indicador. Generalmente, esta función se llama cuando se utilizan más arrays de índices de los necesarios para dibujar un indicador. El sistema gestiona arrays adicionales.

  • La función "SetIndexDigits" gestiona la precisión de la información de salida. En tal caso, cuando se calcula la diferencia entre dos medias móviles, o la diferencia mayor entre el resultado y la línea de señal, la precisión estándar de 4 dígitos tras el punto es, por supuesto, insuficiente.

  • La función "SetIndexDrawBegin" determina el elemento inicial significativo del array del indicador. En nuestro ejemplo, la línea de señal se calcula como la media móvil simple de otra media móvil simple. Por esta razón los primeros 38 valores del indicador se consideran vacíos y no se dibujan.

  • La función "IndicatorShortName" establece el nombre corto del indicador que se muestra en la esquina superior izquierda de la ventana del indicador y en la ventana de datos. Si no se establece ningún nombre corto se utilizará el nombre del indicador personalizado. En este ejemplo no hay necesidad de utilizar la función SetIndexLabel porque solamente sale un valor. Así, el nombre del indicador es suficiente para dar salida a un valor único.

  • La función "SetIndexStyle" gestiona el dibujo de los parámetros de un array de indicador. El modo de dibujo DRAW_NONE significa que no hay que dibujar la línea. La cuestión es que el histograma del indicador aquí expuesto se tiene que pintar con dos colores diferentes. Los datos de ExtBuffer0 se colocan en dos arrays diferentes: ExtBuffer1 y ExtBuffer2. Se establece a NULL el parámetro de la función SetIndexLabel para evitar la duplicación de datos en los consejos sobre herramientas o en la ventana de datos. El modo de dibujo DRAW_HISTOGRAM que se aplica al indicador de la ventana separada permite dibujar el histograma entre el valor cero y el valor del array correspondiente (compárese con el dibujo del histograma en la ventana principal, descrito anteriormente).

  • Los parámetros de entrada utilizados por los indicadores personalizados y por las funciones en los cálculos, se tienen que definir como "externos" y pueden ser de cualquier tipo.

  • Si no se establecen parámetros de entrada se llamará al indicador personalizado correspondiente con el formato más simple.

    double current_AC = iCustom( NULL, 0, "Accelerator", 0, 0 );

    La transferencia de los dos primeros valores, "NULL" y "0", significa que se utilizará el gráfico actual. El nombre del archivo correspondiente (sin extensión mq4) se utiliza como nombre del indicador personalizado. Si el último parámetro es un 0, significa que nos interesan los datos del primer array del indicador. El último parámetro 0 significa que nos interesa el valor del último elemento, es decir, el valor más reciente del array de indicador solicitado.

  • Los parámetros se transfieren en la función de cálculo del indicador personalizado en el orden en que se han descrito. Por ejemplo, el indicador personalizado "Ichimoku" con parámetros (9,26,52) se llamará así:

    iCustom( NULL, 0, "Ichimoku", 9, 26, 52, 0, shift );

    Estrictamente hablando, los parámetros del indicador personalizado no tienen que transferirse a la función necesariamente. No tiene sentido transferir parámetros si no se define ninguna variable externa en el programa. Si es necesario se pueden utilizar los valores iniciales utilizados en la descripción de los parámetros. Por ejemplo, el mismo indicador personalizado se llamará sin parámetros como sigue:

    iCustom( NULL, 0, "Ichimoku", 0, shift );

    Lo que significa que se utilizarán los valores iniciales de las variables "Tenkan", "Kijun", "Senkou", esto es: 9, 26 y 52. Sin embargo, si se utiliza un indicador personalizado combinando diferentes parámetros en un Asesor Experto, es muy aconsejable cambiar la configuración predeterminada.

Nótese que tanto el exceso de indicadores personalizados, como el uso de indicadores que no están escritos correctamente, ¡puede hacer que el terminal cliente se ralentice considerablemente!

Aviso: Todos los derechos de estos materiales están reservados por MetaQuotes Software Corp. Se prohíbe la reproducción completa o parcial.

Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/1497

Probador de estrategias: modos de modelado de las pruebas Probador de estrategias: modos de modelado de las pruebas
Muchos programas de análisis técnico permiten probar estrategias de trading sobre datos históricos. En la mayoría de los casos, las pruebas se realizan sobre datos ya terminados, sin intentar modelar la tendencia del precio. Se llevan a cabo de forma rápida, pero no de forma precisa.
Características de los Asesores Expertos Características de los Asesores Expertos
La creación de Asesores Expertos con la plataforma MetaTrader tiene una serie de particularidades.
Probando las características y los límites de MetaTrader 4 Probando las características y los límites de MetaTrader 4
Este artículo expone algunos detalles sobre las características y los límites del Probador de Estrategias de MetaTrader 4.
¿Qué significan los números de las pruebas del Asesor Experto? ¿Qué significan los números de las pruebas del Asesor Experto?
Este artículo explica cómo leer los informes de las pruebas realizadas y a interpretar correctamente los resultados obtenidos.