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

Gold Level Breakout Enhanced

gold level breakout.mq5

Похожие материалы по тегам

linear breakthrough strategy.pineTradingView · 2 общих теговgoldlevelbreakout 1.00 @simpleforextools.mq4MQL4 / MetaTrader 4 · 2 общих теговsmc+ict+indicators+scalping master.pineTradingView · 2 общих теговsmc & ict & indicators + scalping master(1)_5976621784668052077.pineTradingView · 2 общих тегов+++ wickpercentage_adjusted_alerts .mq5MQL5 / MetaTrader 5 · 1 общих тегов(v) volatility stop.mq4MQL4 / MetaTrader 4 · 1 общих тегов
Вы автор или правообладатель?

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

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

О программе

Gold Level Breakout Enhanced — это торговый советник для MetaTrader 5, ориентированный на скальпирование золотых фьючерсов с адаптивным восстановлением торговых уровней. Советник использует внутренние расчёты на основе SuperTrend, скользящей средней EMA и индикатора ADX для определения регистра тренда и структурных точек входа.

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

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

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

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

НастройкаОписание
Lots Базовый объём позиции в лотах для первого входа в сделку.
LotMultiplier Множитель для расчёта объёма восстановительных позиций. Каждый следующий лэйер умножается на это значение.
MinBarsBetween Минимальное количество баров между последовательными восстановительными входами в одну сторону.
MinDistancePoints Минимальное расстояние в пунктах между ценой входа и последней позицией для добавления восстановительного лэйера.
TrailingPoints Расстояние трейлинг-стопа в пунктах от текущей цены после активации.
TrailingArmPoints Расстояние в пунктах от точки входа, при котором активируется трейлинг-стоп.
TrailLockPercent Процент от начального движения цены, который фиксируется как минимальное расстояние стоп-лосса от точки входа при трейлинге.
MinTrailStepPoints Минимальный шаг в пунктах, на который может быть сдвинут уровень стоп-лосса при трейлинге.
Dist Расстояние в пунктах для расчёта прогнозных уровней входа — отступ от структурного экстремума.
STPeriod Период расчёта индикатора Average True Range (ATR), используемого в линии SuperTrend.
STMultiplier Множитель ATR для расчёта линии SuperTrend. Определяет чувствительность индикатора.
STBars Количество баров для расчёта структурных экстремумов и анализа SuperTrend.
Slippage Допустимое проскальгивание в пунктах при исполнении рыночных ордеров и закрытии позиций.
Magic Магический номер для идентификации позиций, ордеров и сделок, управляемых данным советником.
PanelShow Отображает или скрывает информационную панель со статистикой на графике.
PanelX Горизонтальная позиция (в пикселях от левого верхнего угла) панели статистики на графике.
PanelY Вертикальная позиция (в пикселях от левого верхнего угла) панели статистики на графике.
ForecastShow Отображает или скрывает прогнозную панель с информацией о потенциальном уровне входа на графике.
ForecastRefreshSec Интервал обновления прогнозного уровня на графике в секундах.
TimeFilter Включает или отключает фильтр торгового времени по часам сервера.
StartHour Начальный час торгового фильтра. При активном фильтре вход разрешён только начиная с этого часа.
EndHour Конечный час торгового фильтра. При активном фильтре вход разрешён только в интервале между StartHour и EndHour.
AdaptiveSession Включает адаптивную торговую сессию, при которой вход разрешён только в основной торговый период или при сильном дневном тренде (ADX выше порога).
CoreStartHour Начальный час основной торговой сессии в адаптивном режиме. Вход разрешён начиная с этого часа.
CoreEndHour Конечный час основной торговой сессии в адаптивном режиме. Вход разрешён, пока текущий час меньше этого значения.
ExtendedHoursADX Пороговое значение индекса ADX на дневном таймфрейме, при котором разрешён торговый вход за пределами основной сессии.
WeekendProtection Включает защиту от выходных: блокировку входа в выходные дни и принудительное закрытие всех позиций в пятницу после указанного часа.
FridayCloseHour Час, начиная с которого советник закрывает все позиции в пятницу для защиты от выходного разрыва.
SafetyGuard Включает или отключает защиту корзины — автоматическое закрытие всех позиций при превышении максимального убытка.
MaxBasketLoss Максимальный суммарный плавающий убыток в долларах по корзине позиций. При превышении все позиции закрываются.
SafetyCooldownBars Минимальное количество баров между обычными закрытиями по защите корзины.
HardStopCooldownBars Минимальное количество баров между принудительными закрытиями по стоп-лоссу (жёсткая защита).
HardStopLossUSDPerPosition Максимальный убыток в долларах США на одну позицию, при достижении которого позиция закрывается по стоп-лоссу.
TakeProfitUSDPerPosition Целевая прибыль в долларах США на одну позицию, при достижении которой позиция закрывается по тейку-профиту.
MacroEMAPeriod Период скользящей средней EMA на дневном таймфрейме, используемой для определения макро-направления тренда.
EntryLogic Логика формирования сигнала: вход при откате от экстремума, вход при прорыве тренда или комбинация обоих вариантов.
EntryExecution Режим исполнения входа: немедленный рыночный вход, вход при возврате к уровню (reclaim) или вход при касании уровня.
ReclaimPercent Процент диапазона от экстремума, на который цена должна вернуться для активации входа по reclaim.
ReclaimValidityBars Количество баров, в течение которых уровень reclaim остаётся действительным до отмены.
ReclaimBufferPoints Дополнительный отступ в пунктах при расчёте уровня возврата (reclaim) для входа.
EntryQuality Критерий качества бара для входа: только экстремальные бары, подтверждение тела свечи, расположие закрытия или полное подтверждение отклонением.
RejectionClosePercent Процент расположения закрытия свечи от диапазона бара, используемый как порог подтверждения качества сигнала.
MaxSignalRangeATRPercent Максимальный допустимый диапазон бара в процентах от ATR. Если диапазон превышает порог, сигнал отклоняется.
MaxSpreadPoints Максимально допустимый спред в пунктах. При превышении вход в сделку блокируется.
RecoveryRequiresMacro Если включено, восстановительный вход разрешён только при совпадении макро-направления тренда с направлением позиции.
EnableRecovery Включает или отключает режим восстановления (лэйеринг), при котором после первого входа добавляются дополнительные позиции того же направления.
RecoveryRequiresRejection Если включено, восстановительный вход требует дополнительного подтверждения качеством сигнала через полный rejection-тест.
RecoveryConfirmAfterSafetyBars Количество баров после последнего закрытия по защите корзины, в течение которого восстановительный вход требует дополнительного подтверждения.
RecoveryBasketProfitUSD Целевой прибыльный баланс корзины в долларах. При достижении совокупной прибыли все позиции закрываются.
Получить полный код

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

