English Русский Deutsch 日本語 Português
preview
Desarrollo y prueba de los sistemas comerciales Aroon

Desarrollo y prueba de los sistemas comerciales Aroon

MetaTrader 5Trading | 18 julio 2024, 13:14
65 0
Mohamed Abdelmaaboud
Mohamed Abdelmaaboud

Introducción

En el campo del trading y del análisis técnico, hay muchas herramientas que podemos utilizar, pero definitivamente no podemos usarlas todas, así que elegiremos una herramienta o una combinación rentable de ellas tras ponerlas a prueba y optimizarlas. El propósito de este artículo es tratar de ofrecer un método que pueda ser útil en este contexto, u ofrecer una idea desde otro punto de vista o una idea que se pueda aplicar y ver qué sistema de comercio automatizado es el adecuado para usted.

Los artículos de este tipo son útiles porque su estudio no requiere mucho tiempo; eso sí, la mayor parte del trabajo tendrá que hacerla usted mismo para encontrar la configuración óptima del sistema comercial. Aquí solo estamos tratando de presentar herramientas comerciales que puedan utilizarse individualmente o en combinación con otras herramientas para ahorrarle tiempo. También describiremos cómo programar estos sistemas para su comprobación en el simulador de estrategias. Y esto significa que podrá ahorrar mucho tiempo automatizando el proceso de prueba en lugar de hacerlo manualmente.

En este artículo, utilizaremos el indicador técnico Aroon, probaremos más de una estrategia basada en sus conceptos y veremos los resultados. Y lo que es mucho más valioso, aprenderemos cómo podemos codificar un indicador de MQL5 y utilizarlo en nuestro sistema comercial basado en estrategias. Todo esto sucederá después de que aprendamos qué es el indicador Aroon y cómo se puede calcular y usar.

En el presente artículo trataremos los siguientes temas:

Siguiendo con los temas anteriores, hoy aprenderemos mucho más sobre el indicador Aroon, concretamente, cómo podemos utilizarlo, qué necesitamos para construir un sistema comercial, las estrategias comerciales con Aroon, cómo construir sistemas comerciales basados en estas estrategias y probarlos, y ver hasta qué punto son útiles en el trading.

Las pruebas deben realizarse en diferentes aspectos para obtener los mejores resultados que se adapten a su estilo comercial o a su sistema comercial, especialmente si va a añadir una herramienta a un sistema existente. No hay estrategias o sistemas comerciales que sirvan para todos, pero puedo aportar mi granito de arena mostrando algunos de ellos para ayudarle a ahorrar tiempo.

¡Atención! Toda la información del presente artículo se ofrece «tal cual», únicamente con fines ilustrativos, y no supone ningún tipo de recomendación. El artículo no garantiza ningún resultado en absoluto. Todo lo que ponga en práctica usando este artículo como base, lo hará bajo su propia cuenta y riesgo; el autor no garantiza resultado alguno.


Definición del indicador Aroon

En primer lugar, definiremos el indicador técnico Aroon para comprender su idea básica.

Aroon fue creada por Tushar S. Chande en 1995. Los principales objetivos del indicador consisten en detectar los cambios de tendencia y también medir la fuerza de la misma. Un indicador puede hacer esto midiendo cuánto tiempo ha pasado entre los máximos y cuánto tiempo ha pasado entre los mínimos durante un periodo de tiempo. Una tendencia alcista intensa se manifiesta en la aparición regular de nuevos máximos y una tendencia bajista intensa se manifiesta en la aparición regular de nuevos mínimos. El indicador detecta estas pautas y las señala.

El indicador Aroon consta de dos líneas: Aroon Up, que mide la fuerza de la tendencia alcista, y Aroon Down, que mide la fuerza de la tendencia bajista. En este contexto, podemos decir que cuando Aroon Up se encuentra por encima de Aroon Down, indica una señal alcista. Cuando Aroon Down se encuentra por encima de Aroon Up, tendremos una señal bajista. Los indicadores Aroon también se mueven u oscilan entre los niveles de cero a 100.

A continuación describiremos cómo calcular el indicador técnico Aroon:

Aroon Up     = 100 * ((n-H)/n)

Aroon Down = 100 * ((n-L)/n)

donde:

  • Aroon Up - se expresa como porcentaje del número total de n-periodos y representa el número de periodos desde el último máximo de n-periodos.
  • Aroon Down - se expresa como porcentaje del número total de n-periodos y representa el número de periodos desde el último mínimo de n-periodos.
  • H - es el número de periodos durante un tiempo dado de n-periodos desde el último máximo del n-periodo.
  • L - es el número de periodos durante el tiempo dado de n-periodos desde el último mínimo del n-periodo.
  • n - es el periodo.


Estrategias con Aroon

Veamos dos estrategias sencillas para usar el indicador Aroon. Estas estrategias se implementarán con la ayuda de MQL5 para después probarlas en el simulador de estrategias, ver los resultados de cada estrategia y compararlos.

