← К каталогу
Исходный код · ID 4102

goldtrap_replica (1).mq5

Вы автор или правообладатель?

Сообщите нам, если считаете, что материал размещён без разрешения.

Краткий обзор

О программе

Советник для торговли XAUUSD на MetaTrader 5, реализующий стратегию динамической сетки восстановления. Работает в режиме хеджинга: размещает пару отложенных ордеров Buy Stop и Sell Stop, при срабатывании одной стороны открывает корзину позиций в этом направлении с прогрессивным увеличением лота. Цель — восстановить убытки и выйти в прибыль по заданному таргету на корзину.

Внутри используется конечный автомат с шестью состояниями: инициализация, ожидание триггера, активная корзина на покупку, активная корзина на продажу, закрытие корзины и сброс цикла. При запуске советник восстанавливает состояние по существующим позициям и ордерам, определяет направление активной корзины и при необходимости удаляет противоположные отложенные ордера. Обновляет стоп-лосс и тейк-профит на брокерском сервере для всех позиций корзины.

Советник включает фильтр спреда, фильтр торговой сессии, дневной лимит реализованной прибыли и фильтр новостей на основе встроенного календаря MQL5. Поддерживает защиту от максимальной просадки с аварийной ликвидацией всех позиций и ордеров. Требуется счёт с режимом хеджинга и брокерская поддержка модификации позиций.

Настройки программы

НастройкаОписание
D1 Шаг сетки — Расстояние в цене от средней цены для размещения начальных отложенных ордеров Buy Stop и Sell Stop.
V1 Начальный лот — Базовый размер лота для первой сделки в корзине.
N Макс. позиций в корзине — Максимальное количество позиций в одной направленной корзине (сетка).
S1 Шаг сетки 1 — Расстояние между уровнями сетки для первых P2 добавлений.
S2 Шаг сетки 2 — Расстояние между уровнями сетки для добавлений после P2.
T1 Целевая прибыль на лот — Требуемая прибыль в долларах на один лот для закрытия корзины.
E1 Множитель лота — Коэффициент умножения объёма лота при каждом новом уровне сетки.
R1 (1.0=100%, 0.2=20%) (R1) Множитель начального лота — Коэффициент для корректировки начального лота (0 — без изменений).
P1 Макс. спред — Максимально допустимый спред для входа в сделку.
P2 Кол-во уровней с S1 — Число первых добавлений в корзину, для которых используется шаг S1.
H1 Параметр H1 — Числовой параметр, объявленный во входных настройках.
M1 Магик BUY — Магический номер для ордеров и позиций на покупку.
M2 Магик SELL — Магический номер для ордеров и позиций на продажу.
F1 Фильтр сессии — Включает фильтр торговой сессии по времени (F1).
T2 Час начала сессии — Час начала торговой сессии для фильтра F1.
T3 Минута начала сессии — Минута начала торговой сессии для фильтра F1.
T4 Час окончания сессии — Час окончания торговой сессии для фильтра F1.
T5 Минута окончания сессии — Минута окончания торговой сессии для фильтра F1.
F2 Отмена ордеров при блокировке — Отмена всех отложенных ордеров при блокировке новостями или принудительно (F2).
F3 Дневной таргет — Включает контроль дневной реализованной прибыли (F3).
DT1 Дневной таргет сумма — Минимальная дневная реализованная прибыль в долларах для остановки торговли.
F4 Фильтр новостей — Включает фильтрацию новостей через календарь MQL5 (F4).
N1 (InpNewsMode) Режим новостей — Уровень важности новостей для блокировки: только высокие, средние и высокие, или все.
T6 Защита до новости (мин) — За сколько минут до события начинать блокировку входов.
T7 Защита после новости (мин) — Сколько минут после события продолжать блокировку входов.
Получить полный код

Поиск по коду файла

#property version   "2.00"
#property description "Complete XAUUSD Dynamic Recovery Grid Expert Advisor for MT5"
#property description "Features dynamic lot optimization, one-side basket recovery, state reconstruction, and strict comment tagging."

#include <Trade\Trade.mqh>
#include <Trade\PositionInfo.mqh>
#include <Trade\OrderInfo.mqh>

