English Русский 中文 Español Deutsch 日本語
preview
Auto-otimização de take-profits e parâmetros do indicador usando SMA e EMA

Auto-otimização de take-profits e parâmetros do indicador usando SMA e EMA

MetaTrader 5Exemplos |
463 4
Javier Santiago Gaston De Iriarte Cabrera
Javier Santiago Gaston De Iriarte Cabrera

Introdução

No mundo em constante mudança da negociação algorítmica, a inovação é fundamental para se manter à frente. Hoje, temos o prazer de apresentar um EA avançado que combina aprendizado de máquina com a tradicional análise técnica para operar no mercado de câmbio. O EA utiliza o modelo ONNX e indicadores técnicos cuidadosamente otimizados para tomar decisões de negociação nesse mercado.

A abordagem do EA é multifacetada, utilizando previsão de preços com o modelo de aprendizado de máquina, acompanhamento de tendência e otimização adaptativa de parâmetros. Embora possa ser adaptado para outros ativos, ele foi desenvolvido principalmente para operar ações da #AAPL. Com recursos como definição dinâmica do tamanho do lote, trailing stops e ajuste automático às condições de mercado, este EA representa uma combinação de tecnologias de ponta com princípios consagrados de negociação.

Indicadores utilizados:

  1. Média Móvel Simples (SMA): O EA usa uma média móvel simples com período otimizado de forma adaptativa. A SMA ajuda a identificar a direção geral da tendência e é usada em conjunto com o preço e outros indicadores para gerar sinais de entrada.
  2. Média Móvel Exponencial (EMA): Também utilizada com período dinamicamente otimizado. A EMA reage mais rapidamente às últimas mudanças de preço do que a SMA, oferecendo uma perspectiva diferente sobre a direção da tendência.
  3. Média de Amplitude de Variação (Average True Range, ATR): Embora o indicador não seja calculado diretamente no código, o EA utiliza cálculos baseados no ATR para definir os níveis de stop-loss e take-profit. Isso permite ajustar o tamanho da posição e gerenciar riscos de acordo com a volatilidade.
  4. Modelo de aprendizado de máquina: O EA utiliza o modelo ONNX (Open Neural Network Exchange) para prever preços. Esse modelo leva em consideração uma série de dados de preços recentes e tenta antecipar o próximo movimento, adicionando um elemento preditivo à estratégia de negociação.

Esses indicadores são combinados de maneira complexa, e seus parâmetros são dinamicamente otimizados conforme as condições atuais do mercado. O EA também inclui recursos como trailing stops e cálculo de expectativa matemática para gerenciar eficazmente as posições abertas.

A combinação desses indicadores com o aprendizado de máquina permite que o EA se adapte às condições variáveis do mercado e identifique, potencialmente, oportunidades de negociação em diferentes cenários.


Visão geral do código

1. Configuração inicial e arquivos incluídos:

O código começa com informações de direitos autorais e inclui as bibliotecas necessárias, como Trade.mqh.

#include <Trade\Trade.mqh>

2. Variáveis globais e parâmetros:

  • São definidos os parâmetros do modelo ONNX, incluindo o tamanho da amostra e os identificadores.
  • São declarados os parâmetros de entrada para os indicadores (SMA, EMA, ATR) e operações de negociação.
  • São definidos enumerações e valores constantes para movimentação de preços e números mágicos.

#resource "/Files/model.EURUSD.D1.1_1_2024.onnx" as uchar ExtModel[];
input group "----- Indicators Parameters -----"
int SMA_Period = 20;
int EMA_Period = 50;

input double StopLossATR = 1.5;
input double TakeProfitATR = 3.0;
input int OptimizationDays = 1;        // Hours between optimizations
input int LookbackPeriod = 7;         // Hours loockback periods
input int MinSMAPeriod = 5;            // Period min para SMA
input int MaxSMAPeriod = 50;           // Periodo max para SMA
input int MinEMAPeriod = 5;            // Periodo min para EMA
input int MaxEMAPeriod = 50;           // Periodo max para EMA
#define MAGIC_SE 12321
datetime lastOptimizationTime = 0;
double optimizedTakeProfit = 0.0;//InpTakeProfit;
double optimizedStopLoss = 0.0;//InpStopLoss;
double InpTakeProfit1 ;
double InpStopLoss1;

3. Função de inicialização (OnInit):

  • Configura o modelo ONNX a partir do buffer.
  • Inicializa os indicadores técnicos (SMA, EMA).
  • Chama funções para otimização dos indicadores e parâmetros de negociação.