Usaremos dos estrategias básicas:

  • Aroon Crossover Strategy (estrategia cruzada)
  • Aroon Levels Strategy (estrategia de niveles)

Estrategia de cruce de Aroon:

Colocaremos una orden cuando se crucen las líneas superior e inferior del indicador Aroon. Por lo tanto, tendremos que abrir una orden de compra cuando veamos que Aroon Up (línea ascendente) cruza Aroon Down (línea descendente) hacia arriba y una orden de venta si Aroon Down cruza Aroon Up hacia arriba.

Línea ascendente > Línea descendente ==> compra

Línea descendente > Línea ascendente ==> venta

Estrategia de niveles de Aroon:

Abriremos una orden si la línea Aroon Down cruza los niveles 10 y 50 del indicador Aroon. Por lo tanto, necesitaremos colocar una orden de compra si la línea Aroon Down está por debajo del nivel 10 y colocar una orden de venta si está por encima del nivel 50 del indicador Aroon.

Línea descendente < 10 ==> compra

Downline > 50 ==> venta


Sistemas comercial con Aroon

En esta parte, aprenderemos a codificar las estrategias Aroon mencionadas en MQL5 para luego probarlas en el simulador y evaluar sus resultados. En primer lugar, necesitaremos codificar nuestro propio indicador Aroon para poder utilizarlo en nuestras estrategias comerciales como se muestra a continuación:

En el área global de MQL5, estableceremos las propiedades de los indicadores utilizando el preprocesador de propiedades.

//properties of the indicator
#property indicator_separate_window // the place of the indicator
#property indicator_buffers 2 // number of buffers
#property indicator_plots 2 // number of plots

//up line
#property indicator_type1  DRAW_LINE      // type of the up values to be drawn is a line
#property indicator_color1 clrGreen       // up line color
#property indicator_style1 STYLE_DASH     // up line style
#property indicator_width1 2              // up line width
#property indicator_label1 "Up"           // up line label

// down line
#property indicator_type2  DRAW_LINE      // type of the down values to be drawn is a line
#property indicator_color2 clrRed         // down line color
#property indicator_style2 STYLE_DASH     // down line style
#property indicator_width2 2              // down line width
#property indicator_label2 "Down"         // down line label

// drawing some levels to be used later 10 and 50
#property indicator_level1 10.0
#property indicator_level2 50.0
#property indicator_levelcolor clrSilver
#property indicator_levelstyle STYLE_DOT

Luego crearemos dos datos de entrada de tipo entero para el indicador: periodo y desplazamiento horizontal utilizando la palabra clave input.

//inputs
input int                      periodInp = 25; // Period
input int                      shiftInp  = 0;  // horizontal shift

Y crearemos dos arrays de tipo double para los valores up y down del indicador.

//buffers of the indicator
double                         upBuffer[];
double                         downBuffer[];

En OnInit(), al utilizar la función SetIndexBuffer para vincular búferes de indicador a arrays double, los parámetros serán los siguientes:

  • index - para especificar el índice del búfer, usaremos 0 para upBuffer y 1 para downBuffer.
  • buffer[] - usaremos los arrays upBuffer y downBuffer para especificar el array.
  • data_type - para especificar el tipo de datos que necesitamos almacenar (puede ser uno de ENUM_INDEXBUFFR_TYPE), usaremos INDICATOR_DATA tanto para up como para down.
   SetIndexBuffer(0, upBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, downBuffer, INDICATOR_DATA);

Estableceremos los valores de la propiedad correspondiente y las líneas indicadoras up y down correspondientes con la función PlotIndexSetInteger utilizando la variante de llamada que especifica el ID de la propiedad y los parámetros incluye:

  • plot_index es el valor entero del índice del estilo de visualización, será 0 para up y 1 para down.
  • prop_id:: - es el valor entero del identificador de la propiedad, puede ser uno de ENUM_PLOT_PROPERTY_INTEGER. Usaremos PLOT_SHIFT y PLOT_DRAW_BEGIN para up y down.
  • prop_value - es un valor entero, shiftInp y periodInp para up y down.
   PlotIndexSetInteger(0, PLOT_SHIFT, shiftInp);
   PlotIndexSetInteger(1, PLOT_SHIFT, shiftInp);
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, periodInp);
   PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, periodInp);

Configuración de la bandera AS_SERIES para los arrays up y down

   ArraySetAsSeries(upBuffer, true);
   ArraySetAsSeries(downBuffer, true);

Estableceremos el nombre de la cadena y los valores enteros del indicador después de declarar la variable de cadena indicatorName y asignar la función StringFormat para establecer el formato de lo que queremos ver en la ventana del indicador.

   string indicatorName = StringFormat("Aroon Indicator (%i,%i) - ", periodInp, shiftInp);
   IndicatorSetString(INDICATOR_SHORTNAME, indicatorName);
   IndicatorSetInteger(INDICATOR_DIGITS, 0);

