AK-47 Scalper EA: Tu Asesor Experto para MetaTrader 5

Mike 2023.06.12 03:06 17 0 0
Archivos adjuntos

¿Eres un trader que busca optimizar sus operaciones en MetaTrader 5? Entonces, déjame presentarte al AK-47 Scalper EA, un asesor experto diseñado para maximizar tus oportunidades de trading. En este artículo, te mostraré cómo configurar y utilizar este potente sistema de trading.

1. Parámetros de entrada

#define ExtBotName "AK-47 EA" // Nombre del Bot
#define  Version "1.00"

// Importar clase de entrada
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
#include <Trade\SymbolInfo.mqh>  
#include <Trade\AccountInfo.mqh>
#include <Trade\OrderInfo.mqh>

//--- Variables predefinidas para la legibilidad del código 
#define Ask    SymbolInfoDouble(_Symbol, SYMBOL_ASK)
#define Bid    SymbolInfoDouble(_Symbol, SYMBOL_BID)

//--- Parámetros de entrada
input string  EASettings         = "---------------------------------------------"; //-------- <Configuración EA> --------
input int      InpMagicNumber    = 124656;   //Número mágico
input string  MoneySettings      = "---------------------------------------------"; //-------- <Configuración de Dinero> --------
input bool     isVolume_Percent  = true;     //Permitir porcentaje de volumen
input double   InpRisk           = 3;        //Porcentaje de riesgo del saldo (%)
input string  TradingSettings    = "---------------------------------------------"; //-------- <Configuración de Trading> --------
input double   Inpuser_lot       = 0.01;     //Lotes
input double   InpSL_Pips        = 3.5      //Stoploss (en Pips)
input double   InpTP_Pips        = 7        //TP (en Pips) (0 = Sin TP)
input int      InpMax_slippage   = 3        //Máximo slippage permitido (en Pips)
input double   InpMax_spread     = 5        //Máximo spread permitido (en Puntos) (0 = flotante)
input string   TimeSettings      = "---------------------------------------------"; //-------- <Configuración de Tiempo de Trading> --------
input bool     InpTimeFilter     = true;     //Filtro de Tiempo de Trading
input int      InpStartHour      = 2;        //Hora de Inicio
input int      InpStartMinute    = 30       //Minuto de Inicio
input int      InpEndHour        = 21       //Hora de Fin
input int      InpEndMinute      = 0        //Minuto de Fin

2. Inicialización de variables locales

//--- Variables
int      Pips2Points;    // slippage  3 pips    3=points    30=points
double   Pips2Double;    // Stoploss 15 pips    0.015      0.0150
bool     isOrder = false;
int      slippage;
long     acSpread;
string   strComment = "";

CPositionInfo  m_position;                   // objeto de posición de trading
CTrade         m_trade;                      // objeto de trading
CSymbolInfo    m_symbol;                     // objeto de información del símbolo
CAccountInfo   m_account;                    // envoltorio de info de cuenta
COrderInfo     m_order;                      // objeto de órdenes pendientes

3. Código Principal

a/ Función de inicialización del experto

//+------------------------------------------------------------------+
//| Función de inicialización del experto                                   |
//+------------------------------------------------------------------+
int OnInit() {

   //Detección de 3 o 5 dígitos
   //Pip y punto
   if(_Digits % 2 == 1) {
      Pips2Double  = _Point*10;
      Pips2Points  = 10;
      slippage = 10* InpMax_slippage;
   }
   else {
      Pips2Double  = _Point;
      Pips2Points  =  1;
      slippage = InpMax_slippage;
   }
     
   if(!m_symbol.Name(Symbol())) // establece el nombre del símbolo
      return(INIT_FAILED);
      
   RefreshRates();
//---
   m_trade.SetExpertMagicNumber(InpMagicNumber);
   m_trade.SetMarginMode();
   m_trade.SetTypeFillingBySymbol(m_symbol.Name());
   m_trade.SetDeviationInPoints(slippage);
//---
   return(INIT_SUCCEEDED);
}

b/ Función de tick del experto