int OnInit()
  {
//--- create a model from static buffer
   ExtHandle = OnnxCreateFromBuffer(ExtModel, ONNX_DEFAULT);
   if(ExtHandle == INVALID_HANDLE)
     {
      Print("OnnxCreateFromBuffer error ", GetLastError());
      return(INIT_FAILED);
     }

//--- set input and output shapes
   const long input_shape[] = {1, SAMPLE_SIZE, 1};
   if(!OnnxSetInputShape(ExtHandle, ONNX_DEFAULT, input_shape))
     {
      Print("OnnxSetInputShape error ", GetLastError());
      return(INIT_FAILED);
     }
   const long output_shape[] = {1, 1};
   if(!OnnxSetOutputShape(ExtHandle, 0, output_shape))
     {
      Print("OnnxSetOutputShape error ", GetLastError());
      return(INIT_FAILED);
     }

   SMAHandle = iMA(_Symbol, _Period, SMA_Period, 0, MODE_SMA, PRICE_CLOSE); // Ensure correct period
   if(SMAHandle == INVALID_HANDLE)
     {
      Print("Error initializing SMA indicator: ", GetLastError());
      return INIT_FAILED;
     }
   EMAHandle = iMA(_Symbol, _Period, EMA_Period, 0, MODE_EMA, PRICE_CLOSE); // Ensure correct index
   if(EMAHandle == INVALID_HANDLE)
     {
      Print("Error initializing EMA indicator: ", GetLastError());
      return INIT_FAILED;
     }
   trade.SetDeviationInPoints(Slippage);

   trade.SetExpertMagicNumber(MAGIC_SE);
   OptimizeIndicators();
   OptimizeParameters();
   return(INIT_SUCCEEDED);
  }

4. Função de finalização (OnDeinit):

Libera os identificadores do modelo ONNX e dos indicadores.

//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
   if(ExtHandle != INVALID_HANDLE)
     {
      OnnxRelease(ExtHandle);
      ExtHandle = INVALID_HANDLE;
     }

   IndicatorRelease(SMAHandle);
   IndicatorRelease(EMAHandle);
  }

5. Lógica principal de negociação (OnTick):

  • Verifica se o mercado está fechado.
  • Otimiza periodicamente os indicadores e os parâmetros de negociação.
  • Atualiza a lógica de trailing stop.
  • Prevê o movimento dos preços utilizando o modelo ONNX.
  • Verifica as condições de abertura/fechamento de posições com base nas previsões e nos indicadores.

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {

   if(IsMarketClosed())  // Verificar si el mercado está cerrado
     {
      return; // Si el mercado está cerrado, no hacer nada
     }

   static datetime lastOptimizationTime2 = 0;

   if(TimeCurrent() - lastOptimizationTime2 >= OptimizationDays * PeriodSeconds(PERIOD_H1))
     {
      OptimizeIndicators();
      lastOptimizationTime2 = TimeCurrent();

      // Actualizar los indicadores con los nuevos períodos
      IndicatorRelease(SMAHandle);
      IndicatorRelease(EMAHandle);
      SMAHandle = iMA(_Symbol, _Period, SMA_Period, 0, MODE_SMA, PRICE_CLOSE);
      EMAHandle = iMA(_Symbol, _Period, EMA_Period, 0, MODE_EMA, PRICE_CLOSE);
     }

//--- Optimización cada 2 días
   if(TimeCurrent() - lastOptimizationTime >= PeriodSeconds(PERIOD_H1) * HoursAnalyze)
     {
      OptimizeParameters();
      lastOptimizationTime = TimeCurrent();
     }

//---

   if(NewBarTS()==true)//gather statistics and launch trailing stop
     {
      double open=iOpen(_Symbol,TFTS,1);
      CalcLvl(up,(int)MathRound((iHigh(_Symbol,TFTS,1)-open)/_Point));
      CalcLvl(dn,(int)MathRound((open-iLow(_Symbol,TFTS,1))/_Point));
      buy_sl=CalcSL(dn);
      buy_tp=CalcTP(up);
      sell_sl=CalcSL(up);
      sell_tp=CalcTP(dn);

      if(TypeTS==Simple)//simple trailing stop
         SimpleTS();

      if(TypeTS==MoralExp)//Moral expectation
         METS();
      if(TypeTS==None)//None TS
         return;
     }

   double bid=SymbolInfoDouble(_Symbol,SYMBOL_BID);

   if(bid==SLNeutral || bid<=SLBuy || (SLSell>0 && bid>=SLSell))
     {
      for(int i=PositionsTotal()-1; i>=0; i--)
        {
         ulong ticket=PositionGetTicket(i);
         if(PositionSelectByTicket(ticket)==true)
            trade.PositionClose(ticket);
        }
     }
//---
//--- check new day
   if(TimeCurrent() >= ExtNextDay)
     {
      GetMinMax();
      ExtNextDay = TimeCurrent();
      ExtNextDay -= ExtNextDay % PeriodSeconds(PERIOD_D1);
      ExtNextDay += PeriodSeconds(PERIOD_D1);
     }

//--- check new bar
   if(TimeCurrent() < ExtNextBar)
      return;
   ExtNextBar = TimeCurrent();
   ExtNextBar -= ExtNextBar % PeriodSeconds();
   ExtNextBar += PeriodSeconds();

//--- check min and max
   float close = (float)iClose(_Symbol, _Period, 0);
   if(ExtMin > close)
      ExtMin = close;
   if(ExtMax < close)
      ExtMax = close;


   double sma[], ema[];//, willr[];
   CopyBuffer(SMAHandle, 0, 0, 1, sma);
   CopyBuffer(EMAHandle, 0, 0, 1, ema);
//CopyBuffer(WillRHandle, 0, 0, 1, willr);

//--- predict next price
   PredictPrice();

//--- check trading according to prediction and indicators
   if(ExtPredictedClass >= 0)
     {
      if(PositionSelect(_Symbol))
         CheckForClose(sma[0], ema[0]);//, willr[0]);
      else
         CheckForOpen(sma[0], ema[0]);//, willr[0]);
     }
  }

