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

HedgeCycleEA v7

hedge combo.mq5
Вы автор или правообладатель?

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

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

О программе

HedgeCycleEA v7 — торговый советник для MetaTrader 5, работающий по стратегии хеджирования. Он открывает парные позиции BUY и SELL на одном символе, ожидает достижения заданного ценового движения в пунктах, затем определяет прибыльное направление и управляет циклами сделок. Советник использует конечный автомат с четырьмя состояниями: ожидание, мониторинг, закрытие и простой.

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

Советник отображает информационную панель с 20 строками, показывающую текущее состояние, открытые позиции, плавающую прибыль, целевые значения, дневной P&L, просадку и баланс. Все торговые операции выполняются через стандартные классы CTrade и CPositionInfo платформы MetaTrader 5.

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

НастройкаОписание
LotSize Размер лота для каждой открытой позиции в паре BUY/SELL.
Slippage Допустимое отклонение цены исполнения в пунктах при открытии и закрытии позиций.
MaxSpreadPoints Допустимое значение спреда в пунктах. При превышении советник не открывает новые позиции.
MagicBase Базовое число магического идентификатора для присвоения открытым позициям.
WaitPips Количество пунктов ценового движения, которое необходимо набрать перед первой оценкой и принятием решения по циклу.
FirstTargetUSD Целевая чистая прибыль в долларах после достижения ценового движения в WaitPips. При достижении запускается закрытие.
RecoveryExtraUSD Дополнительная величина сверх заблокированного убытка, формирующая целевой порог восстановления в долларах.
MaxCycles Максимальное количество торговых циклов до принудительного закрытия всех позиций.
EmergencyLossPips Максимальное допустимое движение цены в пунктах от цены входа. При превышении происходит аварийное закрытие всех позиций.
UseRoundCap Переключатель ограничения убытка по циклу. При активации при достижении убытка MaxRoundLossUSD текущий цикл закрывается.
MaxRoundLossUSD Максимальный убыток по текущему циклу в долларах. При превышении запускается закрытие цикла.
UseFloatLock Переключатель механизма фиксации плавающей прибыли. При активации советник отслеживает пик прибыли и закрывает позиции при заданном падении.
FloatLockMinUSD Минимальный пик плавающей прибыли в долларах, при котором активируется механизм фиксации прибыли.
FloatLockDropUSD Допустимое снижение плавающей прибыли от пика в долларах. При падении плавающей прибыли ниже пика на эту величину происходит закрытие для защиты.
UseHWM Переключатель контроля максимальной просадки от исторического пика капитала (High Water Mark). При превышении заданного процента советник приостанавливается.
MaxDDFromPeakPct Максимальная просадка капитала от пика в процентах. При превышении советник приостанавливается.
UseDailyLimit Переключатель дневного лимита убытка. При активации контролируется дневной P&L и при превышении лимита советник приостанавливается.
DailyLossLimitUSD Дневной лимит убытка в долларах. При превышении убытка за торговый день советник приостанавливается до следующего дня.
MonitorDuringPause Переключатель мониторинга плавающей прибыли во время паузы. При активации советник продолжает проверять плавающий P&L и закрывает позиции при достижении целевого значения.
PauseFloatTargetUSD Целевое значение плавающей прибыли в долларах для закрытия позиций при паузе, если до этого целевой порог ещё не был установлен.
ShowPanel Переключатель отображения информационной панели на графике.
PanelX Горизонтальная позиция панели на графике в пикселях от левого верхнего угла.
PanelY Вертикальная позиция панели на графике в пикселях от левого верхнего угла.
Получить полный код

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

#property version   "7.00"
#property strict

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

input group "=== Trade ==="
input double   LotSize            = 0.11;
input int      Slippage           = 50;
input double   MaxSpreadPoints    = 30.0;
input int      MagicBase          = 90000;

input group "=== 40-Pip Rule ==="
input double   WaitPips           = 40.0;

input group "=== Profit Targets ==="
input double   FirstTargetUSD     = 15.0;
input double   RecoveryExtraUSD   = 15.0;

input group "=== Hard Limits ==="
input int      MaxCycles          = 4;
input double   EmergencyLossPips  = 200.0;

input group "=== Round Loss Cap ==="
input bool     UseRoundCap        = true;
input double   MaxRoundLossUSD    = 45.0;

input group "=== Float Profit Lock ==="
input bool     UseFloatLock       = true;
input double   FloatLockMinUSD    = 5.0;
input double   FloatLockDropUSD   = 3.0;

input group "=== Account Protection ==="
input bool     UseHWM             = true;
input double   MaxDDFromPeakPct   = 10.0;
input bool     UseDailyLimit      = true;
input double   DailyLossLimitUSD  = 30.0;