Retornaremos INIT_SUCCEED como parte del evento OnInit().

return INIT_SUCCEEDED;

Evento OnCalculate,

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[])

En el cuerpo del evento, calcularemos el indicador, retornando 0 si no hay datos suficientes.

   if(rates_total < periodInp - 1)
      return (0);

Creación de una variable contador entera y cálculo de la misma como resultado de la resta de rate_total y prev_calculated.

int count = rates_total - prev_calculated;

Si prev_calculated es mayor que 0 (eso significa que tenemos nuevos datos), actualizaremos el contador añadiendo 1.

   if(prev_calculated > 0)
      count++;

Luego crearemos otra condición para actualizar el valor del contador

   if(count > (rates_total - periodInp + 1))
      count = (rates_total - periodInp + 1);

Y crearemos un ciclo for para calcular y actualizar los valores de los indicadores up y down después de calcular los valores máximo y mínimo.

   for(int i = count - 1; i >= 0; i--)
     {
      int highestVal   = iHighest(Symbol(), Period(), MODE_HIGH, periodInp, i);
      int lowestVal    = iLowest(Symbol(), Period(), MODE_LOW, periodInp, i);
      upBuffer[i]   = (periodInp - (highestVal - i)) * 100 / periodInp;
      downBuffer[i] = (periodInp - (lowestVal - i)) * 100 / periodInp;
     }

Retorno de rate_total como parte del evento OnCalculate

return (rates_total);

Por lo tanto, a continuación mostramos el código completo para crear nuestro indicador personalizado Aroon en un bloque de código.

//+------------------------------------------------------------------+
//|                                                        Aroon.mq5 |
//+------------------------------------------------------------------+
#property indicator_separate_window // the place of the indicator
#property indicator_buffers 2 // number of buffers
#property indicator_plots 2 // number of plots
#property indicator_type1  DRAW_LINE      // type of the up values to be drawn is a line
#property indicator_color1 clrGreen       // up line color
#property indicator_style1 STYLE_DASH     // up line style
#property indicator_width1 2              // up line width
#property indicator_label1 "Up"           // up line label
#property indicator_type2  DRAW_LINE      // type of the down values to be drawn is a line
#property indicator_color2 clrRed         // down line color
#property indicator_style2 STYLE_DASH     // down line style
#property indicator_width2 2              // down line width
#property indicator_label2 "Down"         // down line label
#property indicator_level1 10.0
#property indicator_level2 50.0
#property indicator_levelcolor clrSilver
#property indicator_levelstyle STYLE_DOT
input int periodInp = 25; // Period
input int shiftInp  = 0;  // horizontal shift
double    upBuffer[];
double    downBuffer[];
int OnInit()
  {
   SetIndexBuffer(0, upBuffer, INDICATOR_DATA);
   SetIndexBuffer(1, downBuffer, INDICATOR_DATA);
   PlotIndexSetInteger(0, PLOT_SHIFT, shiftInp);
   PlotIndexSetInteger(1, PLOT_SHIFT, shiftInp);
   PlotIndexSetInteger(0, PLOT_DRAW_BEGIN, periodInp);
   PlotIndexSetInteger(1, PLOT_DRAW_BEGIN, periodInp);
   ArraySetAsSeries(upBuffer, true);
   ArraySetAsSeries(downBuffer, true);
   string indicatorName = StringFormat("Aroon Indicator (%i,%i) - ", periodInp, shiftInp);
   IndicatorSetString(INDICATOR_SHORTNAME, indicatorName);
   IndicatorSetInteger(INDICATOR_DIGITS, 0);
   return INIT_SUCCEEDED;
  }
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[])
  {
   if(rates_total < periodInp - 1)
      return (0);
   int count = rates_total - prev_calculated;
   if(prev_calculated > 0)
      count++;
   if(count > (rates_total - periodInp + 1))
      count = (rates_total - periodInp + 1);
   for(int i = count - 1; i >= 0; i--)
     {
      int highestVal   = iHighest(Symbol(), Period(), MODE_HIGH, periodInp, i);
      int lowestVal    = iLowest(Symbol(), Period(), MODE_LOW, periodInp, i);
      upBuffer[i]   = (periodInp - (highestVal - i)) * 100 / periodInp;
      downBuffer[i] = (periodInp - (lowestVal - i)) * 100 / periodInp;
     }
   return (rates_total);
  }
//+------------------------------------------------------------------+

Tras compilar el código, veremos el aspecto de nuestro indicador personalizado cuando lo ejecutemos en el gráfico.

 Aroon ind

El indicador está listo y podemos crear nuestras estrategias comerciales. Así pues, comenzaremos con el cruce de las líneas Aroon y luego pasaremos a los niveles, pero antes crearemos un sencillo programa que pueda mostrar los valores up y down de Aroon. El siguiente método nos permitirá hacerlo:

Primero, en el área global, crearemos dos parámetros de entrada personalizados Period y Shift usando la palabra clave input.

input int         periodInp = 25; // Period
input int         shiftInp  = 0; // Shift

Ahora declararemos una variable entera para Aroon para asignarle más tarde el manejador del indicador.

int aroon;

En OnInit(), asignaremos la función iCustom para adjuntar o retornar el manejador del indicador personalizado Aroon creado al asesor. Los parámetros serán los siguientes:

  • Symbol - nombre del símbolo, usaremos _Symbol para retornar el actual.
  • period - periodo, usaremos _Period para retornar el actual.
  • name - nombre exacto del indicador personalizado con su ruta exacta en la carpeta Indicators.
  • A continuación, especificaremos la lista de parámetros de entrada del indicador personalizado. Solo utilizaremos los dos parámetros de entrada que hemos creado (Period y Shift).
aroon = iCustom(_Symbol,PERIOD_CURRENT,"Aroon",periodInp,shiftInp);

Entonces retornaremos (INIT_SUCCEED) cuando el asesor ha sido inicializado con éxito.

return(INIT_SUCCEEDED);

En OnDeinit imprimiremos "EA is removed" (el asesor ha sido eliminado) usando la palabra clave Print cuando ocurra el evento Deinit para desinicializar un programa MQL5 en ejecución.

void OnDeinit(const int reason)
  {
   Print("EA is removed");
  }

En el evento OnTick(), declararemos dos arrays double: upBuffer y downBuffer

double upBuffer[], downBuffer[];

Obtendremos los datos de los búferes creados del indicador Aroon mediante la función CopyBuffer con la variante de llamada según la primera posición y el número de elementos y parámetros requeridos:

  • indicator_manejador - manejador del indicador personalizado Aroon.
  • buffer_num - número del búfer de indicador.
  • start_pos - posición de inicio del conteo.
  • count - número de contadores a partir de start_pos.
  • buffer[] - array objetivo.
   CopyBuffer(aroon,0,0,3,upBuffer);
   CopyBuffer(aroon,1,0,3,downBuffer);

Usaremos ArraySetAsSeries para establecer la bandera AS_SERIES en la bandera especificada, que será verdadera para invertir el orden de indexación del array.

   ArraySetAsSeries(upBuffer,true);
   ArraySetAsSeries(downBuffer,true);

Declararemos dos variables double upValue y downValue para asignar los valores actuales de los indicadores Aroon a partir de los arrays usando la indexación [0].

   double upValue = upBuffer[0];
   double downValue = downBuffer[0];

Usaremos la función Comment para mostrar un comentario en un gráfico con los valores de indicador up y down

Comment("upValue: ",upValue,"\ndownValue: ",downValue);

A continuación mostraremos el código completo en un solo bloque:

//+------------------------------------------------------------------+
//|                                                AroonValuesEA.mq5 |
//+------------------------------------------------------------------+
input int         periodInp = 25; // Period
input int         shiftInp  = 0; // Shift
int aroon;
int OnInit()
  {
   aroon = iCustom(_Symbol,PERIOD_CURRENT,"Aroon",periodInp,shiftInp);
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   Print("EA is removed");
  }
void OnTick()
  {
   double upBuffer[], downBuffer[];
   CopyBuffer(aroon,0,0,3,upBuffer);
   CopyBuffer(aroon,1,0,3,downBuffer);
   ArraySetAsSeries(upBuffer,true);
   ArraySetAsSeries(downBuffer,true);
   double upValue = upBuffer[0];
   double downValue = downBuffer[0];
   Comment("upValue: ",upValue,"\ndownValue: ",downValue);
  }
//+------------------------------------------------------------------+

Tras compilar el código sin errores y ejecutar el asesor en el gráfico, podremos ver sus datos de salida como en el siguiente ejemplo:

AroonValues

Como podemos ver en el gráfico anterior, los valores up y down se indican con un comentario. El indicador personalizado se ejecutará en el gráfico para tener la seguridad de que el asesor retorne los mismos valores del indicador (96, 48).

Estrategia de cruce:

Ahora es el momento de aplicar las estrategias comerciales que hemos mencionado en el código. Empezaremos con la estrategia de cruce.

De manera global, utilizaremos el preprocesador #include para incorporar funciones comerciales en nuestro asesor para colocar órdenes automáticamente usando como base nuestra estrategia.

#include <trade/trade.mqh>

Así, crearemos cinco variables de entrada: period, horizontal shift, lotSize, slLvl, y tpLvl, y le asignaremos valores por defecto a cada una.

input int         periodInp = 25; // Period
input int         shiftInp  = 0; // Shift
input double      lotSize=1;
input double      slLvl=200;
input double      tpLvl=600;

Crearemos las siguientes variables:

  • La variable entera Aroon, que se utilizará más adelante para definir el indicador.
  • La variable entera barstotal se utilizará para limitar la apertura de órdenes en cada barra.
  • El objeto comercial CTrade, que se utilizará al ubicar órdenes.
