Correção de Erros e Ajustes

Specifiche

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;

}




Con risposta

1
Sviluppatore 1
Valutazioni
(82)
Progetti
139
51%
Arbitraggio
5
20% / 60%
In ritardo
20
14%
In elaborazione
2
Sviluppatore 2
Valutazioni
Progetti
1
0%
Arbitraggio
0
In ritardo
1
100%
Gratuito
3
Sviluppatore 3
Valutazioni
Progetti
0
0%
Arbitraggio
0
In ritardo
0
Gratuito
4
Sviluppatore 4
Valutazioni
Progetti
0
0%
Arbitraggio
0
In ritardo
0
Gratuito
5
Sviluppatore 5
Valutazioni
Progetti
0
0%
Arbitraggio
0
In ritardo
0
Gratuito
6
Sviluppatore 6
Valutazioni
Progetti
0
0%
Arbitraggio
0
In ritardo
0
Gratuito
Ordini simili
Desenvolvi uma estratégia de trading personalizada que gostaria de automatizar através de um Expert Advisor (EA). Tenho conhecimento de que a implementação é tecnicamente viável e busco um programador experiente em MQL4/MQL5 para transformar essa estratégia em código funcional. Estou disposto a negociar os valores do projeto de forma transparente - o orçamento é flexível e não se limita aos $30
Desejo uma boleta estilo Profitchart, onde posso colocar ordens OCO no gráfico via teclado (SHIFT para compras e CTRL ou ALT para vendas). Ela deve ser compatível com ativos do tipo "custom symbols". Entrar em contato para mais detalhes: victor.olv88@gmail.com
Smart Retest and Reversal EA SRR EA O EA funcionará em todos os ativos no time frame desejado pelo usuário. INDICADORES 1) O EA irá utilizar os seguintes indicadores para operar, todos gratuitos: 1.1) "Area of interest MT5" 1.2) "Price Retest MT5" 1.3) "Price Reversal Predictor" 1.4) "Easy Buy Sell Signal" GATILHOS 2) Uma vez colocados os indicadores no gráfico, na configuração padrão, o EA poderá fazer dois tipos de
JB-1 30 - 50 USD
Olá! gostaria de um orçamento para desenvolver um robô para mercado forex com: regra de coloração; Cruzamento de duas médias moveis tillson; confirmação no macd; com quantidade de operações diarias que eu possa controlar o horário para operar
Eu já utilizo um robô na plataforma BA. É um indicador com automação baseado no Canal de Keltner, onde o box quando vai pra fora do canal ele indica que absorveu fora, ele aguarda o box que fecha para dentro do canal e indica que absorveu dentro, caso o próximo box feche para dentro ele confirma a compra ou venda. Além disso, preciso de opção de apenas comprar ou apenas vender; e outra com as duas opções de compra e

Informazioni sul progetto

Budget
30 - 100 USD
Per lo sviluppatore
27 - 90 USD
Scadenze
da 1 a 7 giorno(i)