Correção de Erros e Ajustes

Spécifications

Olá, bom dia.

Segue abaixo um estratégia que precisa de correção, os pontos principais estão inseridos na estratégia, falta correções para seguir as regras e os parametros; 

Regras:

TP: 10 e SL: 10 ( Simulação Inicial de COMPRA )


Ex1: Compra com lote de 1, se o preço subir 10 pips vai atingir o TP e encerrar essa operação, após o TP vai ser aberta uma ordem oposta (VENDA) com lote de 0,5 e TP:20 e SL:10, seguindo o simulação - se o preço continuar subindo encerra a estratégia, porém se o preço cair e atingir o TP de 20 pips essa ordem é encerrada, porém automaticamente abre uma ordem oposta (Compra) nesse caso e formando um Canal que vai se repetir indefinidamente, o lote agora é a metade do anterior 0,25 e SL: 10 e TP:20 e repetir até o SL em um dos lados do Canal;


Ex2: Compra com lote de 1, se o preço cair 10 pips vai atingir o SL e encerrar essa operação, após o SL da Compra vai ser aberta uma ordem oposta de (VENDA) com lote de 0,50 com TP:10 e SL:30 , se o preço continuar caindo e atingir o TP a operação é encerrada, porém se o preço começar a subir , assim que o preço atingir -10 pips é aberta uma nova ordem de COMPRA (Assim temos 2 ordens que estão abertas em direções diferentes) essa nova ordem tem SL:20 e TP:20 com lote de 1 (O lote Dobrou) e caso o preço continue subindo vai até atingir o SL da primeira ordem e o TP da segunda ordem, porém se o preço voltar a cair -10 pips, novamente é aberta uma nova ordem de VENDA (É criado assim um Canal que vai se repetir indefinidamente até atingir o TP e o SL das ordens abertas) essa nova ordem tem lote de 2 (dobro da anterior) e TP:10 e SL:30 e seguindo a estratégia de o preço continuar caindo vai encerrar todas operações, caso volte a subir continuamos com o canal.

Os Erros estão no Inicio da primeira operação onde esta parametrizado SL de 10 pips e TP de 10 pips e no MT5 aparece sempre 100 Pips de TP e SL;

O Segundo erro esta na execução das ordens com SL, TP e Lotes para formação dos Canais ( Iniciando com Compra e Iniciando Venda também )


* Correção dos SL e TP e Correção da Formação dos Canais ( Compra e Venda )

//+------------------------------------------------------------------+

//|                                                   HedgeChannelEA |

//|                                     Copyright 2023, NeoFlow Labs   |

//|                                       https://www.neoflowlab.com      |

//+------------------------------------------------------------------+

#property copyright "Copyright 2023, NeoFlow Labs"

#property version   "1.11" // Versão atualizada: separação dos cálculos para ordens de mercado e de canal

#property strict


// Declarações antecipadas

void RefreshRates();  // Em MQL5 os preços já são atualizados automaticamente

void HandleSLSequence(bool closedByTP);

void OpenOrderWithFixedPrice(ENUM_ORDER_TYPE newType, double lot, int tpPips, int slPips, double basePrice);


// Parâmetros de entrada

input double InitialLot     = 1.0;    // Lote inicial

input int    TP_Pips        = 10;     // Take Profit (pips) para a ordem inicial

input int    SL_Pips        = 10;     // Stop Loss (pips) para a ordem inicial

input double MaxDailyProfit = 500.0;  // Lucro máximo diário ($)

input double MaxDailyLoss   = -300.0; // Perda máxima diária ($)

input string StartTime      = "01:05"; // Horário inicial de negociação

input string EndTime        = "22:30"; // Horário final de negociação


// Variáveis globais

double DailyPL = 0;

bool TradingActive = true;

datetime lastCheckDay = 0;

datetime g_lastCandleTime = 0;


enum SequenceType { NONE, TP_SEQUENCE, SL_SEQUENCE };

SequenceType currentSequence = NONE;

bool waitingForReversal = false;

double hedgeOpenPrice = 0;      // Preço base congelado para as ordens de canal

double lastTradeLot = InitialLot;

ENUM_POSITION_TYPE lastTradeType = POSITION_TYPE_BUY;