6. Funções de negociação:

  • CheckForOpen – determina se uma posição de compra ou venda deve ser aberta com base nas previsões e nos sinais dos indicadores.
  • CheckForClose – verifica se as posições atuais devem ser fechadas com base nas previsões.

//+------------------------------------------------------------------+
//| Check for open position conditions                               |
//+------------------------------------------------------------------+
void CheckForOpen(double sma, double ema)//, double willr)
  {
   MqlRates rates[];
   ArraySetAsSeries(rates,true);
   int copied = CopyRates(_Symbol,0,0,1,rates);
   if(copied <= 0)
     {
      Print("Error copying rates: ", GetLastError());
      return;
     }
   double Close[1];
   Close[0]=rates[0].close;
   double close = Close[0];

   ENUM_ORDER_TYPE signal = WRONG_VALUE;
   Print("ExtPredictedClass ",ExtPredictedClass);

//--- check signals
   if(ExtPredictedClass == 2)//PRICE_DOWN)
     {
      Print("ExtPredictedClass Sell ",ExtPredictedClass);
      Print("close ",close, " sma ",sma, " ema ", ema);//, " willr ", willr);
      // Venta
      if((close < sma && close < ema))// || willr > -20)
        {
         signal = ORDER_TYPE_SELL;
         Print("Order Sell detected");
        }
     }
   else
      if(ExtPredictedClass == 0)//PRICE_UP)
        {
         Print("ExtPredictedClass Buy ",ExtPredictedClass);
         Print("close ",close, " sma ",sma, " ema ", ema);//, " willr ", willr);
         // Compra
         if((close > sma && close > ema))// || willr < -80)
           {
            signal = ORDER_TYPE_BUY;
            Print("Order Buy detected");
           }
        }

//--- open position if possible according to signal
   if(signal != WRONG_VALUE && TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
     {
      Print("Proceding open order");
      double price, sl=0, tp=0;
      double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
      double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);

      MqlTradeRequest request = {};
      MqlTradeResult result = {};

      request.action = TRADE_ACTION_DEAL;
      request.symbol = _Symbol;
      request.deviation = Slippage;
      request.magic = MAGIC_SE;
      request.type_filling = ORDER_FILLING_FOK;
      //request.comment = "AKWr";

      double lotaje;
      if(signal == ORDER_TYPE_SELL)
        {
         price = bid;
         Print("Price: ",price);
         if(inp_lot_type == LOT_TYPE_FIX)
            lotaje=inp_lot_fix ;
         else
            lotaje=get_lot(price);
         if(!CheckVolumeValue(lotaje))
            return;
         if(!InpUseStops && ATR)
           {
            sl = NormalizeDouble(bid + StopLossATR * ATRValue, _Digits);
            tp = NormalizeDouble(ask - TakeProfitATR * ATRValue, _Digits);
            if(!CheckMoneyForTrade(_Symbol, lotaje,ORDER_TYPE_SELL))
              {
               Print("No hay suficiente margen para abrir la posición");
               return;
              }
            request.type = ORDER_TYPE_SELL;
            request.price = SymbolInfoDouble(_Symbol, SYMBOL_BID);
            request.volume = lotaje;
            request.sl = sl;
            request.tp = tp;
            request.comment = "SEW Opened sell order";
           }
         if(!InpUseStops && ATR)
           {
            sl = 0;
            tp = 0;
           }
         else
           {
            InpTakeProfit1 =optimizedTakeProfit;
            InpStopLoss1= optimizedStopLoss;
            sl = NormalizeDouble(bid + InpStopLoss1*_Point, _Digits);
            tp = NormalizeDouble(ask - InpTakeProfit1*_Point, _Digits);

           }
        }
      else
        {
         price = ask;
         Print("Price: ",price);
         if(inp_lot_type == LOT_TYPE_FIX)
            lotaje=inp_lot_fix ;
         else
            lotaje=get_lot(price);
         if(!CheckVolumeValue(lotaje))
            return;
         if(!InpUseStops)
           {
            sl = NormalizeDouble(ask - StopLossATR * ATRValue, _Digits);
            tp = NormalizeDouble(bid + TakeProfitATR * ATRValue, _Digits);
            if(!CheckMoneyForTrade(_Symbol, lotaje,ORDER_TYPE_BUY))
              {
               Print("No hay suficiente margen para abrir la posición");
               return;
              }
            request.type = ORDER_TYPE_BUY;
            request.price = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
            request.volume = lotaje;
            request.sl = sl;
            request.tp = tp;
            request.comment = "SEW Opened buy order";
           }
         if(!InpUseStops && ATR)
           {
            sl = 0;
            tp = 0;
           }
         else
           {
            InpTakeProfit1 =optimizedTakeProfit;
            InpStopLoss1= optimizedStopLoss;
            sl = NormalizeDouble(ask - InpStopLoss1*_Point, _Digits);
            tp = NormalizeDouble(bid + InpTakeProfit1*_Point, _Digits);
           }
        }
      Print("No InpUseStops used");

      //ExtTrade.PositionOpen(_Symbol, signal, lotaje, price, sl, tp);

      if(!CheckMoneyForTrade(_Symbol, lotaje, (ENUM_ORDER_TYPE)signal))
        {
         Print("No hay suficiente margen para abrir la posición");
         return;
        }
      Print("Volume ", lotaje);
      request.type = signal;
      request.price = price;//SymbolInfoDouble(_Symbol, SYMBOL_ASK);
      request.volume = lotaje;
      request.sl = sl;
      request.tp = tp;
      request.comment = "SEW";
      if(!OrderSend(request, result))
        {
         Print("Error opening the order: ", GetLastError());
         return;
        }
     }
  }