//+------------------------------------------------------------------+
//| Función de tick del experto                                             |
//+------------------------------------------------------------------+
void OnTick() {

   if(TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) == false) {
      Comment("LazyBot\nTrading no permitido.");
      return;
   }
     
   MqlDateTime structTime;
   TimeCurrent(structTime);
   structTime.sec = 0;
   
   //Establecer hora de inicio
   structTime.hour = InpStartHour;
   structTime.min = InpStartMinute;       
   datetime timeStart = StructToTime(structTime);
   
   //Establecer hora de fin
   structTime.hour = InpEndHour;
   structTime.min = InpEndMinute;
   datetime timeEnd = StructToTime(structTime);
   
   acSpread = SymbolInfoInteger(_Symbol, SYMBOL_SPREAD);
   
   
   strComment = "\n" + ExtBotName + " - v." + (string)Version;
   strComment += "\nHora del servidor = " + TimeToString(TimeCurrent(),TIME_DATE|TIME_SECONDS) + " - " + DayOfWeekDescription(structTime.day_of_week);
   strComment += "\nTiempo de Trading = [" + (string)InpStartHour + "h" + (string)InpStartMinute + " --> " +  (string)InpEndHour + "h" + (string)InpEndMinute + "]";
   
   strComment += "\nSpread actual = " + (string)acSpread + " Puntos";
   
   Comment(strComment);
   
   //Actualizar valores
   UpdateOrders();
   
   TrailingStop();
      
   //Condiciones para operar según la sesión
   if(InpTimeFilter) {
      if(TimeCurrent() >= timeStart && TimeCurrent() < timeEnd) {
         if(!isOrder) OpenOrder();
      }
   }
   else {
      if(!isOrder) OpenOrder();
   }
   
} //---Fin de la función

3.1 Calcular señal para enviar órdenes

//+------------------------------------------------------------------+
//| CALCULAR SEÑAL Y ENVIAR ORDEN                                  |
//+------------------------------------------------------------------+
void OpenOrder(){
   
   ENUM_ORDER_TYPE OrdType = ORDER_TYPE_SELL;//-1;
  
   double TP = 0;
   double SL = 0;
   string comment = ExtBotName;
   
   //Calcular Lotes
   double lot1 = CalculateVolume();
   
   if(OrdType == ORDER_TYPE_SELL) {
      double OpenPrice = Bid - NormalizeDouble(InpSL_Pips/2 * Pips2Double, _Digits);
      
      TP = OpenPrice - NormalizeDouble(InpTP_Pips * Pips2Double, _Digits);
      SL = Ask + NormalizeDouble(InpSL_Pips/2 * Pips2Double, _Digits);
         
      if(CheckSpreadAllow()                                             //Verificar Spread
         && CheckVolumeValue(lot1)                                      //Verificar volumen
         && CheckOrderForFREEZE_LEVEL(ORDER_TYPE_SELL_STOP, OpenPrice)  //Verificar Dist desde OpenPrice a Bid
         && CheckStopLoss(OpenPrice,  SL, TP)                           //Verificar Dist desde SL, TP a OpenPrice
         && CheckMoneyForTrade(m_symbol.Name(), lot1, ORDER_TYPE_SELL)) //Verificar Balance cuando la orden sea Hit
      {
         if(!m_trade.SellStop(lot1, OpenPrice, m_symbol.Name(), SL, TP, ORDER_TIME_GTC, 0, comment))
         Print(__FUNCTION__,"--> Error de OrderSend ", m_trade.ResultComment());
      }
   }
   else if(OrdType == ORDER_TYPE_BUY) {
      double OpenPrice = Ask + NormalizeDouble(InpSL_Pips/2 * Pips2Double, _Digits);
      SL = Bid - NormalizeDouble(InpSL_Pips/2 * Pips2Double, _Digits);
      
      if(CheckSpreadAllow()                                             //Verificar Spread
         && CheckVolumeValue(lot1)                                      //Verificar volumen
         && CheckOrderForFREEZE_LEVEL(ORDER_TYPE_BUY_STOP, OpenPrice)   //Verificar Dist desde OpenPrice a Bid
         && CheckStopLoss(OpenPrice,  SL, TP)                           //Verificar Dist desde SL, TP a OpenPrice         
         && CheckMoneyForTrade(m_symbol.Name(), lot1, ORDER_TYPE_BUY))  //Verificar Balance cuando la orden sea Hit
      {
         if(!m_trade.BuyStop(lot1, OpenPrice, m_symbol.Name(), SL, TP, ORDER_TIME_GTC, 0, comment))// usar "ORDER_TIME_GTC" cuando la fecha de expiración = 0
         Print(__FUNCTION__,"--> Error de OrderSend ", m_trade.ResultComment());
      }
   }
   
}

3.2 Calcular Volumen