//+------------------------------------------------------------------+

//| Stub para RefreshRates()                                         |

//+------------------------------------------------------------------+

void RefreshRates()

{

   // Em MQL5 os preços são atualizados automaticamente.

}


//+------------------------------------------------------------------+

//| Obtém o valor de 1 pip de forma robusta                          |

//| (Força a interpretação correta para símbolos como EURUSD, mesmo  |

//| quando o nome do símbolo contém sufixos)                         |

//+------------------------------------------------------------------+

double GetPipValue()

{

   // Se o símbolo contiver "EURUSD", forçamos 1 pip = 0.0001

   string symbol = Symbol();

   if(StringFind(symbol, "EURUSD") >= 0)

      return 0.0001;

      

   // Caso geral: utiliza SYMBOL_DIGITS para determinar o valor do pip

   int digits = (int)SymbolInfoInteger(symbol, SYMBOL_DIGITS);

   if(digits == 5 || digits == 4)

      return 0.0001;

   if(digits == 3)

      return 0.001;

   if(digits == 2)

      return 0.01;

   return SymbolInfoDouble(symbol, SYMBOL_POINT);

}


//+------------------------------------------------------------------+

//| Função de inicialização                                          |

//+------------------------------------------------------------------+

int OnInit()

{

   EventSetTimer(60);

   g_lastCandleTime = iTime(Symbol(), PERIOD_CURRENT, 0);

   return(INIT_SUCCEEDED);

}


//+------------------------------------------------------------------+

//| Função de desinicialização                                       |

//+------------------------------------------------------------------+

void OnDeinit(const int reason)

{

   EventKillTimer();

}


//+------------------------------------------------------------------+

//| Função principal                                                 |

//+------------------------------------------------------------------+

void OnTick()

{

   if(!TradingActive || CheckDailyLimits())

      return;

   

   datetime currentCandleTime = iTime(Symbol(), PERIOD_CURRENT, 0);

   if(currentCandleTime != g_lastCandleTime)

   {

      g_lastCandleTime = currentCandleTime;

      if(PositionsTotal() == 0 && IsTradingTime())

         OpenInitialTrade();

   }

   

   if(PositionsTotal() > 0)

      ManageOpenPositions();

}


//+------------------------------------------------------------------+

//| Verifica limites diários                                         |

//+------------------------------------------------------------------+

bool CheckDailyLimits()

{

   MqlDateTime currentDate;

   datetime current_time = TimeCurrent();

   TimeToStruct(current_time, currentDate);

   currentDate.hour = 0;

   currentDate.min  = 0;

   currentDate.sec  = 0;

   datetime currentDay = StructToTime(currentDate);

   

   if(currentDay > lastCheckDay)

   {

      DailyPL = 0;

      lastCheckDay = currentDay;

   }

   

   if(DailyPL >= MaxDailyProfit || DailyPL <= MaxDailyLoss)

   {

      TradingActive = false;

      return true;

   }

   return false;

}


//+------------------------------------------------------------------+

//| Verifica se está dentro do horário de negociação                 |

//+------------------------------------------------------------------+

bool IsTradingTime()

{

   datetime now   = TimeCurrent();

   datetime start = StringToTime(StartTime);

   datetime end   = StringToTime(EndTime);

   

   if(start < end)

      return (now >= start && now <= end);

   else

      return (now >= start || now <= end);

}


//+------------------------------------------------------------------+

//| Fecha uma posição                                                |

//+------------------------------------------------------------------+

void ClosePosition(ulong ticket)