//+------------------------------------------------------------------+
//| Check for close position conditions                              |
//+------------------------------------------------------------------+
void CheckForClose(double sma, double ema)//, double willr)
  {
   if(InpUseStops)
      return;

   bool bsignal = false;

//--- position already selected before
   long type = PositionGetInteger(POSITION_TYPE);

//--- check signals
   if(type == POSITION_TYPE_BUY && ExtPredictedClass == 2)//PRICE_DOWN)
      bsignal = true;
   if(type == POSITION_TYPE_SELL && ExtPredictedClass == 0)//PRICE_UP)
      bsignal = true;

//--- close position if possible
   if(bsignal && TerminalInfoInteger(TERMINAL_TRADE_ALLOWED))
     {
      ExtTrade.PositionClose(_Symbol);
      CheckForOpen(sma, ema);//, willr);
     }
  }

7. Previsão de preços (PredictPrice):

Utiliza o modelo ONNX para prever o movimento futuro do preço.

//+------------------------------------------------------------------+
//| Predict next price                                               |
//+------------------------------------------------------------------+
void PredictPrice(void)
  {
   static vectorf output_data(1);
   static vectorf x_norm(SAMPLE_SIZE);

   if(ExtMin >= ExtMax)
     {
      Print("ExtMin >= ExtMax");
      ExtPredictedClass = -1;
      return;
     }

   if(!x_norm.CopyRates(_Symbol, _Period, COPY_RATES_CLOSE, 1, SAMPLE_SIZE))
     {
      Print("CopyRates ", x_norm.Size());
      ExtPredictedClass = -1;
      return;
     }
   float last_close = x_norm[SAMPLE_SIZE - 1];
   x_norm -= ExtMin;
   x_norm /= (ExtMax - ExtMin);

   if(!OnnxRun(ExtHandle, ONNX_NO_CONVERSION, x_norm, output_data))
     {
      Print("OnnxRun");
      ExtPredictedClass = -1;
      return;
     }

   float predicted = output_data[0] * (ExtMax - ExtMin) + ExtMin;
   float delta = last_close - predicted;
   if(fabs(delta) <= 0.00001)
      ExtPredictedClass = PRICE_SAME;
   else
      if(delta < 0)
         ExtPredictedClass = PRICE_UP;
      else
         ExtPredictedClass = PRICE_DOWN;

// Debugging output
   Print("Predicted price: ", predicted, " Delta: ", delta, " Predicted Class: ", ExtPredictedClass);
  }

