Descargar MetaTrader 5

El indicador Cuerda de Erik Nayman

23 febrero 2016, 13:57
Alexander Puzikov
0
1 107

Contenido


Introducción

El indicador que estudiamos en el presente texto está basado en el libro de Erik L. Nayman, "The Small Encyclopedia of Trader". VIRA-R Alfa Capital, 1999. —236 p.). Cubre los conceptos básicos del análisis técnico y fundamental de los mercados financieros, y se centra en un método de operación específico: el indicador "Cuerda". Descrito muy brevemente, el indicador se basa en la relación que existe entre la velocidad de cambio del precio en el período seleccionado y la cantidad de cambios producidos.

En su libro el autor ofrece un análisis resumido demostrando sus ideas con varias tablas y gráficos. Analiza el mercado basándose en la interacción entre los toros y los osos. Los objetos de estudio son la velocidad de cambio del precio, el número de transacciones y los cambios producidos. La velocidad se mide por el número de transacciones, y los cambios se calculan como la diferencia entre dos cotizaciones adyacentes (actual y anterior). En el libro, el último precio conocido se considera una cotización (el ejemplo de cálculo del primer capítulo proporciona más información).

El objetivo del análisis es calcular la fuerza y determinar la dirección de la tendencia, donde los toros y los osos ejercen simultáneamente su influencia en el mercado. Encontrar el valor de esta fuerza sirve para determinar qué posición es más fuerte en un momento determinado. El autor se sirve de la analogía de un tira y afloja de dos fuerzas opuestas para explicar el funcionamiento de esta acción. Así lo expresa en su obra con el valor de la "cuerda", calculado con la fuerza total de los toros y los osos:

También describe dos enfoques para analizar el mercado, haciendo cálculos basados en métodos estáticos y dinámicos. Calcular el valor de la "cuerda" consiste en estos pasos:

1. Evaluar y calcular las fuerzas alcistas y bajistas, y encontrar la dirección correspondiente.

Fórmulas de la fuerza alcista (como en el libro):

BuF = SPCi, donde:

  • BuF: fuerza alcista;
  • SPCi: suma de los cambios positivos en el periodo de tiempo analizado.

Fórmulas de la fuerza bajista (como en el libro):

BeF = SNCi, donde:

  • BeF: fuerza bajista;
  • SNCi: suma de los cambios negativos en el periodo de tiempo analizado.

Los valores BuF y BeF se comparan entre sí; el valor más alto indica quién tiene una posición dominante en el mercado.

Obtenemos la evaluación dinámica comparando los valores de la fuerza en dos barras adyacentes del período analizado. Veamos a continuación este análisis:

BuF > BeF and (BuF1 - BuFО) > (BeF1 - BeFО) = fuerza alcista creciente total (el valor actual de la fuerza se marca con el índice 1, el valor anterior con el índice 0).

BuF > BeF and (BuF1 - BuFО) < (BeF1 - BeFО) = fuerza alcista decreciente total.

BuF < BeF and (BuF1 - BuFО) > (BeF1 - BeFО) = fuerza bajista decreciente total.

BuF < BeF and (BuF1 - BuFО) < (BeF1 - BeFО) = fuerza bajista creciente total.

Además del valor de la fuerza estática, se ven por separado los cambios en la dinámica de este valor en los puntos adyacentes calculados.

2. Evaluación, cálculo y comparación del "vigor" (número de cambios) de los toros y los osos. Estos son los cálculos del vigor de los toros y los osos:

BuV = NPCi, donde:

  • BuV: vigor de los toros;
  • NPCi: número de cambios positivos en el periodo de tiempo analizado.

BeV = NNCi, donde:

  • BeV: vigor de los osos;
  • NNCi: número de cambios negativos en el periodo de tiempo analizado.

La evaluación dinámica se obtiene comparando el vigor calculado con el valor adyacente anterior. La dinámica se evalúa comparando un valor estático con uno dinámico, como en el ejemplo de la comparación del paso anterior del análisis.

3. Evaluación, cálculo y comparación de las "habilidades" de los toros y los osos. En el código fuente:

A continuación mostramos los cálculos de las "habilidades" de los toros y los osos:

BuS = SPC1/NPC1;

BeS = SNC1 / NNC1.

Esto demuestra cómo se calcula el valor estático; el cálculo dinámico se basa en el ejemplo del primer paso.

4. Evaluación final de los toros y los osos. Después de calcular los valores en los tres pasos anteriores, y tras comparar los datos correspondientes, podemos llegar a una conclusión sobre la dirección y el carácter de la tendencia. La evaluación final se realiza comparando los tres parámetros, en el libro se presenta así:

Si BuF > BeF, BuV > BeV y BuS > BeS (en función de las relaciones dinámicas mencionadas arriba), entonces, de acuerdo a su vigor, los toros son mejores que los osos, por lo tanto solo se tienen en cuenta las órdenes de compra.

 Para evaluar el mercado dinámico hay que añadir a los datos estáticos un valor dinámico de dos "puntos calculados adyacentes en la línea de la cuerda".

En cuanto a los pasos del análisis, se pueden distinguir tres valores principales en la creación del indicador:

  • fuerza: suma de los cambios en el periodo de tiempo analizado;
  • vigor: cantidad de cambios producidos en el periodo de tiempo analizado;
  • habilidad = fuerza / vigor.

El autor señala la parte dinámica como la más sensible y vigorosa de todas. En este artículo solo hemos elegido un método estático para realizar los cálculos. Así pues, comparando las tres partes: "fuerza", "vigor" y "habilidad", el autor saca unas conclusiones sobre la fuerza y la dirección de la tendencia, calcula los datos estáticos y dinámicos, y presenta varios métodos para su uso. Ahora echaremos un vistazo detallado a la creación del indicador "Cuerda" utilizando el método de Erik L. Nayman.


Capítulo 1. Principios de creación y cálculo del indicador "Cuerda", con algunos ejemplos de código

Hemos elegido un método lineal y un histograma para crear el indicador. El método lineal es la suma de los valores calculados de toros y osos. Y el método del histograma muestra los cálculos de los toros y los osos por separado.

Veamos el código del indicador, nótese que proporciona comentarios en cada uno de los pasos. Comencemos con la declaración de las variables y las características del indicador mediante la directiva #property. El siguiente código describe las características del color del indicador, el objetivo es analizar los datos cómodamente de forma visual.