int aroon;
int barsTotal;
CTrade trade;

En el evento OnInit(), definiremos la variable declarada barsTotal utilizando las funciones iBars, que retornan las barras disponibles de un símbolo y periodo en la historia.

barsTotal=iBars(_Symbol,PERIOD_CURRENT);

Vamos a definir una variable Aroon utilizando iCustom para incluir el indicador Aroon personalizado que hemos creado.

aroon = iCustom(_Symbol,PERIOD_CURRENT,"Aroon",periodInp,shiftInp);

En el evento OnDeinit() imprimiremos una notificación sobre la eliminación del asesor.

Print("EA is removed");

En el evento OnTick(), declararemos una variable entera bars para almacenar el número de barras de cada tick

int bars=iBars(_Symbol,PERIOD_CURRENT);

Y comprobaremos la igualdad entre barsTotal y bars

if(barsTotal != bars)

Luego actualizaremos barsTotal usando los búferes bars.

barsTotal=bars;

Después declararemos dos arrays double up y down, obtendremos los datos de los búferes de indicador, estableceremos la bandera AS_SERIES para el array seleccionado, declararemos y definiremos cuatro variables double para los valores anteriores y actuales up y down.

      double upBuffer[], downBuffer[];
      CopyBuffer(aroon,0,0,3,upBuffer);
      CopyBuffer(aroon,1,0,3,downBuffer);
      ArraySetAsSeries(upBuffer,true);
      ArraySetAsSeries(downBuffer,true);
      double prevUpValue = upBuffer[1];
      double prevDownValue = downBuffer[1];
      double upValue = upBuffer[0];
      double downValue = downBuffer[0];

A continuación, estableceremos las condiciones de la orden de compra: prevUpValue tendrá que ser menor que prevDownValue y, al mismo tiempo, upValue tendrá que ser mayor que downValue.

if(prevUpValue<prevDownValue && upValue>downValue)

Si se cumple esta condición, declararemos la variable double ask y su precio actual ask del símbolo actual, también declararemos y especificaremos slVal y tpVal y colocaremos posiciones de compra con el valor predefinido personalizado lotSize en el símbolo actual. En el precio de venta actual, el stop loss será el mismo que el predefinido para slVal y el take profit será el mismo que para tpVal.

         double ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
         double slVal=ask - slLvl*_Point;
         double tpVal=ask + tpLvl*_Point;
         trade.Buy(lotSize,_Symbol,ask,slVal,tpVal);

A continuación, estableceremos las condiciones de la orden de venta: prevUpValue tendrá que ser mayor que prevDownValue, y al mismo tiempo upValue tendrá que ser menor que downValue.

if(prevUpValue>prevDownValue && upValue<downValue)
Si se cumple esta condición, declararemos la variable double bid y su precio bid actual del símbolo actual, también declararemos y especificaremos slVal y tpVal y colocaremos posiciones de venta con un valor predefinido lotSize personalizado en el símbolo actual. Al precio de compra actual, el stop loss será el mismo que el predefinido para slVal, y el take profit será el mismo que para tpVal.
         double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
         double slVal=bid + slLvl*_Point;
         double tpVal=bid - tpLvl*_Point;
         trade.Sell(lotSize,_Symbol,bid,slVal,tpVal);

A continuación le mostramos el código completo de la estrategia de cruce Aroon en un solo bloque:

//+------------------------------------------------------------------+
//|                                             AroonCrossoverEA.mq5 |
//+------------------------------------------------------------------+
#include <trade/trade.mqh>
input int         periodInp = 25; // Period
input int         shiftInp  = 0; // Shift
input double      lotSize=1;
input double      slLvl=200;
input double      tpLvl=600;
int aroon;
int barsTotal;
CTrade trade;
int OnInit()
  {
   barsTotal=iBars(_Symbol,PERIOD_CURRENT);
   aroon = iCustom(_Symbol,PERIOD_CURRENT,"Aroon",periodInp,shiftInp);
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   Print("EA is removed");
  }
void OnTick()
  {
   int bars=iBars(_Symbol,PERIOD_CURRENT);
   if(barsTotal != bars)
     {
      barsTotal=bars;
      double upBuffer[], downBuffer[];
      CopyBuffer(aroon,0,0,3,upBuffer);
      CopyBuffer(aroon,1,0,3,downBuffer);
      ArraySetAsSeries(upBuffer,true);
      ArraySetAsSeries(downBuffer,true);
      double prevUpValue = upBuffer[1];
      double prevDownValue = downBuffer[1];
      double upValue = upBuffer[0];
      double downValue = downBuffer[0];
      if(prevUpValue<prevDownValue && upValue>downValue)
        {
         double ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
         double slVal=ask - slLvl*_Point;
         double tpVal=ask + tpLvl*_Point;
         trade.Buy(lotSize,_Symbol,ask,slVal,tpVal);
        }
      if(prevUpValue>prevDownValue && upValue<downValue)
        {
         double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
         double slVal=bid + slLvl*_Point;
         double tpVal=bid - tpLvl*_Point;
         trade.Sell(lotSize,_Symbol,bid,slVal,tpVal);
        }
     }
  }