8. Funções de trailing stop:

Várias funções (AllTS, METS, SimpleTS) implementam diferentes estratégias de trailing stop.

Mais detalhes podem ser encontrados neste artigo"Trailing Stop no Trading"

9. Funções de otimização:

  • OptimizeParameters – testa diferentes valores de take-profit e stop-loss para encontrar os melhores ajustes.
  • OptimizeIndicators – encontra os melhores períodos para os indicadores SMA e EMA.

void OptimizeParameters()
  {
   double bestTakeProfit = InpTakeProfit1;
   double bestStopLoss = InpStopLoss1;
   double bestPerformance = -DBL_MAX;

   for(int tp = 65; tp <= 500; tp += 5) // rango de TakeProfit
     {
      for(int sl = 65; sl <= 500; sl += 5) // rango de StopLoss
        {
         double performance = TestStrategy(tp, sl);
         if(performance > bestPerformance)
           {
            bestPerformance = performance;
            bestTakeProfit = tp;
            bestStopLoss = sl;
            //Print("Best Take Profit",bestTakeProfit);
            //Print("Best Stop Loss",bestStopLoss);
           }
        }
     }

   optimizedTakeProfit = bestTakeProfit;
   optimizedStopLoss = bestStopLoss;

   Print("Optimized TakeProfit: ", optimizedTakeProfit);
   Print("Optimized StopLoss: ", optimizedStopLoss);
  }
void OptimizeIndicators()
  {
   datetime startTime = TimeCurrent() - LookbackPeriod * PeriodSeconds(PERIOD_H1);
   datetime endTime = TimeCurrent();

   int bestSMAPeriod = SMA_Period;
   int bestEMAPeriod = EMA_Period;
   double bestPerformance = -DBL_MAX;

   for(int smaPeriod = MinSMAPeriod; smaPeriod <= MaxSMAPeriod; smaPeriod++)
     {
      for(int emaPeriod = MinEMAPeriod; emaPeriod <= MaxEMAPeriod; emaPeriod++)
        {
         double performance = TestIndicatorPerformance(smaPeriod, emaPeriod, startTime, endTime);

         if(performance > bestPerformance)
           {
            bestPerformance = performance;
            bestSMAPeriod = smaPeriod;
            bestEMAPeriod = emaPeriod;
           }
        }
     }

   SMA_Period = bestSMAPeriod;
   EMA_Period = bestEMAPeriod;

   Print("Optimized SMA Period: ", SMA_Period);
   Print("Optimized EMA Period: ", EMA_Period);
  }

10. Funções auxiliares e gerenciamento de capital:

Funções para cálculo do tamanho do lote, verificação de volume, verificação de fechamento do mercado, incluindo funções para checar se há capital suficiente para operar e normalizar tamanhos de lote, entre outras.

bool IsMarketClosed()
  {
   datetime currentTime = TimeCurrent();
   MqlDateTime tm;
   TimeToStruct(currentTime, tm);

   int dayOfWeek = tm.day_of_week;
   int hour = tm.hour;

// Verifica si es fin de semana
   if(dayOfWeek <= Sunday || dayOfWeek >= Saturday)
     {
      return true;
     }

// Verifica si está fuera del horario habitual de mercado (ejemplo: 21:00 a 21:59 UTC)
   if(hour >= after || hour < before)  // Ajusta estos valores según el horario del mercado
     {
      return true;
     }

   return false;
  }