const string EA_COMMENT = "Developed By @manoj8901";

enum ENUM_N1_MODE
{
   N0 = 0,   // All importance levels
   N1 = 1,   // Medium and High importance
   N2 = 2    // High importance only
};

input group "=== A ==="
input string   InpLicenseKey = "";             // License Key (GTXX-XXXX-XXXX-XXXX)

input group "=== B ==="
input double   D1 = 1.00;
input double   V1 = 0.01;

input group "=== C ==="
input int      N  = 2000;
input double   S1 = 13.0;
input double   S2 = 2.60;
input double   T1 = 40.00;
input double   E1 = 1.68;
input double   R1 = 0.0;                       // R1 (1.0=100%, 0.2=20%)
input double   P1 = 0.50;
input int      P2 = 2;
input double   H1 = 0.0;

input group "=== D ==="
input ulong    M1 = 123456;
input ulong    M2 = 123457;

input group "=== E ==="
input bool     F1 = true;
input int      T2 = 1;
input int      T3 = 15;
input int      T4 = 22;
input int      T5 = 0;
input bool     F2 = false;

input group "=== F ==="
input bool     F3 = false;
input double   DT1 = 0.0;

input group "=== G ==="
input bool     F4 = false;
input ENUM_N1_MODE InpNewsMode = N2;           // N1
input int      T6 = 30;
input int      T7 = 30;

const ulong    InpSlippage               = 30;
const double   InpMaxLot                 = 1000.00;
const bool     InpUpdateBrokerTP         = true;
const int      InpMinimumDelayBetweenOrders = 1;
const bool     InpEnableLogs             = true;
const int      InpNewsLookAheadDays      = 14;
const bool     InpCancelPendingsForNews  = true;
const int      InpNewsRefreshSeconds     = 30;

enum ENUM_AFTER_MAX_DD
{
   DD_CONTINUE_TRADING = 0,   // Continue Trading
   DD_STOP_TRADING     = 1    // Stop Trading
};

const bool               InpEnableMaxDDProtection = false;
const double             InpMaxDrawdownPercent    = 20.0;
const ENUM_AFTER_MAX_DD  InpAfterMaxDD            = DD_STOP_TRADING;

enum ENUM_EA_STATE
{
   STATE_INIT,                   // Initializing / Reconstructing state
   STATE_WAITING_FOR_TRIGGER,    // Waiting for Buy Stop or Sell Stop to trigger
   STATE_BUY_BASKET_ACTIVE,      // BUY basket active, managing recovery grid
   STATE_SELL_BASKET_ACTIVE,     // SELL basket active, managing recovery grid
   STATE_CLOSING_BASKET,         // Profit target reached, closing all positions
   STATE_RESETTING_CYCLE         // Resetting cycle after full closure
};

CTrade         m_trade;
CPositionInfo  m_position;
COrderInfo     m_order;

ENUM_EA_STATE  g_state = STATE_INIT;
datetime       g_last_order_time = 0;

bool           g_max_dd_emergency_active   = false;
bool           g_trading_stopped_by_max_dd = false;

bool           g_news_blocked       = false;
bool           g_calendar_available = true;
datetime       g_last_news_scan     = 0;
datetime       g_next_news_time     = 0;
string         g_next_news_name     = "No scheduled high-impact USD news";
string         g_active_news_name   = "";

bool IsOurMagic(const long magic)
{
   return ((ulong)magic == M1 || (ulong)magic == M2);
}

void SetTradeMagic(const ulong magic)
{
   m_trade.SetExpertMagicNumber(magic);
}

int OnInit()
{
      // код доступен только после оплаты
   }

void OnDeinit(const int reason)
{
   LogMessage(StringFormat("EA Deinitialized. Reason code: %d", reason));
}

void OnTick()
{
      // код доступен только после оплаты
   }

void OnTradeTransaction(const MqlTradeTransaction &trans,
                         const MqlTradeRequest &request,
                         const MqlTradeResult &result)
{
   if(g_trading_stopped_by_max_dd) return;

   if(g_max_dd_emergency_active)
   {
      ProcessMaxDDEmergency();
      return;
   }

   if(IsMaxDrawdownReached())
   {
      TriggerMaxDDEmergency();
      ProcessMaxDDEmergency();
      return;
   }

   if(trans.type == TRADE_TRANSACTION_ORDER_ADD ||
      trans.type == TRADE_TRANSACTION_ORDER_DELETE ||
      trans.type == TRADE_TRANSACTION_HISTORY_ADD)
   {
      ReconstructState();
   }
}