//+------------------------------------------------------------------+

Tras compilar correctamente el código, podremos encontrar ejemplos de colocación de órdenes basados en la siguiente estrategia:

Ejemplo de orden de compra:

compra

Como podemos ver en el ejemplo anterior, tenemos una orden de compra después de que las líneas up y down se crucen.

Ejemplo de orden de venta:

venta

Como podemos ver en el ejemplo anterior, tenemos una orden de venta después de que la línea down cruce la línea up.

Estrategia de niveles:

En esta parte implementaremos la estrategia de niveles Aroon, que permitirá al asesor abrir una orden basada en el cruce de la línea down con los niveles 10 y 50 del propio indicador Aroon. A continuación veremos cómo podemos implementar esta estrategia en MQL5. El código resulta bastante similar al implementado para la estrategia de cruce, así que ofreceremos el código completo y resaltaremos las diferencias.

A continuación le mostramos el código completo para codificar la estrategia de niveles Aroon en un único bloque de código:

//+------------------------------------------------------------------+
//|                                                AroonLevelsEA.mq5 |
//+------------------------------------------------------------------+
#include <trade/trade.mqh>
input int         periodInp = 25; // Period
input int         shiftInp  = 0; // Shift
input double      lotSize=1;
input double      slLvl=200;
input double      tpLvl=600;
int aroon;
int barsTotal;
CTrade trade;
int OnInit()
  {
   barsTotal=iBars(_Symbol,PERIOD_CURRENT);
   aroon = iCustom(_Symbol,PERIOD_CURRENT,"Aroon",periodInp,shiftInp);
   return(INIT_SUCCEEDED);
  }
void OnDeinit(const int reason)
  {
   Print("EA is removed");
  }
void OnTick()
  {
   int bars=iBars(_Symbol,PERIOD_CURRENT);
   if(barsTotal != bars)
     {
      barsTotal=bars;
      double upBuffer[], downBuffer[];
      CopyBuffer(aroon,0,0,3,upBuffer);
      CopyBuffer(aroon,1,0,3,downBuffer);
      ArraySetAsSeries(upBuffer,true);
      ArraySetAsSeries(downBuffer,true);
      double prevDownValue = downBuffer[1];
      double downValue = downBuffer[0];
      if(prevDownValue> 10 && downValue<10)
        {
         double ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
         double slVal=ask - slLvl*_Point;
         double tpVal=ask + tpLvl*_Point;
         trade.Buy(lotSize,_Symbol,ask,slVal,tpVal);
        }
      if(prevDownValue < 50 && downValue>50)
        {
         double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
         double slVal=bid + slLvl*_Point;
         double tpVal=bid - tpLvl*_Point;
         trade.Sell(lotSize,_Symbol,bid,slVal,tpVal);
        }
     }
  }

Diferencias en el código:

Solo tenemos que definir los valores anterior y actual

      double prevDownValue = downBuffer[1];
      double downValue = downBuffer[0];

Condición de la estrategia: prevDownValue tendrá que ser mayor que el nivel 10 y al mismo tiempo el valor actual de downValue tendrá que ser menor que el nivel 10. Necesitaremos que el asesor coloque una orden de compra después de determinar ask, stop loss y take profit.

      if(prevDownValue> 10 && downValue<10)
        {
         double ask = SymbolInfoDouble(_Symbol,SYMBOL_ASK);
         double slVal=ask - slLvl*_Point;
         double tpVal=ask + tpLvl*_Point;
         trade.Buy(lotSize,_Symbol,ask,slVal,tpVal);
        }

Si prevDownValue es menor que el nivel 50 y al mismo tiempo el downValue actual es mayor que el nivel 50. Necesitaremos que el asesor coloque una orden de venta después de determinar el actual bid, stop loss y take profit.

      if(prevDownValue < 50 && downValue>50)
        {
         double bid = SymbolInfoDouble(_Symbol,SYMBOL_BID);
         double slVal=bid + slLvl*_Point;
         double tpVal=bid - tpLvl*_Point;
         trade.Sell(lotSize,_Symbol,bid,slVal,tpVal);
        }

Después de compilar este código sin errores, podemos encontrar que el asesor puede colocar órdenes como en los siguientes ejemplos:

Ejemplo de orden de compra:

compra

Ejemplo de orden de venta:

venta


Pruebas del sistema comercial Aroon

En esta parte, probaremos cada estrategia para ver sus resultados. Una vez más, insistiremos en que es posible que tenga que optimizar aún más estas estrategias para obtener los mejores resultados y determinar lo que funciona mejor para usted. 