#property strict
#property version   "1.80"
#property description "Gold level breakout Enhanced - MT5 adaptive level-recovery scalper"

#include <Trade/Trade.mqh>

enum ENUM_GLB_ENTRY_QUALITY
{
   GLB_EXTREME_ONLY = 0,
   GLB_BODY_CONFIRM = 1,
   GLB_CLOSE_LOCATION = 2,
   GLB_FULL_REJECTION = 3
};

enum ENUM_GLB_ENTRY_LOGIC
{
   GLB_PULLBACK_EXTREME = 0,
   GLB_TREND_BREAKOUT   = 1,
   GLB_BOTH_EXTREMES    = 2
};

enum ENUM_GLB_ENTRY_EXECUTION
{
   GLB_ENTER_IMMEDIATE = 0,
   GLB_ENTER_ON_RECLAIM = 1,
   GLB_ENTER_LEVEL_TOUCH = 2
};

input double Lots               = 0.03;
input double LotMultiplier      = 1.0;
input int    MinBarsBetween     = 2;
input int    MinDistancePoints  = 51;
input int    TrailingPoints     = 90;
input int    TrailingArmPoints  = 110;
input int    TrailLockPercent   = 75;
input int    MinTrailStepPoints = 5;
input int    Dist               = 33;
input int    STPeriod           = 11;
input double STMultiplier       = 9.0;
input int    STBars             = 20;
input int    Slippage           = 3000;
input long   Magic              = 778001;
input bool   PanelShow          = true;
input int    PanelX             = 20;
input int    PanelY             = 20;
input bool   ForecastShow       = true;
input int    ForecastRefreshSec = 300;
input bool   TimeFilter         = false;
input int    StartHour          = 9;
input int    EndHour            = 18;
input bool   AdaptiveSession    = true;
input int    CoreStartHour      = 7;
input int    CoreEndHour        = 18;
input int    ExtendedHoursADX   = 35;
input bool   WeekendProtection  = true;
input int    FridayCloseHour    = 22;
input bool   SafetyGuard        = true;
input double MaxBasketLoss      = 20.0;
input int    SafetyCooldownBars = 20;
input int    HardStopCooldownBars = 2;