//+------------------------------------------------------------------+
//| CALCULAR VOLUMEN                                                 |
//+------------------------------------------------------------------+
// Definimos la función para calcular el tamaño de la posición y devolver el lote a ordenar.
double CalculateVolume() {

   double LotSize = 0;

   if(isVolume_Percent == false) {
      LotSize = Inpuser_lot;
     }
   else {
      LotSize = (InpRisk) * m_account.FreeMargin();
      LotSize = LotSize /100000;
      double n = MathFloor(LotSize/Inpuser_lot);
      //Comment((string)n);
      LotSize = n * Inpuser_lot;
      
      if(LotSize < Inpuser_lot)
         LotSize = Inpuser_lot;

      if(LotSize > m_symbol.LotsMax()) LotSize = m_symbol.LotsMax();

      if(LotSize < m_symbol.LotsMin()) LotSize = m_symbol.LotsMin();
   }
     
//---
   return(LotSize);
}
3.3 El EA tiene la función "Trailing Stop",  SL cambiará cada vez que el precio cambie (hacia abajo)

//+------------------------------------------------------------------+
//| TRAILING STOP                                                    |
//+------------------------------------------------------------------+
void TrailingStop() {

   double SL_in_Pip = 0;

   for(int i = PositionsTotal() - 1; i >= 0; i--) {
      if(m_position.SelectByIndex(i)) {    // selecciona las órdenes por índice para acceder a sus propiedades        
         if((m_position.Magic() == InpMagicNumber) && (m_position.Symbol() == m_symbol.Name())) {
            // Para orden de compra
            if(m_position.PositionType() == POSITION_TYPE_BUY) {
               //-- Calcular SL cuando el precio cambia
               SL_in_Pip = NormalizeDouble(Bid - m_position.StopLoss(), _Digits) / Pips2Double;
               if(SL_in_Pip > InpSL_Pips) {
                  double newSL = NormalizeDouble(Bid - InpSL_Pips * Pips2Double, _Digits);
                  
                  if(!m_trade.PositionModify(m_position.Ticket(), newSL, m_position.TakeProfit())) {
                     Print(__FUNCTION__,"--> Error de OrderModify ", m_trade.ResultComment());
                   continue  
                }
           }
            }

            // Para orden de venta
            else if(m_position.PositionType() == POSITION_TYPE_SELL) {
               //-- Calcular SL cuando el precio cambia
               SL_in_Pip = NormalizeDouble(m_position.StopLoss() - Bid, _Digits) / Pips2Double;
           if(SL_in_Pip > InpSL_Pips){
                  double newSL = NormalizeDouble(Bid + (InpSL_Pips) * Pips2Double, _Digits);
                  if(!m_trade.PositionModify(m_position.Ticket(), newSL, m_position.TakeProfit())) {
                     Print(__FUNCTION__,"--> Error de OrderModify ", m_trade.ResultComment());
                     //continue;  
              }
           }
            }
      } 
    }
  }
   
   //--- Modificar orden pendiente  
   for(int i=OrdersTotal()-1; i>=0; i--) {// devuelve el número de órdenes actuales
      if(m_order.SelectByIndex(i)) {      // selecciona la orden pendiente por índice para acceder a sus propiedades
         if(m_order.Symbol() == m_symbol.Name() && m_order.Magic()==InpMagicNumber) {
            if(m_order.OrderType() == ORDER_TYPE_BUY_STOP) {
               SL_in_Pip = NormalizeDouble(Bid - m_order.StopLoss(), _Digits) / Pips2Double;
                  
               if(SL_in_Pip < InpSL_Pips/2) {
                  double newOP = NormalizeDouble(Bid + (InpSL_Pips/2) * Pips2Double, _Digits);
                  double newTP =  NormalizeDouble(newOP + InpTP_Pips * Pips2Double, _Digits);
                  double newSL = NormalizeDouble(Bid - (InpSL_Pips/2) * Pips2Double, _Digits);
                  
                  if(!m_trade.OrderModify(m_order.Ticket(), newOP, newSL, newTP, ORDER_TIME_GTC,0)) {
                     Print(__FUNCTION__,"--> Modificar orden pendiente error!", m_trade.ResultComment());
                     continue  
                  }
              }
            }
      } 
      else if(m_order.OrderType() == ORDER_TYPE_SELL_STOP) {
               SL_in_Pip = NormalizeDouble(m_order.StopLoss() - Ask, _Digits) / Pips2Double;
           
               if(SL_in_Pip < InpSL_Pips/2){
                  double newOP = NormalizeDouble(Ask - (InpSL_Pips/2) * Pips2Double, _Digits);
                  double newTP =  NormalizeDouble(newOP - InpTP_Pips * Pips2Double, _Digits);
                  double newSL = NormalizeDouble(Ask + (InpSL_Pips/2) * Pips2Double, _Digits);
                  
                  if(!m_trade.OrderModify(m_order.Ticket(), newOP, newSL, newTP, ORDER_TIME_GTC,0)) {
                     Print(__FUNCTION__,"--> Modificar orden pendiente error!", m_trade.ResultComment());
                     //continue  
                  }
              }
                  }
      } 
    }
  }
   
}




Lista
Comentarios 0