input group "=== Pause Float Monitor ==="
input bool     MonitorDuringPause   = true;

input double   PauseFloatTargetUSD  = 10.0;

input group "=== Panel ==="
input bool     ShowPanel          = true;
input int      PanelX             = 10;
input int      PanelY             = 30;

enum EState
{
   S_IDLE    = 0,
   S_WAITING = 1,
   S_MONITOR = 2,
   S_CLOSING = 3,
};

struct SCycle
{
   int    magicBuy;
   int    magicSell;
   int    winnerMagic;
   double lossLocked;
   bool   decided;
};

CTrade        g_trade;
CPositionInfo g_pos;

EState  g_state         = S_IDLE;
double  g_startPrice    = 0.0;
double  g_highPrice     = 0.0;
double  g_lowPrice      = 0.0;
double  g_totalLocked   = 0.0;
int     g_cycleCount    = 0;
double  g_roundStartBal = 0.0;
int     g_rounds        = 0;
double  g_totalProfit   = 0.0;
bool    g_firstRun      = true;

SCycle  g_cycles[];

double   g_initialBalance  = 0.0;
double   g_floatPeak       = 0.0;
double   g_highWaterMark   = 0.0;
double   g_dayStartBalance = 0.0;
datetime g_lastDayReset    = 0;
bool     g_paused          = false;
string   g_pauseReason     = "";

string  g_status        = "Starting...";
#define PN "HC7_"
#define PANEL_ROWS 20

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

void OnDeinit(const int reason)
{
   for(int i = ObjectsTotal(0,0,-1)-1; i >= 0; i--)
   {
      string name = ObjectName(0,i,0,-1);
      if(StringFind(name,PN) == 0) ObjectDelete(0,name);
   }
}

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

void HandleIdle()
{
   if(HasAnyPosition()) { CloseAllOurs(); return; }

   ArrayResize(g_cycles, 0);
   g_totalLocked   = 0.0;
   g_cycleCount    = 0;
   g_roundStartBal = AccountInfoDouble(ACCOUNT_BALANCE);
   g_floatPeak     = 0.0;

   if(!OpenNewCycle()) return;

   g_startPrice = MidPrice();
   g_highPrice  = g_startPrice;
   g_lowPrice   = g_startPrice;
   g_state      = S_WAITING;
   g_rounds++;

   g_status = StringFormat("Round #%d opened | Entry=%.5f | Waiting %.0f pips...",
                            g_rounds, g_startPrice, WaitPips);
   Print("v7: Round #", g_rounds, " opened. Entry=", g_startPrice);
}

void HandleWaiting()
{
   double mid = MidPrice();
   if(mid > g_highPrice) g_highPrice = mid;
   if(mid < g_lowPrice)  g_lowPrice  = mid;

   double pip       = GetPipSize();
   double rangeUp   = (g_highPrice - g_startPrice) / pip;
   double rangeDn   = (g_startPrice - g_lowPrice)  / pip;
   double pipsMoved = MathMax(rangeUp, rangeDn);

   if(pipsMoved < WaitPips)
   {
      double buyPnl  = SidePnl(g_cycles[0].magicBuy);
      double sellPnl = SidePnl(g_cycles[0].magicSell);
      g_status = StringFormat("WAITING %.1f/%.0f pips | BUY=%+.2f SELL=%+.2f Net=%+.2f",
                               pipsMoved, WaitPips, buyPnl, sellPnl, buyPnl + sellPnl);
      return;
   }

   double buyPnl  = SidePnl(g_cycles[0].magicBuy);
   double sellPnl = SidePnl(g_cycles[0].magicSell);
   double netPnl  = buyPnl + sellPnl;

   Print("v7: 40 pips (", DoubleToString(pipsMoved,1), "). BUY=", buyPnl,
         " SELL=", sellPnl, " Net=", netPnl);

   if(netPnl >= FirstTargetUSD)
   {
      g_status = StringFormat("40-pip TARGET HIT! Net=%.2f >= $%.0f. Closing.", netPnl, FirstTargetUSD);
      Print("v7: First target hit. Closing all.");
      g_state = S_CLOSING;
      return;
   }

   if(g_cycleCount >= MaxCycles)
   {
      g_status = StringFormat("MAX %d CYCLES at first decision. Closing all.", MaxCycles);
      Print("v7: Max cycles at first decision. Closing.");
      g_state = S_CLOSING;
      return;
   }

   int    winnerMagic, loserMagic;
   double winnerPnl,   loserPnl;

   if(buyPnl >= sellPnl)
   {
      winnerMagic = g_cycles[0].magicBuy;  winnerPnl = buyPnl;
      loserMagic  = g_cycles[0].magicSell; loserPnl  = sellPnl;
   }
   else
   {
      winnerMagic = g_cycles[0].magicSell; winnerPnl = sellPnl;
      loserMagic  = g_cycles[0].magicBuy;  loserPnl  = buyPnl;
   }

   double lossAmt = MathAbs(loserPnl);
   g_totalLocked += lossAmt;

   g_cycles[0].winnerMagic = winnerMagic;
   g_cycles[0].decided     = true;

   Print("v7: Closing loser ", MagicLabel(loserMagic), " P&L=", loserPnl,
         " | Keeping ", MagicLabel(winnerMagic), " | TotalLocked=", g_totalLocked);

   CloseByMagic(loserMagic);

   if(!OpenNewCycle())
   {
      g_status = "New cycle open FAILED. Closing all.";
      g_state  = S_CLOSING;
      return;
   }

   g_state  = S_MONITOR;
   g_status = StringFormat("Loser closed (-%.2f). Winner kept (+%.2f). Cycle %d/%d.",
                            lossAmt, winnerPnl, g_cycleCount, MaxCycles);
}