Nos centraremos en las siguientes dimensiones clave para hacer comparaciones entre ellas:

  • Beneficio neto (Net Profit): se calcula restando la pérdida bruta del beneficio bruto. Cuanto mayor sea el valor, mejor.
  • Reducción relativa del balance (Balance DD relative) - pérdida máxima en la cuenta durante la negociación. Cuanto más bajo sea el valor, mejor.
  • Factor de beneficio (Profit factor) - relación entre el beneficio bruto y la pérdida bruta. Cuanto mayor sea el valor, mejor.
  • Esperanza matemática de ganancias (Expected payoff) -beneficio o pérdida media de una transacción. Cuanto mayor sea el valor, mejor.
  • Factor de recuperación (Recovery factor) -determina la capacidad de una estrategia probada para recuperarse de las pérdidas. Cuanto mayor sea el valor, mejor.
  • Ratio de Sharpe (Sharpe Ratio) - determina el riesgo y la estabilidad del sistema comercial probado comparando la rentabilidad con la rentabilidad sin riesgo. Cuanto mayor sea el valor, mejor.

También probaremos el mismo periodo para comprobar ambas estrategias. El periodo será de un año, del 1 de enero de 2023 al 31 de diciembre de 2023, probaremos dos marcos temporales: 15 minutos y una hora.

Estrategia de cruce:

Ahora veamos los resultados de la estrategia de cruce de Aroon en dos marcos temporales, 15 minutos y 1 hora, para ver cuál es mejor basándonos en los números anteriormente mencionados.

Probando la estrategia en un marco temporal de 15 minutos:

Los resultados se presentan en los siguientes gráficos:

resultados de la prueba 15m

resultados de la prueba3- 15m

resultados de la prueba2- 15m

A partir de los resultados anteriores, obtendremos las cifras siguientes:

  • Beneficio neto: 14791
  • Reducción relativa del balance: 6,78%
  • Factor de beneficio: 1,17
  • Esperanza matemática: 24,53
  • Factor de recuperación: 1,91
  • Ratio de Sharpe: 2,23

Probamos la estrategia en el marco temporal de una hora:

Los resultados se presentan en los siguientes gráficos:

resultados de la prueba 1hbr>

resultados de la prueba3- 1h

resultados de la prueba2- 1h

A partir de los resultados anteriores, obtendremos las cifras siguientes:

  • Beneficio neto: 6242,20
  • Reducción relativa del balance: 1,80%
  • Factor de beneficio: 1,39
  • Esperanza matemática: 53,81
  • Factor de recuperación: 2,43
  • Ratio de Sharpe: 3,23

Estrategia de niveles:

Aquí probaremos la estrategia de niveles Aroon en dos marcos temporales: 15 minutos y 1 hora, para comparar los mismos números para ambos marcos temporales.

Probando la estrategia en un marco temporal de 15 minutos:

Los resultados se presentan en los siguientes gráficos:

Resultados de la prueba 15m

resultados de la prueba3- 15m

resultados de la prueba2- 15m

A partir de los resultados anteriores, obtendremos las cifras siguientes:

  • Beneficio neto: 42417,30
  • Reducción relativa del balance: 12,91%
  • Factor de beneficio: 1,21
  • Esperanza matemática: 29,62
  • Factor de recuperación: 2,27
  • Ratio de Sharpe: 1,88

Probamos la estrategia en el marco temporal de una hora:

Los resultados se presentan en los siguientes gráficos:

Resultados de las pruebas 1h

resultados de las pruebas3- 1h

resultados de la prueba2- 1h

A partir de los resultados anteriores, obtendremos las cifras siguientes:

  • Beneficio neto: 16001,10
  • Reducción relativa del balance: 5,11%
  • Factor de beneficio: 1,30
  • Esperanza matemática: 41,89
  • Factor de recuperación: 2,68
  • Ratio de Sharpe: 2,61

La tabla siguiente reúne todos los resultados en un solo lugar para una mejor comparación:

valores

Basándonos en lo anterior, podemos encontrar los mejores valores correspondientes a la estrategia y el marco temporal probados:

  • Beneficio neto: El mejor indicador (42417,30 USD) se ha obtenido utilizando la estrategia de niveles al realizar la prueba en el marco temporal de 15 minutos.
  • Reducción relativa del balance: El mejor indicador (1,80%) se ha obtenido al utilizar la estrategia de cruce cuando se realizaron pruebas en el marco temporal de una hora.
  • Factor de beneficio: El mejor índice (1,39) se ha obtenido utilizando la estrategia de cruce al realizar las pruebas en el intervalo de una hora.
  • Esperanza matemática: El mejor valor (53,81) se ha obtenido utilizando la estrategia de cruce al realizar la prueba en el intervalo horario.
  • Factor de recuperación: El mejor valor (2,68) se ha obtenido utilizando la estrategia de niveles al realizar pruebas en el marco temporal de una hora.
  • Ratio de Sharpe: El mejor valor (3,23) se ha obtenido con la estrategia de cruce al realizar pruebas en el intervalo de una hora.