void ReconstructState()
{
   int buy_pos_count  = 0;
   int sell_pos_count = 0;
   int buy_stop_count = 0;
   int sell_stop_count = 0;

   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      if(m_position.SelectByIndex(i))
      {
         if(m_position.Symbol() == _Symbol && IsOurMagic(m_position.Magic()))
         {
            if(m_position.PositionType() == POSITION_TYPE_BUY)
               buy_pos_count++;
            else if(m_position.PositionType() == POSITION_TYPE_SELL)
               sell_pos_count++;
         }
      }
   }

   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(m_order.SelectByIndex(i))
      {
         if(m_order.Symbol() == _Symbol && IsOurMagic(m_order.Magic()))
         {
            if(m_order.OrderType() == ORDER_TYPE_BUY_STOP)
               buy_stop_count++;
            else if(m_order.OrderType() == ORDER_TYPE_SELL_STOP)
               sell_stop_count++;
         }
      }
   }

   if(buy_pos_count > 0 && sell_pos_count == 0)
   {

      if(sell_stop_count > 0)
      {
         LogMessage("BUY Basket triggered. Deleting opposite Sell Stop order.");
         CancelPendingOrders(ORDER_TYPE_SELL_STOP);
      }
      if(g_state != STATE_CLOSING_BASKET)
         g_state = STATE_BUY_BASKET_ACTIVE;

      UpdateBrokerBasketTP(POSITION_TYPE_BUY);
   }
   else if(sell_pos_count > 0 && buy_pos_count == 0)
   {

      if(buy_stop_count > 0)
      {
         LogMessage("SELL Basket triggered. Deleting opposite Buy Stop order.");
         CancelPendingOrders(ORDER_TYPE_BUY_STOP);
      }
      if(g_state != STATE_CLOSING_BASKET)
         g_state = STATE_SELL_BASKET_ACTIVE;

      UpdateBrokerBasketTP(POSITION_TYPE_SELL);
   }
   else if(buy_pos_count == 0 && sell_pos_count == 0)
   {

      if(buy_stop_count > 0 || sell_stop_count > 0)
      {
         g_state = STATE_WAITING_FOR_TRIGGER;
      }
      else
      {
         g_state = STATE_RESETTING_CYCLE;
      }
   }
   else if(buy_pos_count > 0 && sell_pos_count > 0)
   {
      Print("[EA WARNING] Hedging overlap detected (both BUY and SELL positions exist). Grid entries paused for safety.");
   }
}

void ProcessWaitingForTriggerState()
{
   int buy_stop_count = 0;
   int sell_stop_count = 0;

   for(int i = OrdersTotal() - 1; i >= 0; i--)
   {
      if(m_order.SelectByIndex(i))
      {
         if(m_order.Symbol() == _Symbol && IsOurMagic(m_order.Magic()))
         {
            if(m_order.OrderType() == ORDER_TYPE_BUY_STOP) buy_stop_count++;
            if(m_order.OrderType() == ORDER_TYPE_SELL_STOP) sell_stop_count++;
         }
      }
   }

   bool news_blocked = IsNewsWindowBlocked();
   bool entry_allowed = CanStartNewCycle();
   if(!entry_allowed)
   {
      bool must_cancel_for_news = (news_blocked && InpCancelPendingsForNews);
      if((must_cancel_for_news || F2) && GetPositionCount() == 0 && (buy_stop_count > 0 || sell_stop_count > 0))
         CancelAllPendingOrders();
      return;
   }

   if(buy_stop_count == 1 && sell_stop_count == 1)
      return;

   if(GetPositionCount() == 0)
   {
      PlaceInitialPendingOrders();
   }
}