void HandleMonitor()
{
   double totalPnl = TotalAllFloatingPnl();
   double target   = g_totalLocked + RecoveryExtraUSD;

   if(UseFloatLock)
   {
      if(totalPnl > g_floatPeak) g_floatPeak = totalPnl;

      if(g_floatPeak >= FloatLockMinUSD &&
         totalPnl    <= g_floatPeak - FloatLockDropUSD)
      {
         g_status = StringFormat(
            "FLOAT LOCK: peak=%.2f now=%.2f dropped %.2f. Closing to protect.",
            g_floatPeak, totalPnl, g_floatPeak - totalPnl);
         Print("v7: ", g_status);
         g_state = S_CLOSING;
         return;
      }
   }

   if(totalPnl >= target)
   {
      Print("v7: MONITOR target hit! TotalPnl=", totalPnl, " Target=", target);
      g_status = StringFormat("RECOVERY HIT! P&L=%.2f >= %.2f. Closing ALL!", totalPnl, target);
      g_state  = S_CLOSING;
      return;
   }

   double worstPnl   = -RecoveryExtraUSD;
   int    worstMagic = 0;

   for(int i = PositionsTotal()-1; i >= 0; i--)
   {
      if(!g_pos.SelectByIndex(i))              continue;
      if(g_pos.Symbol() != _Symbol)             continue;
      if(!IsOurMagic((int)g_pos.Magic()))       continue;

      double p = g_pos.Profit() + g_pos.Swap();
      if(p < worstPnl)
      {
         worstPnl   = p;
         worstMagic = (int)g_pos.Magic();
      }
   }

   if(worstMagic != 0 && totalPnl < 0.0)
   {
      if(g_cycleCount < MaxCycles)
      {
         double lossAmt = MathAbs(worstPnl);
         g_totalLocked += lossAmt;

         Print("v7: Monitor re-eval. Closing worst leg ", MagicLabel(worstMagic),
               " P&L=", worstPnl,
               " | NewLocked=", g_totalLocked,
               " | NewTarget=", g_totalLocked + RecoveryExtraUSD);

         CloseByMagic(worstMagic);

         if(!OpenNewCycle())
         {
            g_status = "Monitor recovery open FAILED. Closing all.";
            g_state  = S_CLOSING;
            return;
         }

         g_status = StringFormat("Monitor: closed worst (%.2f). New pair open. Cycle %d/%d. Target=%.2f",
                                  worstPnl, g_cycleCount, MaxCycles,
                                  g_totalLocked + RecoveryExtraUSD);
         return;
      }
      else
      {
         g_status = StringFormat("MAX %d CYCLES in monitor. Closing all.", MaxCycles);
         Print("v7: Max cycles in monitor. Closing.");
         g_state = S_CLOSING;
         return;
      }
   }

   string allStr = "";
   for(int i = 0; i < ArraySize(g_cycles); i++)
   {
      if(g_cycles[i].decided)
      {
         if(SideHasPos(g_cycles[i].winnerMagic))
            allStr += StringFormat("C%dW=%+.1f ", i+1, SidePnl(g_cycles[i].winnerMagic));
      }
      else
      {
         if(SideHasPos(g_cycles[i].magicBuy))
            allStr += StringFormat("C%dB=%+.1f ", i+1, SidePnl(g_cycles[i].magicBuy));
         if(SideHasPo

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

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

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

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

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

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

Стоимость полного кода
1 930,50₽ ≈ $23.60