//+------------------------------------------------------------------+
//|                                             RopebyEricNaiman.mq5 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property description "RopebyEricNaiman por Im_hungry (https://login.mql5.com/en/users/Im_hungry)"
#property description "RopebyEricNaiman - indica la dirección y la potencia de la acción de mercado."
#property version   "1.00"
#property strict
//--- incluimos la función que calcula МА, en el archivo MovingAverages.mqh
#include <MovingAverages.mqh>
//---
#property indicator_separate_window // establecemos el dibujo en una ventana separada
#property indicator_buffers 12 // establecemos 12 búferes de indicador
#property indicator_plots   5 // establecemos 5 búferes de indicador para dibujar
//--- histograma de los toros
#property indicator_label1  "BULL"
#property indicator_type1   DRAW_COLOR_HISTOGRAM
// 0 - clrDarkGreen - índice del color "solo compra", orden de compra con tipo de confirmación alto
// 1 - clrMediumSeaGreen - índice del color "orden de compra permitida", orden de compra con tipo de confirmación medio
// 2 - clrLightGreen - índice del color "orden de compra permitida", orden de compra con tipo de confirmación bajo
// 3 - clrGray - índice del color "orden de compra prohibida"
#property indicator_color1  clrDarkGreen,clrMediumSeaGreen,clrLightGreen,clrGray
#property indicator_style1  STYLE_SOLID
#property indicator_width1  2
//--- histograma de los osos
#property indicator_label2  "BEAR"
#property indicator_type2   DRAW_COLOR_HISTOGRAM
// 0 - clrDarkRed - índice del color "solo venta", orden de venta con tipo de confirmación alto
// 1 - clrIndianRed - índice del color "orden de venta permitida", orden de venta con tipo de confirmación medio
// 2 - clrLightPink - índice del color "orden de venta permitida", orden de venta con tipo de confirmación bajo
// 3 - clrGray - índice del color "orden de venta prohibida"
#property indicator_color2  clrDarkRed,clrIndianRed,clrLightPink,clrGray
#property indicator_style2  STYLE_SOLID
#property indicator_width2  2
//--- línea principal del indicador
#property indicator_label3  "main line"
#property indicator_type3   DRAW_COLOR_LINE
// 0 - clrDarkGreen - índice del color "solo compra", orden de compra con tipo de confirmación alto
// 1 - clrDarkRed - índice del color "solo venta", orden de venta con tipo de confirmación alto
// 2 - clrGray - índice del color "sin confirmación estricta"
#property indicator_color3  clrDarkGreen,clrDarkRed,clrGray
#property indicator_style3  STYLE_SOLID
#property indicator_width3  2
//--- dibujo del indicador MA rápida
#property indicator_label4  "ma rápida"
#property indicator_type4   DRAW_LINE
#property indicator_color4  clrAqua
#property indicator_style4  STYLE_SOLID
#property indicator_width4  1
//--- dibujo del indicador MA lenta
#property indicator_label5  "ma lenta"
#property indicator_type5   DRAW_LINE
#property indicator_color5  clrYellow
#property indicator_style5  STYLE_SOLID
#property indicator_width5  1

El autor no proporciona ninguna descripción de las características del color en sí, pero analiza la tendencia cuando los tres indicadores coinciden totalmente o parcialmente:

  • Fuerza de los toros > fuerza de los osos: tendencia alcista, el signo inverso indica el dominio de los osos.
  • Vigor de los toros > vigor de los osos: tendencia alcista.
  • Habilidad de los toros > habilidad de los osos: tendencia alcista.

La fuerza de la tendencia se puede evaluar comparando estos indicadores. Cuantos más indicadores confirman la tendencia, esta se vuelve más fuerte. Arriba se describe el color del histograma en función de los tres valores calculados durante la inicialización de las variables. Estos valores se pueden combinar de cualquier forma.

0: clrDarkGreen, índice del color "solo compra", orden de compra con tipo de confirmación alto.

1: clrMediumSeaGreen, índice del color "orden de compra permitida", orden de compra con tipo de confirmación medio.

2: clrLightGreen, índice del color "orden de compra permitida", orden de compra con tipo de confirmación bajo.

3: clrGray, índice del color "orden de compra prohibida".

La línea principal del indicador aparece coloreada solo cuando los tres valores calculados coinciden, tal y como se describe en el libro:

"Si BuF > BeF, BuV > BeV and BuS > BeS (en función de las relaciones dinámicas mencionadas arriba), entonces, de acuerdo a su vigor, los toros son mejores que los osos, por lo tanto solo se tienen en cuenta las órdenes de compra.

Si BuF < BeF, BuV < BeV and BuS < BeS (en función de las relaciones dinámicas), entonces los osos son mejores que los toros. Solo se tienen en cuenta las órdenes de venta."

Declaremos ahora las variables externas del indicador. Fíjese que existe la posibilidad de mostrar una línea/histograma de acuerdo a las variables de entrada draw_line y draw_histogram, para facilitar las operaciones con el indicador. Seleccione los precios del indicador y realice cálculos universales con el parámetro _price. La configuración del indicador МА se ejecuta con una opción que se puede desactivar.

//--- parámetros de entrada
input string section_1="___ configuración principal";
//--- activamos el dibujo del histograma de toros y osos
input bool draw_histogram=true;
//--- enable dibujamos la línea principal del indicador
input bool draw_line=true;
//--- periodo del indicador
input int _period=76;
//--- precio utilizado en los cálculos
input ENUM_APPLIED_PRICE _price=PRICE_CLOSE;
//--- restricciones en los cálculos de la barra
input int max_bars=0;
//--- breve desplazamiento de la línea y МА con respecto al histograma, para que el indicador sea más claro. Los valores de la línea principal y MA se multiplican por line_deviation
input double line_deviation=3.0;
//---
input string section_2="___ MA fast";
//--- activamos el dibujo de la МА rápida
input bool draw_MA_fast=false;
//--- periodo del cálculo de la MA rápida basado en el indicador
input int period_MA_fast=25;
//--- método de cálculo de la media móvil rápida
input ENUM_MA_METHOD method_MA_fast=MODE_SMA;
//---
input string section_3="___ MA slow";
//--- activamos el dibujo de la МА rápida
input bool draw_MA_slow=false;
//--- periodo de cálculo de la MA lenta basado en el indicador
input int period_MA_slow=143;
//--- método de cálculo de la media móvil rápida
input ENUM_MA_METHOD method_MA_slow=MODE_SMA;
//---- búferes
...

El libro contiene unas cuantas opciones para trabajar con el valor de la "cuerda". Hemos seleccionado los siguientes:

  • Intersección del indicador con la línea cero.
  • Solo operamos cuando los tres valores, fuerza, vigor y habilidad, coinciden. Se implementa con los colores de la línea principal.
  • Intersección del indicador con МА.
  • Intersección de dos МАs.

El indicador MA (disponible en la librería MovingAverages.mqh) se crea a partir de los valores de la línea principal del indicador, presentes en el array Buffer_calcLINE. Esto facilita el acceso a los datos antes de transferirlos a la función que calcula MA.

Los datos principales para calcular y crear el indicador se inicializan en la función OnInit. Es importante vaciar el valor de las variables prev_rates_total y _tm_prev en aquellos cálculos donde el periodo del gráfico cambia o el indicador se reinicia. El valor _tm_prev hace el seguimiento del tiempo de la última barra calculada, a partir de la cual comienzan a realizarse los cálculos, cuando aparece la siguiente barra. El parámetro prev_rates_total mantiene el valor anterior - rates_total (en el tick anterior). Comparándolo con el rates_total actual (número de barras o tamaño del array price[]), vemos que los datos se han recalculado, no se cargaron todas las barras, el nuevo cálculo se hizo para prevenir la carga de agujeros (gaps) del historial, y, como resultado, los datos no se muestran correctamente en el gráfico.

