Discusión sobre el artículo "Implementación de una estrategia de trading con Bandas de Bollinger en MQL5: Guía paso a paso"

 

Artículo publicado Implementación de una estrategia de trading con Bandas de Bollinger en MQL5: Guía paso a paso:

Una guía paso a paso para implementar un algoritmo de trading automatizado en MQL5 basado en la estrategia de trading de las Bandas de Bollinger. Un tutorial detallado basado en la creación de un Asesor Experto que puede ser útil para los traders.

Los traders pueden crear un Asesor Experto (EA) que utilice Bandas de Bollinger para ejecutar órdenes de compra y venta basadas en condiciones particulares del mercado siguiendo este tutorial paso a paso. Se cubrirán temas importantes, incluida la configuración del indicador de Bandas de Bollinger, el control de posiciones comerciales y el tratamiento de la ejecución de órdenes y la gestión de errores. Independientemente de su nivel de experiencia con el desarrollo o familiaridad con el trading algorítmico, este tutorial brindará a los traders una base sólida sobre la cual diseñar y mejorar sus métodos de trading. 

Este viaje cubrirá los siguientes temas:

  1. Definición de la estrategia de Bandas de Bollinger
  2. Descripción de la estrategia de Bandas de Bollinger
  3. Implementación paso a paso con MQL5
  4. Conclusión

From 2016 to 2019, the strategy executed 1425 trades, 857 closed with trades which is 20.28% more than the loss trades.

De 2016 a 2019, la estrategia ejecutó 1425 operaciones, 857 se cerraron con ganancias, lo que supone un 20,28% más que las operaciones con pérdidas.   

Autor: Kikkih25

 

Estamos en 2024 y su backtest se detiene en 2019.

Es porque no funciona después de 2019?

 
El EA tiene numerosos errores de compilación.
 

Aquí hay un código que al menos compila en MT5 :)

Archivos adjuntos:
 

Ese código tiene demasiados errores. He corregido los errores y estoy publicando el código actualizado aquí. De nada.

//+------------------------------------------------------------------+
//|BollingerBands.mq5
//|Copyright 2024, MetaQuotes Ltd. |
//| https://www.mql5.com
//+------------------------------------------------------------------+
#property copyright "Copyright 2024, MetaQuotes Ltd."
#property link      "https://www.mql5.com"
#property version   "1.00"

#include <Trade\Trade.mqh> // Incluir la biblioteca comercial
CTrade trade; // Crear una instancia de la clase CTrade 

// Parámetros de entrada para la estrategia de Bandas de Bollinger
input int BandPeriod = 30;
input double BandDeviation = 2.0;
input double LotSize = 0.2;
input int Slippage = 3;
input double StopLoss = 70;
input double TakeProfit = 140;

int Bb_Handle; // Mango para el indicador de Bandas de Bollinger 

//+------------------------------------------------------------------+
//| Función de inicialización experta|
//+------------------------------------------------------------------+
int OnInit()
{
   // Crear el manejador del indicador Bandas de Bollinger
   Bb_Handle = iBands(_Symbol, PERIOD_CURRENT, BandPeriod, 0, BandDeviation, PRICE_CLOSE);
   
   if(Bb_Handle == INVALID_HANDLE)
   {
      Print("Error creating Bollinger Bands indicator"); 
      return(INIT_FAILED);
   }
   return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Función de desinicialización experta|
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   // Liberar el manejador del indicador Bandas de Bollinger
   IndicatorRelease(Bb_Handle);
}

//+------------------------------------------------------------------+
//| Función tick experto|
//+------------------------------------------------------------------+
void OnTick()
{
   double upperBand[], lowerBand[], middleBand[];
   
   // Copiar los valores de las Bandas de Bollinger en arrays
   if(CopyBuffer(Bb_Handle, 0, 0, 1, upperBand) <= 0 ||
      CopyBuffer(Bb_Handle, 1, 0, 1, middleBand) <= 0 ||
      CopyBuffer(Bb_Handle, 2, 0, 1, lowerBand) <= 0)
   {
      Print("Error copying band values");
      return;
   }
   
   double upper = upperBand[0];
   double lower = lowerBand[0];
   double middle = middleBand[0];
   double price = SymbolInfoDouble(_Symbol, SYMBOL_LAST);
   double Ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double Bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   
   // Señal de compra: el precio está por debajo de la banda inferior y no hay posiciones abiertas 
   if(price < lower && !IsPositionOpen(_Symbol))
   {
      double sl, tp;
      CalculateSLTP(sl, tp, Ask, true);
      if(trade.Buy(LotSize, _Symbol, Ask, sl, tp, "Buy Order"))
         Print("Buy order opened at price: ", Ask);
      else
         Print("Error opening BUY order:", trade.ResultRetcode());
   }
   // Señal de venta: el precio está por encima de la banda superior y no hay posiciones abiertas
   else if(price > upper && !IsPositionOpen(_Symbol))
   {
      double sl, tp;
      CalculateSLTP(sl, tp, Bid, false);
      if(trade.Sell(LotSize, _Symbol, Bid, sl, tp, "Sell Order"))
         Print("Sell order opened at price:", Bid);
      else
         Print("Error opening SELL order:", trade.ResultRetcode());
   }
}

//+------------------------------------------------------------------+
//| Comprueba si hay una posición abierta para un símbolo.
//+------------------------------------------------------------------+
bool IsPositionOpen(string symbol)
{
   for(int i = 0; i < PositionsTotal(); i++)
   {
      if(PositionGetSymbol(i) == symbol)
         return true;
   }
   return false;
}

//+------------------------------------------------------------------+
//| Cerrar todas las posiciones de un símbolo|
//+------------------------------------------------------------------+
void CloseAllPositions(string symbol)
{
   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      if(PositionGetSymbol(i) == symbol)
      {
         ulong ticket = PositionGetTicket(i);
         if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY)
            trade.PositionClose(ticket, Slippage);
         else if(PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_SELL)
            trade.PositionClose(ticket, Slippage);
         // Esperar a que se procese el pedido antes de continuar
         Sleep(1000);
      }
   }
}

//+------------------------------------------------------------------+
//| Calcular los niveles de Stop Loss y Take Profit.
//+------------------------------------------------------------------+
void CalculateSLTP(double &sl, double &tp, double price, bool isBuy)
{
   if(isBuy)
   {
      sl = price - StopLoss * _Point;
      tp = price + TakeProfit * _Point;
   }
   else 
   {
      sl = price + StopLoss * _Point;
      tp = price - TakeProfit * _Point;
   }
}
 
El índice del búfer del copybuffer es incorrecto para la banda superior e intermedia; debería usar UPPER_BAND, BASE_LINE, LOWER_BAND para iBands.
 
El artículo es magnífico. Gracias al autor. Voy a probarlo en mi comercio con diferenciales planos.
 
Eso es exactamente lo que hago....
Estudia el código y aplícalo a tu estrategia específica para obtener resultados óptimos.