//+------------------------------------------------------------------+
//| Check the correctness of the order volume                        |
//+------------------------------------------------------------------+
bool CheckVolumeValue(double volume)//,string &description)
  {
//--- minimal allowed volume for trade operations
   double min_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MIN);
   if(volume<min_volume)
     {
      //description=StringFormat("Volume is less than the minimal allowed SYMBOL_VOLUME_MIN=%.2f",min_volume);
      return(false);
     }

//--- maximal allowed volume of trade operations
   double max_volume=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_MAX);
   if(volume>max_volume)
     {
      //description=StringFormat("Volume is greater than the maximal allowed SYMBOL_VOLUME_MAX=%.2f",max_volume);
      return(false);
     }

//--- get minimal step of volume changing
   double volume_step=SymbolInfoDouble(Symbol(),SYMBOL_VOLUME_STEP);

   int ratio=(int)MathRound(volume/volume_step);
   if(MathAbs(ratio*volume_step-volume)>0.0000001)
     {
      //description=StringFormat("Volume is not a multiple of the minimal step SYMBOL_VOLUME_STEP=%.2f, the closest correct volume is %.2f",
      //volume_step,ratio*volume_step);
      return(false);
     }
//description="Correct volume value";
   return(true);
  }
//+------------------------------------------------------------------+
bool CheckMoneyForTrade(string symb,double lots,ENUM_ORDER_TYPE type)
  {
//--- Getting the opening price
   MqlTick mqltick;
   SymbolInfoTick(symb,mqltick);
   double price=mqltick.ask;
   if(type==ORDER_TYPE_SELL)
      price=mqltick.bid;
//--- values of the required and free margin
   double margin,free_margin=AccountInfoDouble(ACCOUNT_MARGIN_FREE);
//--- call of the checking function
   if(!OrderCalcMargin(type,symb,lots,price,margin))
     {
      //--- something went wrong, report and return false
      Print("Error in ",__FUNCTION__," code=",GetLastError());
      return(false);
     }
//--- if there are insufficient funds to perform the operation
   if(margin>free_margin)
     {
      //--- report the error and return false
      Print("Not enough money for ",EnumToString(type)," ",lots," ",symb," Error code=",GetLastError());
      return(false);
     }
//--- checking successful
   return(true);
  }
double get_lot(double price)
  {
   if(inp_lot_type==LOT_TYPE_FIX)
      return(normalize_lot(inp_lot_fix));
   double one_lot_margin;
   if(!OrderCalcMargin(ORDER_TYPE_BUY,_Symbol,1.0,price,one_lot_margin))
      return(inp_lot_fix);
   return(normalize_lot((AccountInfoDouble(ACCOUNT_BALANCE)*(inp_lot_risk/100))/ one_lot_margin));
  }
//<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<
double normalize_lot(double lt)
  {
   double lot_step = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_STEP);
   lt = MathFloor(lt / lot_step) * lot_step;
   double lot_minimum = SymbolInfoDouble(_Symbol,SYMBOL_VOLUME_MIN);
   lt = MathMax(lt, lot_minimum);
   return(lt);
  }

Funções principais:

  1. Utiliza aprendizado de máquina (modelo ONNX) para prever os preços.
  2. Combina indicadores técnicos (SMA, EMA) com previsões do aprendizado de máquina para tomar decisões de negociação.
  3. Implementa várias estratégias de trailing stop.
  4. Inclui otimização periódica dos parâmetros dos indicadores e das configurações de negociação.
  5. Possui gerenciamento de risco embutido (tamanho do lote, verificação de capital).
  6. Considera o horário de funcionamento do mercado para negociar.

O EA combina a tradicional análise técnica com aprendizado de máquina para operar no mercado Forex. Ele também inclui diversos recursos de gerenciamento de risco e otimização para se adaptar às condições de mercado em mudança.

Parâmetros de entrada

Gráfico AAPL

Backtest no histórico da AAPL

A estratégia demonstrou ser lucrativa, com um sólido coeficiente de Sharpe de 6,21. No entanto, ela apresenta uma retração elevada, o que indica a necessidade de um gerenciamento de risco cuidadoso. A capacidade da estratégia de gerar lucros consistentes, visível na curva de patrimônio, indica seu potencial para uso em negociações reais. Otimizações futuras podem ser direcionadas à redução das retrações e ao aumento do fator de recuperação, visando melhorar o desempenho geral.