//+------------------------------------------------------------------+
//| Función de inicialización del indicador personalizado            |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- mensaje de log; ejecutamos el indicador por primera vez
   Print(__FUNCTION__+"\\ Inicialización | _period: ",_period);
//--- número de dígitos decimales del símbolo actual
   _digits=(int)SymbolInfoInteger(Symbol(),SYMBOL_DIGITS);
//---visualización precisa de los valores del indicador
   IndicatorSetInteger(INDICATOR_DIGITS,_digits);
//--- establecemos el nombre del indicador que se muestra en la ventana
   IndicatorSetString(INDICATOR_SHORTNAME,"RopebyEricNaiman");
//--- INDICATOR_DATA - almacena los datos para dibujar
//--- INDICATOR_COLOR_INDEX - almacena los índices del color
//--- INDICATOR_CALCULATIONS - almacena los datos de cálculos intermedios no pensados para dibujar
   SetIndexBuffer(0,Buffer_main_bull,INDICATOR_DATA); // búfer de datos del histograma alcista
   SetIndexBuffer(1,Buffer_color_bull,INDICATOR_COLOR_INDEX);  // búfer de datos de los colores alcistas
   SetIndexBuffer(2,Buffer_main_bear,INDICATOR_DATA); // búfer de datos del histograma bajista
   SetIndexBuffer(3,Buffer_color_bear,INDICATOR_COLOR_INDEX);  // búfer de datos de los colores bajistas
   SetIndexBuffer(4,Buffer_mainline,INDICATOR_DATA); // búfer de datos de la línea principal del indicador
   SetIndexBuffer(5,Buffer_mainline_color,INDICATOR_COLOR_INDEX); // búfer de datos de los colores de la línea principal del indicador
   SetIndexBuffer(6,Buffer_MAfast,INDICATOR_DATA); // búfer de datos de la MA rápida
   SetIndexBuffer(7,Buffer_MAslow,INDICATOR_DATA); // búfer de datos de la MA lenta
   SetIndexBuffer(8,Buffer_calc,INDICATOR_CALCULATIONS); // búfer de datos de los cálculos del precio
   SetIndexBuffer(9,Buffer_calc_bull,INDICATOR_CALCULATIONS); // búfer de datos alcistas calculados
   SetIndexBuffer(10,Buffer_calc_bear,INDICATOR_CALCULATIONS); // búfer de datos bajistas calculados
   SetIndexBuffer(11,Buffer_calcLINE,INDICATOR_CALCULATIONS); // búfer de datos calculados de la MA
//--- vaciamos la hora de la última barra calculada y prev_rates_total (rates_total en la llamada anterior // rates_total = tamaño del array price[])
   _tm_prev=0;
   prev_rates_total=0;
//---
   return(INIT_SUCCEEDED);
  }

La función OnCalculate realiza otros cálculos adicionales para mostrar los datos en el gráfico. Si tenemos en cuenta los cálculos de la tabla del libro de Nayman, en la página 147, un cambio positivo es un resultado positivo de la diferencia de dos precios, y el precio es un precio de cierre (al utilizar price=PRICE_CLOSE). Esta diferencia puede indicar tanto un mercado alcista (cambio positivo) como uno bajista (cambio negativo). Además se contemplará como una "barra" formada por un precio de apertura igual al precio de cierre de la barra anterior, y un precio de cierre de la barra calculada establecido por la función:

for(int i=1; i<bars_calc && !IsStopped(); i++)
        {
         ...

Para calcular los tres indicadores principales debemos tomar el array de precios de acuerdo al ajuste _price, y calcular el valor de la variable _period utilizando el operador for. Esto es necesario para calcular los cambios de precio positivos (toros) y los negativos (osos), así como la cantidad de cambios producidos en el período, y para encontrar la relación, dividiendo la suma por la cantidad:

  • if(total_bull>0) Buffer_calc_bull[i]=sum_bull/total_bull; — para los toros.
  • if(total_bear>0) Buffer_calc_bear[i]=sum_bear/total_bear; — para los osos.

A continuación se muestra un ejemplo de cálculo con toros, osos y línea principal del histograma con periodo _period=5:


En consecuencia, como resultado de la suma de los toros y los osos, aparece una "cuerda" en cada barra que se utiliza posteriormente para realizar otros cálculos. Esto se representa en el indicador en forma de línea de tres colores, que se pintan mediante el búfer de color del indicador, Buffer_mainline_color[]. A continuación se muestra el código de la función OnCalculate().

//+------------------------------------------------------------------+
//| Función de iteración del indicador personalizado                 |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,    // tamaño del array price[]
                const int prev_calculated,// barras procesadas en la llamada anterior
                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[])
  {
   ArraySetAsSeries(time,true);
//--- establecemos la indexación del array como en las series temporales, el índice menor 0 contiene el último valor conocido del historial
   ArraySetAsSeries(open,true);
   ArraySetAsSeries(high,true);
   ArraySetAsSeries(low,true);
   ArraySetAsSeries(close,true);
   ArraySetAsSeries(Buffer_main_bull,true);
   ArraySetAsSeries(Buffer_color_bull,true);
   ArraySetAsSeries(Buffer_main_bear,true);
   ArraySetAsSeries(Buffer_color_bear,true);
   ArraySetAsSeries(Buffer_mainline,true);
   ArraySetAsSeries(Buffer_mainline_color,true);
   ArraySetAsSeries(Buffer_MAfast,true);
   ArraySetAsSeries(Buffer_MAslow,true);
   ArraySetAsSeries(Buffer_calc,true);
   ArraySetAsSeries(Buffer_calc_bull,true);
   ArraySetAsSeries(Buffer_calc_bear,true);
   ArraySetAsSeries(Buffer_calcLINE,true);
//--- 
   int copy=0;
   bars_calc=0;
//--- cálculos de los datos del indicador
//--- cuando prev_calculated = 0, los datos se calculan de nuevo en todas las barras, =0 puede ser igual a cero después del agujero (gap) en el historial, por ejemplo, al desconectarnos de Internet durante un periodo de tiempo largo
   if(prev_calculated==0) _tm_prev=0;
//---si el tamaño anterior es mayor que el actual, indica un fallo, y los datos se tienen que recalcular
   if(prev_rates_total>rates_total) _tm_prev=0;
   if(_tm_prev<time[0]) // cálculo cuando aparece una barra nueva
     {
      if(_tm_prev>0) // si el indicador ya tiene datos calculados previamente
        {
         copy=TakeShift_byTime(Symbol(),PERIOD_CURRENT,_tm_prev); // el desplazamiento de la barra del símbolo actual a lo largo de la última barra
         if(copy<=0) // si el desplazamiento no se encuentra, entonces los cálculos se apartan y se repiten en el siguiente tick
           {
            return 0;
           }
         bars_calc=copy+1; // establecemos el desplazamiento de la barra para comenzar los cálculos a partir de la barra actual del indiciador que no está cerrada
         //--- vaciamos la primera barra actual no cerrada, es decir, los datos no se calculan
         Buffer_main_bull[0]=0.0;
         Buffer_color_bull[0]=5; // establecer el índice del color a 5 significa color vacío, por lo tanto el color no se pinta
         Buffer_main_bear[0]=0.0;
         Buffer_color_bear[0]=5; // establecer el índice del color a 5 significa color vacío, por lo tanto el color no se pinta
         Buffer_mainline[0]=0.0;
         Buffer_mainline_color[0]=5; // establecer el índice del color a 5 significa color vacío, por lo tanto el color no se pinta
         Buffer_MAfast[0]=0.0;
         Buffer_MAslow[0]=0.0;
         Buffer_calc[0]=0.0;
         Buffer_calc_bull[0]=0.0;
         Buffer_calc_bear[0]=0.0;
         Buffer_calcLINE[0]=0.0;
        }
      else // si el indicador se configura por primera vez y los valores no se calculan
        {
         bars_calc=Bars(Symbol(),PERIOD_CURRENT)-1; // el desplazamiento de la barra para comenzar los cálculos se establece en el número total de barras -1
         //--- vaciamos los datos de todas las barras para evitar errores de dibujo 
         for(int i=0; i<Bars(Symbol(),PERIOD_CURRENT) && !IsStopped(); i++)
           {
            Buffer_main_bull[i]=0.0;
            Buffer_main_bear[i]=0.0;
            Buffer_mainline[i]=0.0;
            Buffer_MAfast[i]=0.0;
            Buffer_MAslow[i]=0.0;
            Buffer_calc[i]=0.0;
            Buffer_calc_bull[i]=0.0;
            Buffer_calc_bear[i]=0.0;
            Buffer_calcLINE[i]=0.0;
           }
        }
      //--- si la cantidad de barras de los cálculos del indicador es menor que cero, cancelamos los cálculos
      if(bars_calc<0) return 0;
      //--- restricción de la cantidad de barras para calcular el valor max_bars
      if(bars_calc>max_bars && max_bars!=0) bars_calc=max_bars;
      for(int i=1; i<bars_calc && !IsStopped(); i++)
        {
         //--- cálculo de la diferencia entre las cotizaciones de dos barras de acuerdo a la configuración _price
         switch(_price)
           {
            case PRICE_CLOSE:
               Buffer_calc[i]=close[i]-close[i+1];
               break;
            case PRICE_OPEN:
               Buffer_calc[i]=open[i]-open[i+1];
               break;
            case PRICE_HIGH:
               Buffer_calc[i]=high[i]-high[i+1];
               break;
            case PRICE_LOW:
               Buffer_calc[i]=low[i]-low[i+1];
               break;
            case PRICE_MEDIAN:
               Buffer_calc[i]=((high[i]+low[i])/2)-((high[i+1]+low[i+1])/2);
               break;
            case PRICE_TYPICAL:
               Buffer_calc[i]=((high[i]+low[i]+close[i])/3)-((high[i+1]+low[i+1]+close[i+1])/3);
               break;
            case PRICE_WEIGHTED:
               Buffer_calc[i]=((high[i]+low[i]+close[i]+close[i])/4)-((high[i+1]+low[i+1]+close[i+1]+close[i+1])/4);
               break;
            default: return 0;
           }
        }
      //--- iteramos las barras que no se han calculado hasta que el bucle termina
      for(int i=1; i<=bars_calc && !IsStopped(); i++)
        {
         //--- vaciamos los datos 
         sum_bull=0.0; // suma de los cambios positivos (toros) en el periodo de tiempo analizado
         total_bull=0; // suma de la cantidad de cambios positivos en el periodo de tiempo analizado
         sum_bear=0.0; // suma de los cambios negativos (osos) en el periodo de tiempo analizado
         total_bear=0; // suma de los cambios negativos en el periodo de tiempo analizado

         Buffer_main_bull[i]=0.0;
         Buffer_color_bull[i]=5;
         Buffer_main_bear[i]=0.0;
         Buffer_color_bear[i]=5;
         Buffer_mainline[i]=0.0;
         Buffer_mainline_color[0]=5;

         Buffer_calc_bull[i]=0.0;
         Buffer_calc_bear[i]=0.0;
         Buffer_calcLINE[i]=0.0;
         //--- paramos los cálculos de la barra, si caen más allá de los datos disponibles según el período analizado 
         if(i>=(rates_total-_period)) continue;
         //--- iteramos los datos en el periodo analizado (_period) a partir de la barra actual
         for(int i2=i; i2<i+_period; i2++)
           {
            //--- cálculo de los toros
            if(Buffer_calc[i2]>0)
              {
               sum_bull+=Buffer_calc[i2]; // sumamos los precios de las barras positivas ("suma de los cambios positivos en el periodo de tiempo analizado")
               total_bull++; // calculamos la cantidad de barras positivas ("cantidad de cambios positivos en el periodo de tiempo analizado")
              }
            //--- cálculo de los osos
            if(Buffer_calc[i2]<0)
              {
               sum_bear+=Buffer_calc[i2]; // sumamos los precios de las barras negativas ("suma de los cambios negativos en el periodo de tiempo analizado")
               total_bear++; // calculamos la cantidad de barras negativas ("cantidad de cambios negativos en el periodo de tiempo analizado")
              }
           }
         //--- calculamos la "habilidad de los toros", dividiendo el valor de la barra en puntos por la cantidad de barras
         if(total_bull>0) Buffer_calc_bull[i]=sum_bull/total_bull;
         //--- calculamos la "habilidad de los osos"
         if(total_bear>0) Buffer_calc_bear[i]=sum_bear/total_bear;
         //--- dibujamos el histograma con colores por categorías de la señal de confirmación
         if(draw_histogram)
           {
            //--- dibujamos el histograma de los toros, dividiendo el valor de la barra en puntos por la cantidad de barras
            if(total_bull>0) Buffer_main_bull[i]=sum_bull/total_bull;
            //--- dibujamos el histograma de los osos, dividiendo el tamaño de la barra en puntos por la cantidad de barras
            if(total_bear>0) Buffer_main_bear[i]=sum_bear/total_bear;
            //--- 0 color del histograma clrDarkGreen - índice del color "solo compra", orden de compra con tipo de confirmación alto
            //--- tipo de confirmación - los tres indicadores revelan una tendencia alcista
            //--- vigor de los toros > vigor de los osos y fuerza de los toros > fuerza de los osos y habilidad de los toros > habilidad de los osos
            //--- vigor - cantidad de barras
            //--- fuerza - suma del tamaño de la barra en puntos
            //--- habilidad - valor medio de las sumas de las barras sobre el periodo indicado fuerza/vigor
            if(total_bull>total_bear && MathAbs(sum_bull)>MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])>MathAbs(Buffer_main_bear[i])) Buffer_color_bull[i]=0;
            else
              {
               //--- 1 color del histograma clrMediumSeaGreen - índice del color "orden de compra permitida", orden de compra con tipo de confirmación medio
               //--- tipo de confirmación - con dos indicadores alcistas y uno bajista, en cualquier combinación
               if((total_bull>total_bear && MathAbs(sum_bull)>MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])<MathAbs(Buffer_main_bear[i])) || 
                  (total_bull>total_bear && MathAbs(sum_bull)<MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])>MathAbs(Buffer_main_bear[i])) || 
                  (total_bull<total_bear && MathAbs(sum_bull)>MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])>MathAbs(Buffer_main_bear[i]))) Buffer_color_bull[i]=1;
               else
                 {
                  //--- 2 color del histograma clrLightGreen - índice del color "orden de compra permitida", orden de compra con tipo de confirmación bajo
                  //--- tipo de confirmación - con un indicador alcista y dos indicadores bajistas, en cualquier combinación 
                  if((total_bull>total_bear && MathAbs(sum_bull)<MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])<MathAbs(Buffer_main_bear[i])) || 
                     (total_bull<total_bear && MathAbs(sum_bull)>MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])<MathAbs(Buffer_main_bear[i])) || 
                     (total_bull<total_bear && MathAbs(sum_bull)<MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])>MathAbs(Buffer_main_bear[i]))) Buffer_color_bull[i]=2;
                  else
                    {
                     //--- 3 color del histograma clrGray - índice del color "orden de compra prohibida"
                     //--- tipo de confirmación - cuando no hay indicador alcista
                     Buffer_color_bull[i]=3;
                    }
                 }
              }
            //--- 0 color del histograma clrDarkRed - índice del color "solo venta", orden de venta con tipo de confirmación alto
            //--- tipo de confirmación - los tres indicadores revelan una tendencia alcista
            if(total_bull<total_bear && MathAbs(sum_bull)<MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])<MathAbs(Buffer_main_bear[i])) Buffer_color_bear[i]=0;
            else
              {
               //--- color del histograma clrIndianRed - índice del color "orden de venta permitida", orden de venta con tipo de confirmación medio
               //--- tipo de confirmación - con dos indicadores alcistas y un indicador alcista, en cualquier combinación
               if((total_bull<total_bear && MathAbs(sum_bull)<MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])>MathAbs(Buffer_main_bear[i])) || 
                  (total_bull<total_bear && MathAbs(sum_bull)>MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])<MathAbs(Buffer_main_bear[i])) || 
                  (total_bull>total_bear && MathAbs(sum_bull)<MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])<MathAbs(Buffer_main_bear[i]))) Buffer_color_bear[i]=1;
               else
                 {
                  //--- 2 color del histograma clrLightPink - índice del color "orden de venta permitida", orden de venta con tipo de confirmación bajo
                  //--- tipo de confirmación - con un indicador bajista y dos indicadores alcistas, en cualquier combinación
                  if((total_bull<total_bear && MathAbs(sum_bull)>MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])>MathAbs(Buffer_main_bear[i])) || 
                     (total_bull>total_bear && MathAbs(sum_bull)<MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])>MathAbs(Buffer_main_bear[i])) || 
                     (total_bull>total_bear && MathAbs(sum_bull)>MathAbs(sum_bear) && MathAbs(Buffer_main_bull[i])<MathAbs(Buffer_main_bear[i]))) Buffer_color_bear[i]=2;
                  else
                    {
                     //--- 3 color del histograma clrGray - índice del color "orden de venta prohibida"
                     //--- tipo de confirmación - sin indicador bajista
                     Buffer_color_bear[i]=3;
                    }
                 }
              }
           }
         //--- valor de la línea principal, sumando las habilidades de los osos y los toros
         Buffer_calcLINE[i]=(Buffer_calc_bull[i]+Buffer_calc_bear[i])*line_deviation;
         //--- dibujamos la línea con colores por tipo de confirmación de señal
         // 0 - clrDarkGreen - índice del color "solo compra", orden de compra con tipo de confirmación alto
         // 1 - clrDarkRed - índice del color "solo venta", orden de venta con tipo de confirmación alto
         // 2 - clrGray - índice del color "sin confirmación estricta"
         if(draw_line)
           {
            //--- dibujamos la línea principal, se suman las habilidades de los osos y de los toros
            Buffer_mainline[i]=(Buffer_calc_bull[i]+Buffer_calc_bear[i])*line_deviation;
            //--- establecemos la línea de color indefinido (2 - clrGray)
            Buffer_mainline_color[i]=2;
            //--- configuramos la línea de color alcista (0 - clrDarkGreen) cuando coinciden los tres indicadores alcistas (toro>oso)
            if(total_bull>total_bear && MathAbs(sum_bull)>MathAbs(sum_bear) && MathAbs(Buffer_calc_bull[i])>MathAbs(Buffer_calc_bear[i])) Buffer_mainline_color[i]=0;
            //--- configuramos la línea de color bajista (1 - clrDarkRed) cuando coinciden los tres indicadores bajistas (oso>toro)
            if(total_bull<total_bear && MathAbs(sum_bull)<MathAbs(sum_bear) && MathAbs(Buffer_calc_bull[i])<MathAbs(Buffer_calc_bear[i])) Buffer_mainline_color[i]=1;
           }
        }
      //--- calculamos y dibujamos la МA
      if(draw_MA_fast || draw_MA_slow)
        {
         //--- deshabilitamos la indexación como en las series temporales para transferir a la librería MovingAverages.mqh (la indexación cambia para tener una barra del historial al final del array)
         ArraySetAsSeries(Buffer_calcLINE,false);
         ArraySetAsSeries(Buffer_MAfast,false);
         ArraySetAsSeries(Buffer_MAslow,false);
         //--- iteración de las barras sin calcular Iteración = Todas las barras (rates_total) - desplazamiento de la barra desde la última hora calculada conocida _tm_prev (bars_calc)
         for(int i=rates_total-bars_calc; i<rates_total && !IsStopped(); i++)
           {
            //--- restricción de cálculos en el parámetro max_bars, cálculo solo para la cantidad establecida de max_bars como la diferencia total de todas las barras (rates_total) menos la cantidad (max_bars)
            if(max_bars>0?(i<(rates_total-max_bars)):false)
              {
               //--- si el índice actual i cae más allá del valor admisible, se procede con el índice permitido.
               i=rates_total-max_bars;
               continue;
              }
            //--- vaciamos el array si los datos MA no se reciben
            Buffer_MAfast[i]=0.0;
            Buffer_MAslow[i]=0.0;
            //--- seleccionamos el método de cálculo de la MA rápida según el parámetro method_MA_fast
            if(draw_MA_fast)
              {
               switch(method_MA_fast)
                 {
                  case MODE_SMA: // Media sencilla
                     Buffer_MAfast[i]=SimpleMA(i,period_MA_fast,Buffer_calcLINE); // obtenemos los datos del índice i de SimpleMA, que obtenemos de la librería Include\\MovingAverages.mqh, según los datos del búfer Buffer_calcLINE y el periodo period_MA_fast
                     break;
                  case MODE_EMA: // Media exponencial
                     Buffer_MAfast[i]=ExponentialMA(i,period_MA_fast,Buffer_MAfast[i-1],Buffer_calcLINE);
                     break;
                  case MODE_SMMA: // Media suavizada
                     Buffer_MAfast[i]=SmoothedMA(i+period_MA_fast,period_MA_fast,Buffer_MAfast[i-1],Buffer_calcLINE);
                     break;
                  case MODE_LWMA: // Promedio ponderado lineal
                     Buffer_MAfast[i]=LinearWeightedMA(i+period_MA_fast,period_MA_fast,Buffer_calcLINE);
                     break;
                  default: return 0;
                 }
              }
            //--- seleccionamos el método de cálculo de la MA lenta según el parámetro method_MA_slow
            if(draw_MA_slow)
              {
               switch(method_MA_slow)
                 {
                  case MODE_SMA: // Media sencilla
                     Buffer_MAslow[i]=SimpleMA(i,period_MA_slow,Buffer_calcLINE);
                     break;
                  case MODE_EMA: // Media exponencial
                     Buffer_MAslow[i]=ExponentialMA(i,period_MA_slow,Buffer_MAslow[i-1],Buffer_calcLINE);
                     break;
                  case MODE_SMMA: // Media suavizada
                     Buffer_MAslow[i]=SmoothedMA(i,period_MA_slow,Buffer_MAslow[i-1],Buffer_calcLINE);
                     break;
                  case MODE_LWMA: // Promedio ponderado lineal
                     Buffer_MAslow[i]=LinearWeightedMA(i,period_MA_slow,Buffer_calcLINE);
                     break;
                  default: return 0;
                 }
              }
           }
         //--- activamos la indexación como en las series temporales para dibujar
         ArraySetAsSeries(Buffer_calcLINE,true);
         ArraySetAsSeries(Buffer_MAfast,true);
         ArraySetAsSeries(Buffer_MAslow,true);
         //--- vaciamos los datos MA de la barra actual, es decir, la barra sin calcular
         Buffer_MAfast[0]=EMPTY_VALUE;
         Buffer_MAslow[0]=EMPTY_VALUE;
         Buffer_calcLINE[0]=EMPTY_VALUE;
        }
      //--- memorizamos la hora de la última barra calculada
      _tm_prev=time[0];
     }