Utilizando las cifras anteriores, podemos elegir una estrategia adecuada partiendo de nuestros objetivos comerciales y de los valores que nos ayudarán a alcanzarlos.


Conclusión

La creación y comprobación de un sistema comercial es la tarea más importante para cualquier tráder que se tome en serio la negociación. En este artículo hemos tratado de ofrecer una idea sobre el indicador Aroon que podamos utilizar en cualquier sistema comercial, tanto por separado como en combinación con otras herramientas. Esta puede resultar útil para sus operaciones y darle una idea de cómo construir un buen sistema comercial.

Asimismo, hemos descrito detalladamente el indicador Aroon, así como su aplicación y su cálculo. También hemos visto dos estrategias sencillas que podrá utilizar:

  • La estrategia de cruce nos permite colocar automáticamente una posición de compra cuando la línea Aroon Up está por encima de la línea Aroon Down, o una posición de venta cuando la línea Aroon Down está por encima de la línea Aroon Up.
  • La estrategia de niveles nos permite colocar automáticamente una posición de compra si la línea Aroon Down está por debajo del nivel 10 del indicador, o una posición de venta si Aroon Down está por encima del nivel 50.

Además, hemos implementado estas estrategias en un código, creando un asesor para cada una de ellas. Después de crear nuestro indicador Aroon personalizado en MQL5 y escribir un programa simple que puede generar valores Aroon Up y Aroon Down en el gráfico, hemos ejecutado el indicador en el gráfico, lo hemos probado y hemos determinado los resultados importantes de la prueba de cada estrategia en dos marcos temporales: 15 minutos y 1 hora. Podremos utilizarlos en función de nuestros objetivos comerciales y del rendimiento de cada estrategia.

También debemos comprender que es posible que necesitemos más optimización y más esfuerzo para encontrar estrategias que nos permitan obtener mejores resultados. El objetivo principal de este artículo es compartir algunas ideas sobre distintos sistemas comerciales que nos pueden empujar a crear mejores sistemas comerciales.

Espero que el artículo le haya resultado útil. Si quiere aprender más sobre la construcción de sistemas comerciales basados en diferentes estrategias y diferentes indicadores técnicos, puedes leer mis artículos anteriores sobre los indicadores técnicos más populares entrando en la sección "Publicaciones" de mi perfil. Espero que también le resulten útiles.

Traducción del inglés realizada por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/en/articles/14006

Archivos adjuntos |
Aroon.mq5 (3.04 KB)
AroonValuesEA.mq5 (0.91 KB)
AroonLevelsEA.mq5 (1.63 KB)
Utilizando redes neuronales en MetaTrader Utilizando redes neuronales en MetaTrader
En el artículo se muestra la aplicación de las redes neuronales en los programas de MQL, usando la biblioteca de libre difusión FANN. Usando como ejemplo una estrategia que utiliza el indicador MACD se ha construido un experto que usa el filtrado con red neuronal de las operaciones. Dicho filtrado ha mejorado las características del sistema comercial.
Desarrollo de un sistema de repetición (Parte 47): Proyecto Chart Trade (VI) Desarrollo de un sistema de repetición (Parte 47): Proyecto Chart Trade (VI)
En este artículo finalizaremos el indicador Chart Trade, haciéndolo funcional hasta el punto de poder usarlo junto con algún Expert Advisor. Entonces, en este artículo finalizaremos el indicador Chart Trade, haciéndolo funcional hasta el punto de poder usarlo junto con algún Expert Advisor. Esto nos permitirá acceder y trabajar con el indicador, como si estuviera realmente vinculado al Expert Advisor. Pero lo haremos de una manera mucho más interesante que en el pasado.
Particularidades del trabajo con números del tipo double en MQL4 Particularidades del trabajo con números del tipo double en MQL4
En estos apuntes hemos reunido consejos para resolver los errores más frecuentes al trabajar con números del tipo double en los programas en MQL4.
Desarrollo de un sistema de repetición (Parte 46): Proyecto Chart Trade (V) Desarrollo de un sistema de repetición (Parte 46): Proyecto Chart Trade (V)
¿Cansado de perder tiempo buscando ese archivo que es necesario para que tu aplicación funcione? ¿Qué tal si incluimos todo en el ejecutable? Así nunca perderás tiempo buscando las cosas. Sé que muchos utilizan exactamente esa forma de distribuir y guardar las cosas. Pero existe una manera mucho más adecuada. Al menos en lo que respecta a la distribución de ejecutables y almacenamiento de los mismos. La forma que explicaré aquí, puede ser de gran ayuda. Ya que puedes usar el propio MetaTrader 5 como un gran ayudante, así como el MQL5. No es algo tan complejo ni difícil de entender.