Техническое задание

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;

}




Откликнулись

1
Разработчик 1
Оценка
(83)
Проекты
143
52%
Арбитраж
8
13% / 75%
Просрочено
22
15%
Свободен
2
Разработчик 2
Оценка
Проекты
1
0%
Арбитраж
1
0% / 100%
Просрочено
1
100%
Свободен
3
Разработчик 3
Оценка
Проекты
0
0%
Арбитраж
0
Просрочено
0
Свободен
4
Разработчик 4
Оценка
Проекты
0
0%
Арбитраж
0
Просрочено
0
Свободен
5
Разработчик 5
Оценка
Проекты
0
0%
Арбитраж
0
Просрочено
0
Свободен
6
Разработчик 6
Оценка
Проекты
0
0%
Арбитраж
0
Просрочено
0
Свободен
Похожие заказы
Vamos aprender a operar no mercado Forex vamos aprender vamos trabalhar no mercado Forex vamos temos tudo para dar certo só trabalho só com trabalho podemos fazer tudo para nossa vida
Preciso de um EA versátil, totalmente configurável para MT5, que opera nos modos: Multi Timeframe e Monotimefreme, fazendo leituras do indicador HMA de ambos os modos. Quero um parâmetro de escolha(input) nas configurações do EA, pra mim poder alternar entre os dois modos. Uma opção para escolher o modo de operação. Tipo: Modo Operação: ( Mono time frame) (Multi Time Frame). Filtros e indicadores: ( HMA ),/ ( BANDAS
Estou em busca de um sistema operacional para mesas proprietarias, drawdown não pode passar de 3% e que faça algo entorno de 1 a 2% ao mês de lucratividade. forex ou futuros, o importante é o resultado
Hello, I need an Expert Advisor (EA) developed for MetaTrader 5, specifically tailored for the EUR/USD currency pair on the 5-minute (M5) timeframe. The robot should execute trades based on Price Action or Technical Analysis (such as Support/Resistance Breakouts or Moving Average Crossovers - I am open to the programmer's suggestions for proven, consolidated strategies). Mandatory Risk Management Requirements

Информация о проекте

Бюджет
30 - 100 USD
Сроки выполнения
от 1 до 7 дн.