input group "Hard stop-loss controls"
input double HardStopLossUSDPerPosition = 9.0;
input double TakeProfitUSDPerPosition    = 0.0;

input group "Enhanced quality controls"
input int    MacroEMAPeriod            = 20;
input ENUM_GLB_ENTRY_LOGIC EntryLogic  = GLB_PULLBACK_EXTREME;
input ENUM_GLB_ENTRY_EXECUTION EntryExecution = GLB_ENTER_IMMEDIATE;
input int    ReclaimPercent            = 50;
input int    ReclaimValidityBars       = 3;
input int    ReclaimBufferPoints       = 0;
input ENUM_GLB_ENTRY_QUALITY EntryQuality = GLB_EXTREME_ONLY;
input int    RejectionClosePercent     = 60;
input int    MaxSignalRangeATRPercent  = 0;
input int    MaxSpreadPoints           = 20;
input bool   RecoveryRequiresMacro     = true;
input bool   EnableRecovery            = true;
input bool   RecoveryRequiresRejection = false;
input int    RecoveryConfirmAfterSafetyBars = 288;
input double RecoveryBasketProfitUSD  = 5.0;

CTrade trade;
int g_atrHandle = INVALID_HANDLE;
int g_trendHandle = INVALID_HANDLE;
int g_dailyAdxHandle = INVALID_HANDLE;
ENUM_TIMEFRAMES g_signalTf = PERIOD_CURRENT;
datetime g_lastBarTime = 0;
datetime g_lastForecastRefresh = 0;
datetime g_lastSafetyExit = 0;
datetime g_lastHardStopExit = 0;
double g_buyLevel = 0.0;
double g_sellLevel = 0.0;
double g_stLine = 0.0;
int g_bias = 0;                 // +1 bullish ST regime / BUY support, -1 bearish ST regime / SELL resistance
int g_prevBias = 0;
bool g_touchArmed = true;
double g_prevAsk = 0.0;
double g_prevBid = 0.0;
int g_armedDirection = 0;
double g_armedTrigger = 0.0;
datetime g_armedAt = 0;
string PFX = "GLB_CR_";

struct DealStats
{
   int trades;
   int wins;
   int losses;
   double net;
   double grossProfit;
   double grossLoss;
   double profitFactor;
   double winRate;
   double avgTrade;
   double bestTrade;
   double worstTrade;
   double maxDrawdown;
};

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

void OnDeinit(const int reason)
{
   EventKillTimer();
   if(g_atrHandle != INVALID_HANDLE) IndicatorRelease(g_atrHandle);
   if(g_trendHandle != INVALID_HANDLE) IndicatorRelease(g_trendHandle);
   if(g_dailyAdxHandle != INVALID_HANDLE) IndicatorRelease(g_dailyAdxHandle);
   ObjectsDeleteAll(0, PFX);
}

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

void OnTimer()
{
   if(PanelShow || ForecastShow)
   {
      MqlTick tick;
      if(SymbolInfoTick(_Symbol, tick))
         UpdatePanel(tick);
   }
}

void OnTradeTransaction(const MqlTradeTransaction &trans,
                        const MqlTradeRequest &request,
                        const MqlTradeResult &result)
{
   if(trans.type != TRADE_TRANSACTION_DEAL_ADD || trans.deal == 0) return;
   if(!HistoryDealSelect(trans.deal)) return;
   if(HistoryDealGetString(trans.deal, DEAL_SYMBOL) != _Symbol) return;
   if((long)HistoryDealGetInteger(trans.deal, DEAL_MAGIC) != Magic) return;

   ENUM_DEAL_ENTRY entry = (ENUM_DEAL_ENTRY)HistoryDealGetInteger(trans.deal, DEAL_ENTRY);
   ENUM_DEAL_REASON reason = (ENUM_DEAL_REASON)HistoryDealGetInteger(trans.deal, DEAL_REASON);
   double net = HistoryDealGetDouble(trans.deal, DEAL_PROFIT)
              + HistoryDealGetDouble(trans.deal, DEAL_COMMISSION)
              + HistoryDealGetDouble(trans.deal, DEAL_SWAP);
   if((entry == DEAL_ENTRY_OUT || entry == DEAL_ENTRY_OUT_BY) &&
      reason == DEAL_REASON_SL && net < 0.0)
   {
      g_lastHardStopExit = iTime(_Symbol, g_signalTf, 0);
      g_armedDirection = 0;
      g_armedTrigger = 0.0;
      g_armedAt = 0;
   }
}