Conclusão

O artigo apresentou um EA inovador para negociação algorítmica no mercado Forex, desenvolvido especificamente para operar ações da Apple Inc. (#AAPL). O EA representa uma combinação sofisticada de aprendizado de máquina com análise técnica tradicional, voltada para o gerenciamento preciso e adaptativo de cenários complexos nos mercados cambiais.

O núcleo do EA é um modelo ONNX (Open Neural Network Exchange), que atua como componente de aprendizado de máquina. A função do modelo é prever o movimento de preços com base em dados recentes do mercado. O EA combina essas previsões com indicadores técnicos populares, como a média móvel simples (SMA) e a média móvel exponencial (EMA), para gerar sinais de negociação.

A abordagem é multifacetada e inclui várias características fundamentais:

  1. Otimização dinâmica: Tanto os indicadores técnicos quanto os parâmetros de negociação são otimizados periodicamente. Isso permite que o EA se ajuste às mudanças nas condições de mercado, potencialmente melhorando seu desempenho ao longo do tempo.
  2. Gerenciamento de risco adaptativo: O EA utiliza definição dinâmica do tamanho de lote e cálculos baseados na Média de Amplitude de Variação (ATR) para definir níveis de stop-loss e take-profit. Essa abordagem visa ajustar o tamanho das posições e o nível de risco com base na volatilidade atual do mercado.
  3. Múltiplas estratégias de trailing stop: O EA implementa diferentes métodos de trailing stop, permitindo uma gestão flexível das posições abertas e potencialmente maximizando os lucros enquanto minimiza perdas.
  4. Consciência das condições do mercado: O sistema leva em consideração os horários de funcionamento e as condições do mercado, garantindo que as operações sejam realizadas apenas quando for apropriado.

O artigo apresenta uma análise detalhada da estrutura do código do EA, explicando seus componentes principais:

  1. Inicialização: Nesta etapa, o modelo ONNX e os indicadores técnicos são configurados, preparando o EA para operar.
  2. Lógica principal de negociação: A funcionalidade central que decide quando abrir ou fechar posições, com base em sinais combinados da modelo de aprendizado de máquina e dos indicadores técnicos.
  3. Previsão de preços: Utiliza o modelo ONNX para prever os movimentos futuros dos preços.
  4. Funções de otimização: Ajusta periodicamente os parâmetros dos indicadores e configurações de negociação para manter a eficácia em condições de mercado variáveis.
  5. Gerenciamento de risco: Inclui funções para cálculo do tamanho do lote, gestão de capital e verificação das condições do mercado.

A eficácia do EA foi avaliada por meio de testes com dados históricos das ações da AAPL. Os resultados demonstraram uma lucratividade promissora, com um coeficiente de Sharpe de 6,21, indicando um retorno ajustado ao risco bastante alto. No entanto, a análise também revelou níveis relativamente altos de retração, o que aponta para áreas que podem se beneficiar de um aprimoramento no gerenciamento de risco.


Considerações finais

O EA analisado representa um avanço significativo. Ele utiliza uma combinação de tecnologias inteligentes (aprendizado de máquina) e métodos consagrados (análise técnica) para oferecer aos traders soluções exclusivas sobre como investir em ações da AAPL e outros ativos.

O EA integra o modelo ONNX para previsão de preços com indicadores técnicos otimizados. Essa combinação permite reagir tanto a mudanças bruscas de preço quanto a movimentos mais lentos, associados a eventos de longo prazo.

Uma de suas características mais atraentes é o sistema de gerenciamento de risco completo. Por exemplo, ele utiliza tamanho de lote dinâmico (ajustando o volume da operação conforme as condições de mercado), níveis de stop-loss e take-profit baseados na ATR (limitando lucros e perdas), além de várias estratégias de trailing stop sensíveis à mudança de preço. Essas ferramentas são projetadas especificamente para proteger seu capital contra perdas menos evidentes.

Outra característica notável deste EA é a atualização regular de seus indicadores e parâmetros de negociação. Isso permite que o EA acompanhe as mudanças do mercado, o que é muito importante para manter sua eficácia ao longo do tempo.

No entanto, os resultados dos testes com dados históricos ainda deixam a desejar. Apesar de parecerem bons em termos de lucro e gerenciamento de risco, foram observadas algumas retrações significativas — quedas expressivas no valor —, o que indica a necessidade de um gerenciamento de risco mais rigoroso. Versões futuras do EA podem incluir medidas de segurança mais eficazes ou uma abordagem mais cautelosa durante períodos de alta volatilidade.

Embora tenha sido desenvolvido para negociar ações da AAPL, os princípios em que ele se baseia podem ser facilmente aplicados a outros mercados financeiros. Essa flexibilidade torna a ferramenta útil tanto para operações atuais quanto para servir de modelo para futuras soluções algorítmicas.

Trata-se de um EA de negociação automática complexo e promissor, que combina tecnologias avançadas com abordagens tradicionais, sendo eficaz no gerenciamento de riscos e facilmente adaptável às mudanças do mercado. No entanto, como qualquer outro instrumento de negociação, ele requer monitoramento regular, atualizações e testes em condições reais para garantir seu funcionamento contínuo ao longo do tempo.

Por fim, embora esse EA claramente tenha grande potencial, ainda há trabalho a ser feito e muitas otimizações a serem realizadas. É importante lembrar que a negociação sempre envolve risco e que resultados passados não garantem sucesso futuro. Se você estiver considerando usar este ou qualquer outro sistema automatizado, certifique-se de entender os riscos e, idealmente, teste-o em um ambiente simulado antes de aplicá-lo com dinheiro real.

Espero que você consiga aprimorar bastante este EA e alcançar bons resultados. Ele é um bom exemplo de como implementar otimização automática com níveis de stop e indicadores. Espero que o artigo tenha sido útil.

Traduzido do Inglês pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/en/articles/15476

Arquivos anexados |
SE_v9.mq5 (80.02 KB)
Últimos Comentários | Ir para discussão (4)
Arup Nag
Arup Nag | 16 ago. 2024 em 09:12
Um guia passo a passo para otimização automática será muito útil
Javier Santiago Gaston De Iriarte Cabrera
Arup Nag otimização automática será muito útil

Obrigado! Estou fazendo um agora mesmo, ele será concluído em pouco tempo. Solicite qualquer outra coisa que queira ou precise.

Javier Santiago Gaston De Iriarte Cabrera
Arup Nag otimização automática será muito útil

Aqui está o artigo, espero que você goste: Como implementar a otimização automática em MQL5 Expert Advisors - MQL5 Articles

yehaichang
yehaichang | 9 abr. 2025 em 20:00
Se houver algum EA baseado em negociação de rede neural que eu gostaria de experimentar, ajustando os parâmetros da alta taxa de ganhos, vou comprar!
Reimaginando Estratégias Clássicas (Parte V): Análise de Múltiplos Símbolos no USDZAR Reimaginando Estratégias Clássicas (Parte V): Análise de Múltiplos Símbolos no USDZAR
Nesta série de artigos, revisitamos estratégias clássicas para verificar se podemos melhorá-las usando IA. No artigo de hoje, examinaremos uma estratégia popular de análise de múltiplos símbolos utilizando uma cesta de ativos correlacionados. Focaremos no par de moedas exótico USDZAR.
Simulação de mercado (Parte 12): Sockets (VI) Simulação de mercado (Parte 12): Sockets (VI)
Neste artigo, vamos ver como resolver algumas questões e ver alguns problemas que temos ao usar código feito em Python dentro de outros programas. No caso o que mostrarei aqui, é um típico problema que existe, quando você vai usar o Excel junto com o MetaTrader 5. Mas para fazer esta comunicação estaremos usando o Python. Porém existe um pequeno problema nesta implementação. Não em todos os casos, mas em alguns casos específicos e quando o problema ocorre você tem que entender por que ele ocorre. Neste artigo iniciarei a explicação de como resolver tal coisa.
Reimaginando Estratégias Clássicas (Parte VI): Análise de Múltiplos Tempos Gráficos Reimaginando Estratégias Clássicas (Parte VI): Análise de Múltiplos Tempos Gráficos
Nesta série de artigos, revisitamos estratégias clássicas para ver se podemos melhorá-las usando IA. No artigo de hoje, vamos examinar a popular estratégia de análise de múltiplos tempos gráficos para avaliar se a estratégia seria aprimorada com IA.
Do básico ao intermediário: Indicador (II) Do básico ao intermediário: Indicador (II)
Neste artigo veremos como implementar o calculo de média móvel e os cuidados a serem tomados ao efetivamente criar este calculo. Além disto, vamos também falar sobre a sobrecarga da função OnCalculate a fim de podemos saber quando e como trabalhar com um ou outro modelo de sobrecarga.