void PlaceInitialPendingOrders()
{
   if(!CanStartNewCycle() || IsSpreadExceeded()) return;

   CancelAllPendingOrders();

   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double ref_price = (ask + bid) / 2.0;

   double buy_stop_price  = NormalizePrice(ref_price + D1);
   double sell_stop_price = NormalizePrice(ref_price - D1);

   double initial_lot = GetConfiguredInitialLot();

   double k_profit = GetProfitPerUnitPerLot();
   if(k_profit <= 0.0) k_profit = 100.0;
   double target_dist = T1 / k_profit;

   double buy_tp  = InpUpdateBrokerTP ? NormalizePrice(buy_stop_price + target_dist) : 0.0;
   double sell_tp = InpUpdateBrokerTP ? NormalizePrice(sell_stop_price - target_dist) : 0.0;

   LogMessage(StringFormat("Starting New Cycle. Ref Price: %.2f | Buy Stop: %.2f (TP: %.2f) | Sell Stop: %.2f (TP: %.2f) | Comment: %s",
              ref_price, buy_stop_price, buy_tp, sell_stop_price, sell_tp, EA_COMMENT));

   SetTradeMagic(M1);
   if(!m_trade.BuyStop(initial_lot, buy_stop_price, _Symbol, 0.0, buy_tp, ORDER_TIME_GTC, 0, EA_COMMENT))
   {
      PrintFormat("[EA ERROR] Failed to place Buy Stop order at %.2f. Error: %d", buy_stop_price, GetLastError());
      return;
   }

   SetTradeMagic(M2);
   if(!m_trade.SellStop(initial_lot, sell_stop_price, _Symbol, 0.0, sell_tp, ORDER_TIME_GTC, 0, EA_COMMENT))
   {
      PrintFormat("[EA ERROR] Failed to place Sell Stop order at %.2f. Error: %d", sell_stop_price, GetLastError());
      return;
   }

   g_state = STATE_WAITING_FOR_TRIGGER;
}

void ProcessBuyBasketState()
{

   if(CheckBasketProfitTarget(POSITION_TYPE_BUY))
   {
      g_state = STATE_CLOSING_BASKET;
      CloseActiveBasket();
      return;
   }

   int buy_pos_count = GetPositionCount(POSITION_TYPE_BUY);
   if(buy_pos_count < N)
   {
      double lowest_buy_price = GetLowestEntryPrice(POSITION_TYPE_BUY);
      if(lowest_buy_price > 0.0)
      {
         double next_grid_price = NormalizePrice(lowest_buy_price - GetGridDistancePrice(buy_pos_count));
         double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);

         if(ask <= next_grid_price)
         {
            if(!IsSpreadExceeded() && (TimeCurrent() - g_last_order_time >= InpMinimumDelayBetweenOrders))
            {

               double next_lot = CalculateNextGridLot(POSITION_TYPE_BUY, next_grid_price);
               if(next_lot > 0.0)
               {
                  SetTradeMagic(M1);
                  if(m_trade.Buy(next_lot, _Symbol, 0.0, 0.0, 0.0, EA_COMMENT))
                  {
                     g_last_order_time = TimeCurrent();
                     UpdateBrokerBasketTP(POSITION_TYPE_BUY);
                  }
                  else
                  {
                     PrintFormat("[EA ERROR] Failed to open BUY grid trade. Error: %d", GetLastError());
                  }
               }
               else
               {
                  Print("[EA WARNING] Next lot calculation returned 0.0 (MaxLot reached or invalid lot). Grid trade skipped.");
               }
            }
         }
      }
   }

   UpdateBrokerBasketTP(POSITION_TYPE_BUY);
}