bool IsTradingTime()
{
   MqlDateTime tm;
   TimeToStruct(TimeCurrent(), tm); // broker/server time

   if(WeekendProtection)
   {
      if(tm.day_of_week == 0 || tm.day_of_week == 6) return false;
      if(tm.day_of_week == 5 && tm.hour >= MathMax(0, MathMin(23, FridayCloseHour)))
         return false;
   }

   if(AdaptiveSession)
   {
      int coreStart = MathMax(0, MathMin(23, CoreStartHour));
      int coreEnd = MathMax(0, MathMin(23, CoreEndHour));
      bool inCore = (coreStart == coreEnd
                     ? true
                     : coreStart < coreEnd
                       ? (tm.hour >= coreStart && tm.hour < coreEnd)
                       : (tm.hour >= coreStart || tm.hour < coreEnd));
      if(inCore) return true;
      return StrongDailyTrend();
   }

   if(!TimeFilter) return true;

   if(StartHour == EndHour) return true;
   if(StartHour < EndHour)
      return (tm.hour >= StartHour && tm.hour < EndHour);
   return (tm.hour >= StartHour || tm.hour < EndHour);
}

bool StrongDailyTrend()
{
   if(ExtendedHoursADX <= 0) return true;
   if(g_dailyAdxHandle == INVALID_HANDLE) return false;
   double adx[];
   ArrayResize(adx, 1);
   if(CopyBuffer(g_dailyAdxHandle, 0, 1, 1, adx) != 1) return false;
   return (adx[0] >= ExtendedHoursADX);
}

bool ManageWeekendProtection()
{
   if(!WeekendProtection) return false;

   MqlDateTime tm;
   TimeToStruct(TimeCurrent(), tm);
   int cutoff = MathMax(0, MathMin(23, FridayCloseHour));
   if(tm.day_of_week != 5 || tm.hour < cutoff) return false;

   bool attempted = false;
   for(int i=PositionsTotal()-1; i>=0; --i)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket == 0) continue;
      if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
      if((long)PositionGetInteger(POSITION_MAGIC) != Magic) continue;
      attempted = true;
      if(!trade.PositionClose(ticket, (ulong)Slippage))
         Print("Gold level weekend close failed: ", trade.ResultRetcode(),
               " ", trade.ResultRetcodeDescription());
   }

   if(attempted)
   {
      g_armedDirection = 0;
      g_armedTrigger = 0.0;
      g_armedAt = 0;
   }
   return attempted;
}

void ApplyVisualTheme()
{
   ChartSetInteger(0, CHART_COLOR_BACKGROUND, C'0,0,0');
   ChartSetInteger(0, CHART_COLOR_FOREGROUND, C'155,160,168');
   ChartSetInteger(0, CHART_COLOR_GRID, C'45,50,58');
   ChartSetInteger(0, CHART_COLOR_CHART_UP, C'30,255,60');
   ChartSetInteger(0, CHART_COLOR_CHART_DOWN, C'30,255,60');
   ChartSetInteger(0, CHART_COLOR_CANDLE_BULL, C'30,255,60');
   ChartSetInteger(0, CHART_COLOR_CANDLE_BEAR, C'30,255,60');
   ChartSetInteger(0, CHART_COLOR_BID, C'160,165,175');
   ChartSetInteger(0, CHART_SHOW_ASK_LINE, false);
   ChartSetInteger(0, CHART_SHOW_VOLUMES, CHART_VOLUME_HIDE);
   ChartRedraw(0);
}