//--- devolvemos el valor prev_calculated para la próxima llamada
   prev_rates_total=rates_total;
   return(rates_total);
  }

Los valores de la línea principal han aumentado (valor de la línea principal * line_deviation), y ahora están más allá del histograma para favorecer la visualización de las líneas y el histograma. Se añade la restricción de la cantidad de barras (max_bars) con el objetivo de acelerar los cálculos en los periodos pequeños, por ejemplo М1. El último bloque del código TakeShift_byTime obtiene la desviación de la barra en el tiempo para encontrar la cantidad de barras necesarias para hacer los cálculos enbars_calc.


Capítulo 2. Implementación práctica del indicador "Cuerda" y creación de un Asesor Experto

En este capítulo nos centramos en la creación del Asesor Experto EARopebyEricNaiman basado en el indicador "Cuerda" (este es el nombre del código fuente del indicador, RopebyEricNaiman). El indicador se puede utilizar en una estrategia distinta basada en el ejemplo del Asesor Experto EARopebyEricNaiman, y un filtro para encontrar la dirección de la tendencia. El autor estudia varias aproximaciones que gestionan los datos calculados por el indicador. En nuestro Asesor Experto hemos seleccionado las siguientes:

  • Cruce de la línea principal con el 0. Por encima de la intersección: orden de compra; por debajo de la intersección: orden de venta.

  • Abrimos una posición cuando el color de la línea principal pasa de gris a verde (compra) o cuando pasa de gris a rojo (venta).

  • Abrimos una posición cuando la línea principal se cruza con la МА rápida (MAfast). La línea principal cruza la MA por encima: orden de compra; por debajo: orden de venta.

  • Abrimos una posición cuando se cruzan las dos MAs. La MA rápida cruza la MA lenta por encima: orden de compra; por debajo: orden de venta.