void ProcessSellBasketState()
{

   if(CheckBasketProfitTarget(POSITION_TYPE_SELL))
   {
      g_state = STATE_CLOSING_BASKET;
      CloseActiveBasket();
      return;
   }

   int sell_pos_count = GetPositionCount(POSITION_TYPE_SELL);
   if(sell_pos_count < N)
   {
      double highest_sell_price = GetHighestEntryPrice(POSITION_TYPE_SELL);
      if(highest_sell_price > 0.0)
      {
         double next_grid_price = NormalizePrice(highest_sell_price + GetGridDistancePrice(sell_pos_count));
         double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);

         if(bid >= next_grid_price)
         {
            if(!IsSpreadExceeded() && (TimeCurrent() - g_last_order_time >= InpMinimumDelayBetweenOrders))
            {

               double next_lot = CalculateNextGridLot(POSITION_TYPE_SELL, next_grid_price);
               if(next_lot > 0.0)
               {
                  SetTradeMagic(M2);
                  if(m_trade.Sell(next_lot, _Symbol, 0.0, 0.0, 0.0, EA_COMMENT))
                  {
                     g_last_order_time = TimeCurrent();
                     UpdateBrokerBasketTP(POSITION_TYPE_SELL);
                  }
                  else
                  {
                     PrintFormat("[EA ERROR] Failed to open SELL grid trade. Error: %d", GetLastError());
                  }
               }
               else
               {
                  Print("[EA WARNING] Next lot calculation returned 0.0 (MaxLot reached or invalid lot). Grid trade skipped.");
               }
            }
         }
      }
   }

   UpdateBrokerBasketTP(POSITION_TYPE_SELL);
}

double CalculateNextGridLot(ENUM_POSITION_TYPE type, double grid_entry_price)
{
   double last_lot = 0.0;
   datetime latest_time = 0;
   int pos_count = 0;
   double total_basket_lots = 0.0;
   double current_floating_profit = 0.0;

   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      if(m_position.SelectByIndex(i))
      {
         if(m_position.Symbol() == _Symbol && IsOurMagic(m_position.Magic()) &&
            m_position.PositionType() == type)
         {
            pos_count++;
            double vol = m_position.Volume();
            total_basket_lots += vol;
            current_floating_profit += m_position.Profit() + m_position.Swap();

            datetime pos_time = m_position.Time();
            if(pos_time >= latest_time)
            {
               latest_time = pos_time;
               last_lot = vol;
            }
         }
      }
   }

   if(last_lot <= 0.0)
      return GetConfiguredInitialLot();

   double raw_next_lot = last_lot * E1;

   double normalized_next_lot = NormalizeVolume(raw_next_lot);

   double max_broker_vol = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MAX);
   if(normalized_next_lot > InpMaxLot || normalized_next_lot > max_broker_vol)
   {
      PrintFormat("[EA WARNING] Calculated lot (%.2f) exceeds MaxLot limit (%.2f). Grid trade blocked.",
                  normalized_next_lot, InpMaxLot);
      return 0.0;
   }

   if(InpEnableLogs)
   {
      double basket_target_profit = (total_basket_lots + normalized_next_lot) * T1;
      PrintFormat("---------------- GRID TRADE PROGRESSION (#%d) ----------------", pos_count + 1);
      PrintFormat("Previous Lot: %.2f | Lot Multiplier: %.2f", last_lot, E1);
      PrintFormat("Raw Next Lot: %.4f | Normalized Lot: %.2f", raw_next_lot, normalized_next_lot);
      PrintFormat("Grid Entry: %.2f | Direction: %s", grid_entry_price, EnumToString(type));
      PrintFormat("Total Basket Lots (After): %.2f | Basket Positions (After): %d",
                  total_basket_lots + normalized_next_lot, pos_count + 1);
      PrintFormat("Current Floating Profit: $%.2f | Basket Target Profit: $%.2f",
                  current_floating_profit, basket_target_profit);
      PrintFormat("---------------------------------------------------------------");
   }

   return normalized_next_lot;
}

double CalculateTheoreticalTPPrice(ENUM_POSITION_TYPE type, double new_entry_price, double candidate_lot, double k_profit)
{
   double sum_volume_price = candidate_lot * new_entry_price;
   double total_volume = candidate_lot;

   for(int i = PositionsTotal() - 1; i >= 0; i--)
   {
      if(m_position.SelectByIndex(i))
      {
         if(m_position.Symbol() == _Symbol && IsOurMagic(m_position.Magic()) &&
            m_position.PositionType() == type)
         {
            sum_volume_price += m_position.Volume() * m_position.PriceOpen

Показано первые 50% кода (символов: 25221)

Открыть по тарифу

Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.

Разовая покупка файла

На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.

Чтобы оформить заказ, введите email и перейдите к оплате.

Стоимость полного кода
2 522,10₽ ≈ $30.82