void RefreshLevels(bool force)
{
   if(Bars(_Symbol, g_signalTf) < MathMax(STBars, STPeriod) + 20) return;

   double st=0.0;
   int trend=0;
   if(!CalculateSuperTrend(st, trend)) return;

   g_prevBias = g_bias;
   g_bias = MacroDirection();
   g_stLine = st;

   int lookback = MathMax(2, STBars);
   double pad = MathMax(0, Dist) * _Point;
   int lowShift = iLowest(_Symbol, g_signalTf, MODE_LOW, lookback, 1);
   int highShift = iHighest(_Symbol, g_signalTf, MODE_HIGH, lookback, 1);
   g_buyLevel = (lowShift >= 1
                 ? NormalizeDouble(iLow(_Symbol, g_signalTf, lowShift)-pad, _Digits)
                 : 0.0);
   g_sellLevel = (highShift >= 1
                  ? NormalizeDouble(iHigh(_Symbol, g_signalTf, highShift)+pad, _Digits)
                  : 0.0);

   if(g_prevBias != 0 && g_bias != g_prevBias)
      g_touchArmed = true;

   if(force || (TimeCurrent() - g_lastForecastRefresh >= ForecastRefreshSec))
   {
      g_lastForecastRefresh = TimeCurrent();
      DrawForecastLevel();
   }
}

int MacroDirection()
{
   if(g_trendHandle == INVALID_HANDLE) return +1;
   double ema[];
   ArrayResize(ema, 2);
   ArraySetAsSeries(ema, true);
   if(CopyBuffer(g_trendHandle, 0, 1, 2, ema) != 2) return +1;
   double closeMacro = iClose(_Symbol, PERIOD_D1, 1);
   if(closeMacro <= 0.0) return +1;
   return (closeMacro >= ema[0] ? +1 : -1);
}

bool CalculateSuperTrend(double &line, int &trend)
{
   int need = MathMax(80, MathMax(STBars + STPeriod + 20, STPeriod * 4));

   MqlRates rates[];
   double atr[];
   ArraySetAsSeries(rates, true);
   ArraySetAsSeries(atr, true);

   int got = CopyRates(_Symbol, g_signalTf, 0, need, rates);
   if(got < MathMax(STBars, STPeriod) + 5) return false;
   int gotAtr = CopyBuffer(g_atrHandle, 0, 0, got, atr);
   if(gotAtr < got) return false;

   double upper[], lower[], st[];
   ArrayResize(upper, got);
   ArrayResize(lower, got);
   ArrayResize(st, got);

   double mult = MathMax(0.10, STMultiplier);
   int oldest = got - 1;

   double hl2 = (rates[oldest].high + rates[oldest].low) * 0.5;
   double a0 = MathMax(atr[oldest], _Point);
   upper[oldest] = hl2 + mult * a0;
   lower[oldest] = hl2 - mult * a0;
   st[oldest] = (rates[oldest].close >= hl2 ? lower[oldest] : upper[oldest]);

   for(int i=oldest-1; i>=1; --i)
   {
      int p = i + 1;
      double mid = (rates[i].high + rates[i].low) * 0.5;
      double av = MathMax(atr[i], _Point);
      double basicUpper = mid + mult * av;
      double basicLower = mid - mult * av;

      upper[i] = (basicUpper < upper[p] || rates[p].close > upper[p])
                 ? basicUpper : upper[p];
      lower[i] = (basicLower > lower[p] || rates[p].close < lower[p])
                 ? basicLower : lower[p];

      bool prevWasUpper = (MathAbs(st[p] - upper[p]) <= MathAbs(st[p] - lower[p]));
      if(prevWasUpper)
         st[i] = (rates[i].close <= upper[i]) ? upper[i] : lower[i];
      else
         st[i] = (rates[i].close >= lower[i]) ? lower[i] : upper[i];
   }

   bool onLower = (MathAbs(st[1] - lower[1]) <= MathAbs(st[1] - upper[1]));
   trend = onLower ? +1 : -1;
   line = NormalizeDouble(st[1], _Digits);
   return (line > 0.0);
}

void HandleConfirmedTrendFlip()
{
   if(g_prevBias == 0 || g_bias == 0 || g_prevBias == g_bias) return;

   ENUM_POSITION_TYPE wrong = (g_bias > 0 ? POSITION_TYPE_SELL : POSITION_TYPE_BUY);
   ClosePositionsOfType(wrong);
}

void ClosePositionsOfType(ENUM_POSITION_TYPE type)
{
   for(int i=PositionsTotal()-1; i>=0; --i)
   {
      ulong ticket = PositionGetTicket(i);
      if(ticket == 0) continue;
      if(PositionGetString(POSITION_SYMBOL) != _Symbol) continue;
      if((long)PositionGetInteger(POSITION_MAGIC) != Magic) continue;
      if((ENUM_POSITION_TYPE)PositionGetInteger(POSITION_TYPE) != type) continue;

      if(!trade.PositionClose(ticket, (ulong)Slippage))
         Print("GLB CR flip-close failed: ", trade.ResultRetcode(), " ", trade.ResultRetcodeDescription());
   }
}