Además de los parámetros principales, el Asesor Experto permite configurar cuatro tipos de cierre correspondientes a las señales de apertura por separado, pero en la dirección opuesta en comparación con el tipo de la posición abierta:

//---  configuración de cierre de posición
input string section_5="___ Configuración de cierre";
//--- cerramos cuando la línea principal se cruza con el cero / BUY cierre en la intersección por debajo
input bool close1=true; // Cerrar cuando la línea principal se cruza con el cero
//--- cierre cuando el color cambia al color opuesto de la posición abierta / BUY cerrar al cambiar a rojo
input bool close2=false; // Cerrar cuando la línea principal cambia de color
//--- cierre en la intersección de la línea principal con la línea MA/ BUY cerrar en la intersección de la línea principal por debajo de MA
input bool close3=false; // Cerrar cuando la línea principal se cruza con MAfast
//---  cierre en la intersección de dos MAs / BUY cierre en la intersección de la MA rápida con la MA lenta por debajo
input bool close4=true; // Cerrar cuando se cruzan dos MA

Por lo tanto, la apertura de la posición depende del método seleccionado en la variable trade_mode, y el cierre se ejecuta con un Stop Loss o Take Profit mediante uno de los métodos descritos arriba. El código fuente del Asesor Experto y el indicador se encuentran disponibles para descarga en los archivos que se adjuntan más adelante. En este artículo tan solo analizamos la parte principal que gestiona la apertura y el cierre de las posiciones.

  • Tanto las variables principales como el indicador RopebyEricNaiman se inicializan en el bloque OnInit().
  • El bloque OnTick() contiene la parte que gestiona la apertura y el cierre de las posiciones.
  • En Check_Indi_Open(), el bloque que calcula las señales, cargamos los datos del indicador y buscamos una señal de apertura:
//+------------------------------------------------------------------+
//| Check_Indi_Open                                                  |
//+------------------------------------------------------------------+
int Check_Indi_Open()
  {
   //--- declaración de arrays que obtienen los datos del indicador
   int copy=0;
   double _arr_ind_1[];
   double mafast[];
   double mainline[];
   double maslow[];
   //--- con este switch seleccionamos el método de apertura a partir de la variable externa trade_mode
   switch((int)trade_mode)
     {
      case 0:
         //--- comparación de la línea principal del indicador en las dos últimas barras, excepto la actual
         copy=Copy_indi_Buffer(RbEN_handle,4,1,2,_arr_ind_1,"RbEN");
         if(copy!=2) return 4;
         if(_arr_ind_1[0]!=EMPTY_VALUE && _arr_ind_1[1]!=EMPTY_VALUE && 
            _arr_ind_1[0]>0 && _arr_ind_1[1]<=0)
           {
            return 0;
           }
         if(_arr_ind_1[0]!=EMPTY_VALUE && _arr_ind_1[1]!=EMPTY_VALUE && 
            _arr_ind_1[0]<0 && _arr_ind_1[1]>=0)
           {
            return 1;
           }
         break;
      case 1:
         //--- obtenemos el índice del color del indicador a partir del búfer número cinco en las dos últimas barras, excepto la actual
         copy=Copy_indi_Buffer(RbEN_handle,5,1,2,_arr_ind_1,"RbEN");
         if(copy!=2) return 5;
         if(_arr_ind_1[0]!=EMPTY_VALUE && _arr_ind_1[1]!=EMPTY_VALUE && 
            _arr_ind_1[0]==0 && _arr_ind_1[1]!=0)
           {
            return 0;
           }
         if(_arr_ind_1[0]!=EMPTY_VALUE && _arr_ind_1[1]!=EMPTY_VALUE && 
            _arr_ind_1[0]==1 && _arr_ind_1[1]!=1)
           {
            return 1;
           }
         break;
      case 2:
         //--- recibimos y comparamos los valores mafast (МА en la línea principal del indicador) y mainline (línea principal del indicador) en las últimas dos barras, excepto la actual.
         copy=Copy_indi_Buffer(RbEN_handle,6,1,2,mafast,"RbEN");
         if(copy!=2) return 6;
         copy=Copy_indi_Buffer(RbEN_handle,4,1,2,mainline,"RbEN");
         if(copy!=2) return 7;
         if(mafast[0]!=EMPTY_VALUE && mafast[1]!=EMPTY_VALUE && 
            mainline[0]!=EMPTY_VALUE && mainline[1]!=EMPTY_VALUE && 
            mainline[0]>mafast[0] && mainline[1]<=mafast[1])
           {
            return 0;
           }
         if(mafast[0]!=EMPTY_VALUE && mafast[1]!=EMPTY_VALUE && 
            mainline[0]!=EMPTY_VALUE && mainline[1]!=EMPTY_VALUE && 
            mainline[0]<mafast[0] && mainline[1]>=mafast[1])
           {
            return 1;
           }
         break;
      case 3:
         //--- recibimos y comparamos los valores mafast (МА rápida en la línea principal del indicador) y maslow (МА lenta en la línea principal del indicador) en las últimas dos barras, excepto la actual
         copy=Copy_indi_Buffer(RbEN_handle,6,1,2,mafast,"RbEN");
         if(copy!=2) return 8;
         copy=Copy_indi_Buffer(RbEN_handle,7,1,2,maslow,"RbEN");
         if(copy!=2) return 9;
         if(mafast[0]!=EMPTY_VALUE && mafast[1]!=EMPTY_VALUE &&
            maslow[0]!=EMPTY_VALUE && maslow[1]!=EMPTY_VALUE &&
            maslow[0]<mafast[0] && maslow[1]>=mafast[1])
           {
            return 0;
           }
         if(mafast[0]!=EMPTY_VALUE && mafast[1]!=EMPTY_VALUE &&
            maslow[0]!=EMPTY_VALUE && maslow[1]!=EMPTY_VALUE &&
            maslow[0]>mafast[0] && maslow[1]<=mafast[1])
           {
            return 1;
           }
         break;
      default: return 3;
     }
//---
   return 2;
  }

El bloque Check_Indi_Close() lleva a cabo una iteración de acuerdo a los parámetros de entrada de los cuatro métodos de cierre de posición:

//+------------------------------------------------------------------+
//| Check_Indi_Close                                                 |
//+------------------------------------------------------------------+
int Check_Indi_Close()
  {
   //--- declaración de arrays que obtienen los datos del indicador
   int copy=0;
   double _arr_ind_1[];
   double mafast[];
   double mainline[];
   double maslow[];
   _str_close="";
   //--- recepción y comparación de la línea cero con la línea principal en las dos últimas barras, excepto la actual
   if(close1)
     {
      copy=Copy_indi_Buffer(RbEN_handle,4,1,2,_arr_ind_1,"RbEN");
      if(copy!=2) return 4;
      _str_close="Cerrar cuando la línea principal se cruza con el cero";
      if(_arr_ind_1[0]!=EMPTY_VALUE && _arr_ind_1[1]!=EMPTY_VALUE && 
         _arr_ind_1[0]>0 && _arr_ind_1[1]<=0)
        {
         return 0;
        }
      if(_arr_ind_1[0]!=EMPTY_VALUE && _arr_ind_1[1]!=EMPTY_VALUE && 
         _arr_ind_1[0]<0 && _arr_ind_1[1]>=0)
        {
         return 1;
        }
     }
   //--- obtenemos el índice del color del indicador a partir del búfer número cinco en las dos últimas barras, excepto la actual
   if(close2)
     {
      copy=Copy_indi_Buffer(RbEN_handle,5,1,2,_arr_ind_1,"RbEN");
      if(copy!=2) return 5;
      _str_close="Cerrar cuando la línea principal cambia de color";
      if(_arr_ind_1[0]!=EMPTY_VALUE && _arr_ind_1[1]!=EMPTY_VALUE && 
         _arr_ind_1[0]==0 && _arr_ind_1[1]!=0)
        {
         return 0;
        }
      if(_arr_ind_1[0]!=EMPTY_VALUE && _arr_ind_1[1]!=EMPTY_VALUE && 
         _arr_ind_1[0]==1 && _arr_ind_1[1]!=1)
        {
         return 1;
        }
     }
   //--- recibimos y comparamos los valores mafast (МА en la línea principal del indicador) y mainline (línea principal del indicador) en las últimas dos barras, excepto la actual.
   if(close3)
     {
      copy=Copy_indi_Buffer(RbEN_handle,6,1,2,mafast,"RbEN");
      if(copy!=2) return 6;
      copy=Copy_indi_Buffer(RbEN_handle,4,1,2,mainline,"RbEN");
      if(copy!=2) return 7;
      _str_close="Cerrar cuando la línea principal se cruza con MAfast";
      if(mafast[0]!=EMPTY_VALUE && mafast[1]!=EMPTY_VALUE && 
         mainline[0]!=EMPTY_VALUE && mainline[1]!=EMPTY_VALUE && 
         mainline[0]>mafast[0] && mainline[1]<=mafast[1])
        {
         return 0;
        }
      if(mafast[0]!=EMPTY_VALUE && mafast[1]!=EMPTY_VALUE && 
         mainline[0]!=EMPTY_VALUE && mainline[1]!=EMPTY_VALUE && 
         mainline[0]<mafast[0] && mainline[1]>=mafast[1])
        {
         return 1;
        }
     }
   //--- recibimos y comparamos los valores mafast (МА rápida en la línea principal del indicador) y maslow (МА lenta en la línea principal del indicador) en las últimas dos barras, excepto la actual
   if(close4)
     {
      copy=Copy_indi_Buffer(RbEN_handle,6,1,2,mafast,"RbEN");
      if(copy!=2) return 8;
      copy=Copy_indi_Buffer(RbEN_handle,7,1,2,maslow,"RbEN");
      if(copy!=2) return 9;
      _str_close="Cerrar cuando se cruzan dos MA";
      if(mafast[0]!=EMPTY_VALUE && mafast[1]!=EMPTY_VALUE &&
         maslow[0]!=EMPTY_VALUE && maslow[1]!=EMPTY_VALUE &&
         maslow[0]<mafast[0] && maslow[1]>=mafast[1])
        {
         return 0;
        }
      if(mafast[0]!=EMPTY_VALUE && mafast[1]!=EMPTY_VALUE &&
         maslow[0]!=EMPTY_VALUE && maslow[1]!=EMPTY_VALUE &&
         maslow[0]>mafast[0] && maslow[1]<=mafast[1])
        {
         return 1;
        }
     }
//---
   return 2;
  }

  • El bloque Copy_indi_Buffer() recibe los datos del indicador por medio de la función CopyBuffer().
  • El bloque TakeLastOpenTime() recibe la hora de la última posición abierta y la compara (en OnTick) con la hora de apertura de la barra, para evitar abrir múltiples posiciones en una barra.
  • OpenPosition() abre posiciones.
  • Copy_Time() copia la hora de la barra indicada.
  • CloseAllPosition() cierra todas las posiciones.