{

   if(!PositionSelectByTicket(ticket))

   {

      Print("Posição ", ticket, " não existe para fechamento.");

      return;

   }

   

   MqlTradeRequest request = {};

   MqlTradeResult result   = {};

   request.action   = TRADE_ACTION_DEAL;

   request.position = ticket;

   request.symbol   = Symbol();

   request.volume   = PositionGetDouble(POSITION_VOLUME);

   request.type     = (PositionGetInteger(POSITION_TYPE) == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;

   request.price    = (request.type == ORDER_TYPE_SELL) ? SymbolInfoDouble(Symbol(), SYMBOL_BID) : SymbolInfoDouble(Symbol(), SYMBOL_ASK);

   request.deviation= 3;

   request.type_filling = ORDER_FILLING_FOK;

   

   if(OrderSend(request, result))

      Print("Posição fechada: Ticket ", ticket);

   else

      Print("Falha ao fechar posição. Erro: ", GetLastError());

}


//+------------------------------------------------------------------+

//| Abre a ordem inicial (market order)                              |

//+------------------------------------------------------------------+

void OpenInitialTrade()

{

   // Envia ordem de COMPRA com TP e SL de 10 pips utilizando os preços atuais

   OpenOrder(ORDER_TYPE_BUY, InitialLot, TP_Pips, SL_Pips);

   currentSequence = NONE;

}


//+------------------------------------------------------------------+

//| Função para abrir ordem (market order) com preços atualizados      |

//+------------------------------------------------------------------+

void OpenOrder(ENUM_ORDER_TYPE newType, double lot, int tpPips, int slPips)

{

   RefreshRates();

   MqlTradeRequest request = {};

   MqlTradeResult result   = {};

   double price, sl, tp;

   double pip = GetPipValue();

   

   if(newType == ORDER_TYPE_SELL)

   {

      price = SymbolInfoDouble(Symbol(), SYMBOL_BID);

      sl    = price + slPips * pip;

      tp    = price - tpPips * pip;

   }

   else

   {

      price = SymbolInfoDouble(Symbol(), SYMBOL_ASK);

      sl    = price - slPips * pip;

      tp    = price + tpPips * pip;

   }

   tp = NormalizeDouble(tp, (int)SymbolInfoInteger(Symbol(), SYMBOL_DIGITS));

   sl = NormalizeDouble(sl, (int)SymbolInfoInteger(Symbol(), SYMBOL_DIGITS));

   

   request.action       = TRADE_ACTION_DEAL;

   request.symbol       = Symbol();

   request.volume       = lot;

   request.type         = newType;

   request.price        = price;

   request.sl           = sl;

   request.tp           = tp;

   request.deviation    = 3;

   request.type_filling = ORDER_FILLING_FOK;

   

   if(OrderSend(request, result))

   {

      Print("Ordem inicial aberta: ", EnumToString(newType), " Lote: ", lot,

            " TP: ", tpPips, " pips, SL: ", slPips, " pips, Preço: ", price);

      hedgeOpenPrice = price; // Armazena o preço base para as ordens de canal

   }

   else

      Print("Erro na ordem inicial: ", GetLastError());

}


//+------------------------------------------------------------------+

//| Função para abrir ordens de canal (pending orders) usando preço fixo |

//| Os cálculos de SL/TP para ordens de canal utilizam os parâmetros   |

//| definidos para o canal, sem interferir na ordem inicial             |

//+------------------------------------------------------------------+

void OpenOrderWithFixedPrice(ENUM_ORDER_TYPE newType, double lot, int tpPips, int slPips, double basePrice)

{

   RefreshRates();

   MqlTradeRequest request = {};

   MqlTradeResult result   = {};

   double pip = GetPipValue();

   double sl, tp;

   

   // Utiliza o preço base congelado (hedgeOpenPrice) sem ajuste com a cotação atual

   if(newType == ORDER_TYPE_SELL)

   {

      // Ordem pendente de venda: SELL STOP

      sl = basePrice + slPips * pip;

      tp = basePrice - tpPips * pip;

      request.type = ORDER_TYPE_SELL_STOP;

   }

   else

   {

      // Ordem pendente de compra: BUY STOP

      sl = basePrice - slPips * pip;

      tp = basePrice + tpPips * pip;

      request.type = ORDER_TYPE_BUY_STOP;

   }

   tp = NormalizeDouble(tp, (int)SymbolInfoInteger(Symbol(), SYMBOL_DIGITS));

   sl = NormalizeDouble(sl, (int)SymbolInfoInteger(Symbol(), SYMBOL_DIGITS));

   

   request.action       = TRADE_ACTION_PENDING;

   request.symbol       = Symbol();

   request.volume       = lot;

   request.price        = basePrice;

   request.sl           = sl;

   request.tp           = tp;

   request.deviation    = 3;

   request.type_filling = ORDER_FILLING_FOK;

   

   if(OrderSend(request, result))

      Print("Ordem fixa aberta: ", EnumToString(request.type), " Lote: ", lot,

            " TP: ", tpPips, " pips, SL: ", slPips, " pips, Preço base: ", basePrice);

   else

      Print("Erro na ordem fixa: ", GetLastError());

}


//+------------------------------------------------------------------+

//| Gerenciamento de posições                                        |

//+------------------------------------------------------------------+

void ManageOpenPositions()

{

   for(int i = PositionsTotal()-1; i >= 0; i--)

   {

      ulong ticket = PositionGetTicket(i);

      if(PositionSelectByTicket(ticket))

      {

         double profit = PositionGetDouble(POSITION_PROFIT);

         double currentPrice = PositionGetDouble(POSITION_PRICE_CURRENT);

         ENUM_POSITION_TYPE type = (ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE);

         double positionTP = PositionGetDouble(POSITION_TP);

         double positionSL = PositionGetDouble(POSITION_SL);

         

         bool exitCondition = false;

         if(type == POSITION_TYPE_BUY)

            exitCondition = (currentPrice >= positionTP || currentPrice <= positionSL);

         else if(type == POSITION_TYPE_SELL)

            exitCondition = (currentPrice <= positionTP || currentPrice >= positionSL);

         

         if(exitCondition)

         {

            lastTradeLot = PositionGetDouble(POSITION_VOLUME);

            lastTradeType = type;

            ClosePosition(ticket);

            DailyPL += profit;

            

            bool closedByTP = (profit >= 0);

            HandleSequence(closedByTP);

            break; // Processa apenas uma posição por tick para evitar duplicidade

         }

      }

   }

   

   if(waitingForReversal)

      CheckSLReversal();

}


//+------------------------------------------------------------------+

//| Lógica de sequência após fechamento                              |

//+------------------------------------------------------------------+

void HandleSequence(bool closedByTP)

{

   if(currentSequence == NONE)

      currentSequence = closedByTP ? TP_SEQUENCE : SL_SEQUENCE;

   

   if(currentSequence == TP_SEQUENCE)

      OpenNextOrder_TP();

   else if(currentSequence == SL_SEQUENCE)

      HandleSLSequence(closedByTP);

}


//+------------------------------------------------------------------+

//| Função HandleSLSequence para ordens pendentes de canal           |

//+------------------------------------------------------------------+

void HandleSLSequence(bool closedByTP)

{

   if(!closedByTP)

      OpenNextOrder_SL_initial();

   else

   {

      waitingForReversal = true;

      hedgeOpenPrice = (lastTradeType == POSITION_TYPE_SELL) ?

                       SymbolInfoDouble(Symbol(), SYMBOL_BID) :

                       SymbolInfoDouble(Symbol(), SYMBOL_ASK);

   }

}


//+------------------------------------------------------------------+

//| Para sequência TP: abre ordem oposta fixa com lote = metade       |

//+------------------------------------------------------------------+

void OpenNextOrder_TP()

{

   ENUM_ORDER_TYPE newType = (lastTradeType == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;

   double newLot = lastTradeLot / 2;

   int newTP = 20;

   int newSL = 10;

   // Utiliza o preço base congelado para a ordem de canal

   OpenOrderWithFixedPrice(newType, newLot, newTP, newSL, hedgeOpenPrice);

   UpdateSequenceInfo(newType, newLot);

}


//+------------------------------------------------------------------+

//| Para sequência SL inicial: abre ordem oposta fixa com lote = metade |

//+------------------------------------------------------------------+

void OpenNextOrder_SL_initial()

{

   ENUM_ORDER_TYPE newType = (lastTradeType == POSITION_TYPE_BUY) ? ORDER_TYPE_SELL : ORDER_TYPE_BUY;

   double newLot = lastTradeLot / 2;

   int newTP = 10;

   int newSL = 30;

   OpenOrderWithFixedPrice(newType, newLot, newTP, newSL, hedgeOpenPrice);

   UpdateSequenceInfo(newType, newLot);

}


//+------------------------------------------------------------------+

//| Para sequência SL continuada: abre ordem oposta fixa com lote dobrado |

//+------------------------------------------------------------------+

void OpenNextOrder_SL()

{

   ENUM_ORDER_TYPE newType = (lastTradeType == POSITION_TYPE_SELL) ? ORDER_TYPE_BUY : ORDER_TYPE_SELL;

   double newLot = lastTradeLot * 2;

   int newTP = (newType == ORDER_TYPE_BUY) ? 20 : 10;

   int newSL = (newType == ORDER_TYPE_BUY) ? 20 : 30;

   OpenOrderWithFixedPrice(newType, newLot, newTP, newSL, hedgeOpenPrice);

   UpdateSequenceInfo(newType, newLot);

}


//+------------------------------------------------------------------+

//| Atualiza informações da sequência                                |

//+------------------------------------------------------------------+

void UpdateSequenceInfo(ENUM_ORDER_TYPE newType, double newLot)

{

   lastTradeLot = newLot;

   lastTradeType = (newType == ORDER_TYPE_BUY) ? POSITION_TYPE_BUY : POSITION_TYPE_SELL;

   waitingForReversal = false;

}


//+------------------------------------------------------------------+

//| Verificação de reversão para SL                                  |

//+------------------------------------------------------------------+

void CheckSLReversal()

{

   double pip = GetPipValue();

   double reversalDistance = 10 * pip;

   

   double currentPrice = (lastTradeType == POSITION_TYPE_SELL) ?

                         SymbolInfoDouble(Symbol(), SYMBOL_ASK) :

                         SymbolInfoDouble(Symbol(), SYMBOL_BID);

   

   if((lastTradeType == POSITION_TYPE_SELL && currentPrice >= hedgeOpenPrice + reversalDistance) ||

      (lastTradeType == POSITION_TYPE_BUY && currentPrice <= hedgeOpenPrice - reversalDistance))

   {

      OpenNextOrder_SL();

   }

}


//+------------------------------------------------------------------+

//| Função Timer para reset diário                                   |

//+------------------------------------------------------------------+

void OnTimer()

{

   if(IsTradingTime())

   {

      if(!TradingActive && CheckDailyLimits())

         TradingActive = true;

   }

   else

      TradingActive = false;

}




Répondu

1
Développeur 1
Évaluation
(83)
Projets
143
52%
Arbitrage
8
13% / 75%
En retard
22
15%
Gratuit
2
Développeur 2
Évaluation
Projets
1
0%
Arbitrage
1
0% / 100%
En retard
1
100%
Gratuit
3
Développeur 3
Évaluation
Projets
0
0%
Arbitrage
0
En retard
0
Gratuit
4
Développeur 4
Évaluation
Projets
0
0%
Arbitrage
0
En retard
0
Gratuit
5
Développeur 5
Évaluation
Projets
0
0%
Arbitrage
0
En retard
0
Gratuit
6
Développeur 6
Évaluation
Projets
0
0%
Arbitrage
0
En retard
0
Gratuit
Commandes similaires
Consulta a programador experiente em B3 — divergência entre ambiente de teste e execução real Estou procurando a opinião de um programador com experiência específica em MT5, execução na B3 e mercado de futuros brasileiro , porque estou investigando uma questão de comportamento de um Expert Advisor. Tenho um EA desenvolvido para operar mini índice , e nos testes realizados no Strategy Tester do MT5 e também em conta
Preciso de um EA consistente no mercado forex, Pode ser EA de GRID, Scalping, que eu possa escolher até quantas ordens deve abrir, qual o volume do lote, horários para abrir novas ordens, que faça o cálculo das ordens abertas e se estiver no lucro que eu escolher no painel, assim ele fechará, mesmo que eu tenha parado as ordens naquele certo horário. O Setup será básico, de Médias Móveis, Estocástico
Preciso de um EA consistente no mercado forex, Pode ser EA de GRID, Scalping, que eu possa escolher até quantas ordens deve abrir, qual o volume do lote, horários para abrir novas ordens, que faça o cálculo das ordens abertas e se estiver no lucro que eu escolher no painel, assim ele fechará, mesmo que eu tenha parado as ordens naquele certo horário. O Setup será básico, de Médias Móveis, Estocástico

Informations sur le projet

Budget
30 - 100 USD
Délais
de 1 à 7 jour(s)