bool SignalQualityPass(int direction, bool forceRejection)
{

   if(!forceRejection && EntryQuality == GLB_EXTREME_ONLY &&
      MaxSignalRangeATRPercent <= 0)
      return true;

   MqlRates signal[1];
   if(CopyRates(_Symbol, g_signalTf, 1, 1, signal) != 1) return false;

   double range = signal[0].high - signal[0].low;
   if(range <= _Point) return false;

   if(MaxSignalRangeATRPercent > 0)
   {
      double atr[1];
      if(CopyBuffer(g_atrHandle, 0, 1, 1, atr) != 1) return false;
      if(atr[0] <= _Point) return false;
      if(range * 100.0 > atr[0] * MaxSignalRangeATRPercent)
         return false;
   }

   bool bodyConfirm = (direction > 0
                       ? signal[0].close > signal[0].open
                       : signal[0].close < signal[0].open);
   double closeLocation = 100.0 * (signal[0].close - signal[0].low) / range;
   int threshold = MathMax(50, MathMin(95, RejectionClosePercent));
   bool locationConfirm = (direction > 0
                           ? closeLocation >= threshold
                           : closeLocation <= 100 - threshold);

   if(forceRejection)
      return bodyConfirm && locationConfirm;

   if(EntryQuality == GLB_BODY_CONFIRM) return bodyConfirm;
   if(EntryQuality == GLB_CLOSE_LOCATION) return locationConfirm;
   if(EntryQuality == GLB_FULL_REJECTION) return bodyConfirm && locationConfirm;
   return true;
}