Después de crear el Asesor Experto, procedemos a optimizar los parámetros de entrada, tal y como describimos en el siguiente capítulo.


Capítulo 3. Optimización de los parámetros de entrada del Asesor Experto

Se aconseja optimizar los parámetros de entrada principales antes de ejecutar el Asesor Experto. A modo de ejemplo seleccionamos el símbolo EURUSD H1 2005-2015 (algoritmo genético de optimización). Implementamos una optimización diferente para cada uno de los cuatro tipos de apertura.

1. trade_mode = Cerrar cuando la línea principal se cruza con el cero (abrimos posición en la intersección de la línea principal con el 0. Si el cruce es hacia arriba: compra; si el cruce es hacia abajo: venta).

Parámetros de optimización:

Valor Inicio Paso Parada Pasos
StopLoss 0 50 10000 201
TakeProfit 0 50 10000 201
_period 1 1 200 200
close1 false
true 2
Pasos totales


16160400

Tanto la optimización como los resultados de las pruebas se encuentran en el archivo optimization.zip de la carpeta "EURUSD H1 2005-2015\test1 - main line cross zero\".


2. trade_mode = Cerrar cuando la línea principal cambia de color (abrimos posición cuando el color de la línea principal pasa de gris a verde (compra) o de gris a rojo (venta)).

Parámetros de optimización:

Valor Inicio Paso Parada Pasos
StopLoss 0 50 10000 201
TakeProfit 0 50 10000 201
_period 1 1 200 200
close2 false
true 2
Pasos totales


16160400

Tanto la optimización como los resultados de las pruebas se encuentran en el archivo optimization.zip de la carpeta "EURUSD H1 2005-2015\test2 - main line color\".


3. trade_mode = cruce de la línea principal con MAfast (abrimos posición en la intersección de la línea principal con la MA rápida. Si la línea principal cruza la MA por arriba: compra; si lo hace por debajo: venta).

Parámetros de optimización:

Valor Inicio Paso Parada Pasos
StopLoss 0 50 10000 201
TakeProfit 0 50 10000 201
_period 1 1 200 200
period_MA_fast 1 1 300 300
close3 false
true 2
Pasos totales


4848120000

Tanto la optimización como los resultados de las pruebas se encuentran en el archivo optimization.zip de la carpeta "EURUSD H1 2005-2015\test3 - main line cross MAfast\".


4. trade_mode = cruce de dos MA (abrimos posición en la intersección de dos MAs. Si la MA rápida se cruza con la lenta por encima: orden de compra; si lo hace por debajo: orden de venta).

Parámetros de optimización:

Valor Inicio Paso Parada Pasos
StopLoss 0 50 10000 201
TakeProfit 0 50 10000 201
_period 1 1 200 200
period_MA_fast 1 1 300 300
period_MA_slow 1 1 400 400
close4 false
true 2
Pasos totales


1939248000000

Tanto la optimización como los resultados de las pruebas se encuentran en el archivo optimization.zip de la carpeta "EURUSD H1 2005-2015\test4 - two MA cross\".



Conclusión

La optimización de los resultados demuestra la viabilidad de esta estrategia. Pensemos que el Asesor Experto se construye bajo la idea, puramente lógica, de un indicador sin funciones adicionales de gestión del dinero. Simplemente, la estrategia del autor consiste en descubrir la tendencia a partir de la evaluación estática del vigor de los osos y los toros en el periodo de tiempo especificado. Con este indicador definimos los puntos centrales de entrada al mercado, y por lo tanto, se puede utilizar para filtrar la estrategia y también como señal básica de apertura de posiciones.

Eche un vistazo al código fuente del indicador y del Asesor Experto, esto le ayudará a tomar ideas prácticas que le servirán para desarrollar sus propios programas y para optimizar sus operaciones de trading. Finalmente, la estrategia que hemos expuesto en este artículo se ha aplicado solo en algunos ámbitos específicos, en concreto hemos tratado las señales básicas de entrada y salida; y se ha demostrado su capacidad de funcionamiento en las fases iniciales.

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

Archivos adjuntos |
optimization.zip (2230.41 KB)
Utilización de layouts y contenedores en los controles GUI: la clase CGrid Utilización de layouts y contenedores en los controles GUI: la clase CGrid

Este artículo explica un método alternativo de creación de GUIs basado en layouts y contenedores por medio de un gestor de layouts: la clase CGrid. La clase CGrid es un control auxiliar que actúa como contenedor de contenedores y controles, utilizando un diseño de rejilla o cuadrícula (grid layout).

Aserciones en los programas MQL5 Aserciones en los programas MQL5

Este artículo explica cómo utilizar aserciones en el lenguaje MQL5. Proporciona dos mecanismos de aserción a modo de ejemplo, así como una guía para implementarlas correctamente.

Interfaces gráficas II: Control "Elemento del menú" (Capítulo 1) Interfaces gráficas II: Control "Elemento del menú" (Capítulo 1)

En la segunda parte de la serie demostraremos el proceso del desarrollo de los controles como el menú principal y el menú contextual. Además, trataremos la cuestión del dibujo de los controles, y para ello vamos a crear una clase especial. También aclararemos detalladamente la cuestión de la gestión de los eventos del programa, inclusive los eventos del usuario.

Cómo añadir rápidamente un panel de control a un indicador o asesor Cómo añadir rápidamente un panel de control a un indicador o asesor

¿Quiere añadir a su indicador o asesor un panel gráfico de control rápido y cómodo, pero no sabe como hacerlo? En este artículo le enseñaré paso a paso cómo "atornillar" un panel de diálogo con parámetros de entrada a su programa MQL4/MQL5.