void ProcessEntries(const MqlTick &tick, bool newBar)
{
   int buys=0, sells=0;
   double lastBuy=0.0, lastSell=0.0;
   datetime lastBuyTime=0, lastSellTime=0;
   GetOpenState(buys, sells, lastBuy, lastSell, lastBuyTime, lastSellTime);

   if(buys > 0 && sells > 0) return;

   if(MaxSpreadPoints > 0)
   {
      double spreadPoints = (tick.ask - tick.bid) / _Point;
      if(spreadPoints > MaxSpreadPoints) return;
   }

   if(g_lastSafetyExit > 0 &&
      BarsSince(g_lastSafetyExit) < MathMax(1, SafetyCooldownBars))
      return;
   if(g_lastHardStopExit > 0 &&
      BarsSince(g_lastHardStopExit) < MathMax(0, HardStopCooldownBars))
      return;

   if(buys == 0 && sells == 0)
   {

      if(EntryExecution == GLB_ENTER_LEVEL_TOUCH)
      {
         if(newBar)
         {
            if(g_bias >= 0 && g_buyLevel > 0.0 && tick.ask > g_buyLevel)
               g_touchArmed = true;
            else if(g_bias < 0 && g_sellLevel > 0.0 && tick.bid < g_sellLevel)
               g_touchArmed = true;
         }

         if(g_touchArmed)
         {
            if(g_bias >= 0 && g_buyLevel > 0.0 && tick.ask <= g_buyLevel)
            {
               g_touchArmed = false;
               OpenMarket(ORDER_TYPE_BUY, Lots, "Gold level touch buy");
            }
            else if(g_bias < 0 && g_sellLevel > 0.0 && tick.bid >= g_sellLevel)
            {
               g_touchArmed = false;
               OpenMarket(ORDER_TYPE_SELL, Lots, "Gold level touch sell");
            }
         }
         return;
      }

      if(EntryExecution == GLB_ENTER_ON_RECLAIM && g_armedDirection != 0)
      {
         bool expired = (BarsSince(g_armedAt) > MathMax(1, ReclaimValidityBars));
         bool invalidBias = (g_armedDirection > 0 ? g_bias < 0 : g_bias > 0);
         if(expired || invalidBias)
         {
            g_armedDirection = 0;
            g_armedTrigger = 0.0;
            g_armedAt = 0;
         }
         else
         {
            bool crossed = (g_armedDirection > 0
                            ? tick.ask >= g_armedTrigger
                            : tick.bid <= g_armedTrigger);
            if(crossed)
            {
               int direction = g_armedDirection;
               g_armedDirection = 0;
               g_armedTrigger = 0.0;
               g_armedAt = 0;
               OpenMarket(direction > 0 ? ORDER_TYPE_BUY : ORDER_TYPE_SELL,
                          Lots, direction > 0 ? "Gold reclaim buy" : "Gold reclaim sell");
               return;
            }
         }
      }

      if(!newBar) return;

      int lookback = MathMax(2, STBars);
      if(g_bias >= 0)
      {
         double signalLow = iLow(_Symbol, g_signalTf, 1);
         double signalHigh = iHigh(_Symbol, g_signalTf, 1);
         int lowShift = iLowest(_Symbol, g_signalTf, MODE_LOW, lookback, 2);
         int highShift = iHighest(_Symbol, g_signalTf, MODE_HIGH, lookback, 2);
         double olderLow = (lowShift >= 2 ? iLow(_Symbol, g_signalTf, lowShift) : 0.0);
         double olderHigh = (highShift >= 2 ? iHigh(_Symbol, g_signalTf, highShift) : 0.0);
         bool pullback = (signalLow > 0.0 && olderLow > 0.0 && signalLow <= olderLow);
         bool breakout = (signalHigh > 0.0 && olderHigh > 0.0 && signalHigh >= olderHigh);
         bool triggered = (EntryLogic == GLB_PULLBACK_EXTREME ? pullback
                           : EntryLogic == GLB_TREND_BREAKOUT ? breakout
                           : pullback || breakout);
         if(triggered && SignalQualityPass(+1, false))
         {
            if(EntryExecution == GLB_ENTER_IMMEDIATE)
               OpenMarket(ORDER_TYPE_BUY, Lots, "Gold level buy");
            else if(EntryExecution == GLB_ENTER_ON_RECLAIM)
               ArmReclaim(+1, signalLow, signalHigh);
         }
      }
      else
      {
         double signalLow = iLow(_Symbol, g_signalTf, 1);
         double signalHigh = iHigh(_Symbol, g_signalTf, 1);
         int lowShift = iLowest(_Symbol, g_signalTf, MODE_LOW, lookback, 2);
         int highShift = iHighest(_Symbol, g_signalTf, MODE_HIGH, lookback, 2);
         double olderLow = (lowShift >= 2 ? iLow(_Symbol, g_signalTf, lowShift) : 0.0);
         double olderHigh = (highShift >= 2 ? iHigh(_Symbol, g_signalTf, highShift) : 0.0);
         bool breakout = (signalLow > 0.0 && olderLow > 0.0 && signalLow <= olderLow);
         bool pullback = (signalHigh > 0.0 && olderHigh > 0.0 && signalHigh >= olderHigh);
         bool triggered = (EntryLogic == GLB_PULLBACK_EXTREME ? pullback
                           : EntryLogic == GLB_TREND_BREAKOUT ? breakout
                           : pullback || breakout);
         if(triggered && SignalQualityPass(-1, false))
         {
            if(EntryExecution == GLB_ENTER_IMMEDIATE)
               OpenMarket(ORDER_TYPE_SELL, Lots, "Gold level sell");
            else if(EntryExecution == GLB_ENTER_ON_RECLAIM)
               ArmReclaim(-1, signalLow, signalHigh);
         }
      }
      return;
   }

   if(!newBar) return;
   if(!EnableRecovery) return;

   if(buys == 1)
   {
      if(RecoveryRequiresMacro && g_bias < 0) return;
      bool confirmRecovery = RecoveryRequiresRejection ||
         (RecoveryConfirmAfterSafetyBars > 0 && g_lastSafetyExit > 0 &&
          BarsSince(g_lastSafetyExit) < RecoveryConfirmAfterSafetyBars);
      if(confirmRecovery && !SignalQualityPass(+1, true)) return;
      if(BarsSince(lastBuyTime) >= MathMax(0, MinBarsBetween) &&
         tick.ask <= lastBuy - MathMax(1, MinDistancePoints) * _Point)
      {
         double v = Lots * MathPow(MathMax(LotMultiplier, 0.01), buys);
         OpenMarket(ORDER_TYPE_BUY, v, "GLB buy layer");
      }
   }
   else if(sells == 1)
   {
      if(RecoveryRequiresMacro && g_bias > 0) return;
      bool confirmRecovery = RecoveryRequiresRejection ||
         (RecoveryConfirmAfterSafet

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

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

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

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

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

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

Стоимость полного кода
3 297,20₽ ≈ $40.24