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

DynamicSR4

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

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

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

О программе

DynamicSR4 — торговый советник для MetaTrader 5, реализующий систему автоматического отслеживания зон поддержки и сопротивления. Программа анализирует ценовые данные, выявляет симметричные структурные пивоты и назначает количественные оценки зон на основе объёма, скорости ухода цены и геометрической симметрии.

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

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

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

НастройкаОписание
Proximity alert aura distance in pips (ApproachPips) Приближение в пипсах — Расстояние зоны оповещения о приближении цены в пипсах
Historical structural scanning depth (LookbackBars) Бары обзора — Глубина исторического сканирования структур
Symmetrical bars required for structural pivot (SwingBars) Бары симметрии — Количество симметричных баров, необходимых для структурного пивота
Proximity threshold multiplier for merging zones (MergeSensitivity) Чувствительность слияния — Множитель порога близости для слияния зон
Percentage of zone height required for breakout penetration (BreakBufferPct) Процент буфера пробоя — Процент высоты зоны, необходимый для проникновения при пробое
Number of consecutive candle closes required to confirm breakout (BreakConfirmCloses) Подтверждение пробоя свечами — Количество последовательных закрытий свечей для подтверждения пробоя
Lifetime limit in bars for broken hollow zones (GhostBarLimit) Лимит призрачных баров — Максимальное количество баров жизни призрачной зоны после пробоя
Re-activate ghost zones if price closes back inside range (AllowResurrection) Разрешить восстановление — Восстановление призрачных зон, если цена закрывается обратно внутри диапазона
Minimum mathematical score (0-100) required to track zone (MinZoneScore) Минимальная оценка зоны — Минимальная оценка зоны от 0 до 100 для отслеживания
Enable/disable tick-volume relationship checks (EnableVolumeValidation) Валидация объёма — Включение или отключение проверок соотношения объёмов
Max points allocated to institutional volume (Default: 30) (VolumeWeight) Вес объёма — Максимальное количество очков, выделяемых институциональному объёму
Max points allocated to escape velocity (Default: 40) (VelocityWeight) Вес скорости — Максимальное количество очков, выделяемых скорости ухода цены
Max points allocated to geometric symmetry (Default: 30) (StructureWeight) Вес структуры — Максимальное количество очков, выделяемых геометрической симметрии
Bar count lookahead window for departure calculation (VelocityLookaheadBars) Бары опережения скорости — Количество баров окна опережения для расчёта скорости ухода
Enable score degradation over time (EnableTemporalDecay) Временное угасание — Включение постепенного снижения оценки зоны с течением времени
Score reduction unit per bar age (DecayRatePerBar) Ставка угасания на бар — Величина снижения очка оценки на каждый бар при активном временном угасании
Score increase awarded for clean rejections (TouchScoreBonus) Бонус за касание — Прирост оценки за чистое отталкивание от зоны
Score reduction unit for deep structural test drillings (PenetrationPenalty) Штраф за проникновение — Величина снижения оценки при глубоком тестировании зоны
Bars Away Required for Confirmation (BounceConfirmCloses) Подтверждение отскока свечами — Количество последовательных закрытий свечей для подтверждения отскока
ATR Multiplier Filter for Movement Away (BounceATRDistance) ATR-расстояние отскока — Множитель ATR для фильтрации подтверждённого отталкивания от зоны
Max Bars Allowed to Remain Pending (BounceTimeoutBars) Таймаут отскока в барах — Максимальное количество баров ожидания для незавершённого отскока
Enable automated execution signals (CheckTradingSignals) Проверка торговых сигналов — Включение автоматической генерации торговых сигналов
EA Magic Number (MagicNumber) Магический номер — Магический номер советника для идентификации ордеров
Lot size (LotSize) Размер лота — Размер лота для торговых операций
Maximum tolerated slippage / spread points (MaxSpreadPoints) Максимальный спред — Максимально допустимые проскальзывание и спред в пунктах
Strategy mathematical target multiplier (RiskRewardRatio) Соотношение риск/прибыль — Математический множитель целевого соотношения риск/прибыль стратегии
Structural volatility invalidation cushion (ATRBufferMultiplier) Множитель ATR-буфера — Коэффициент волатильности для определения уровня структурной недействительности
Enable real-time profit preservation (UseTrailingStop) Использовать трейлинг-стоп — Включение трейлинг-стопа для сохранения текущей прибыли
Minimum pips gained to activate trailing layer (TrailingStartPips) Старт трейлинга в пипсах — Минимальное количество пипсов прибыли для активации трейлинг-стопа
Trailing step distance adjustments (TrailingStepPips) Шаг трейлинга — Шаговая величина перестановки трейлинг-стопа
Enable Higher Timeframe Trend Filter (InpUseHTFFilter) Использовать HTF тренд — Включение фильтра тренда старшего таймфрейма
HTF Trend Timeframe (InpHtfTimeframe) Таймфрейм HTF — Таймфрейм для трендового фильтра старшего таймфрейма
HTF Trend EMA Period (InpHtfMaPeriod) Период EMA HTF — Период EMA трендового фильтра старшего таймфрейма
Enable HTF RSI Exhaustion Filter (InpUseHTFRsiFilter) Использовать HTF RSI — Включение фильтра RSI старшего таймфрейма
HTF RSI Period (InpHtfRsiPeriod) Период RSI HTF — Период RSI фильтра старшего таймфрейма
HTF RSI Overbought Threshold (InpHtfRsiOverbought) Перекупленность RSI HTF — Порог перекупленности RSI старшего таймфрейма
HTF RSI Oversold Threshold (InpHtfRsiOversold) Перепроданность RSI HTF — Перепроданность RSI старшего таймфрейма
Bars Evaluated Before Touch (1-5) (InpApproachBars) Бары подхода — Количество баров для оценки перед касанием зоны
Aggressive Sprint Threshold (ATR Mult) (InpApproachThreshold) Порог подхода — Порог агрессивного спринта в кратных ATR
Получить полный код

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

#property version   "1.2"

#include <Arrays\ArrayObj.mqh>
#include <Arrays\ArrayString.mqh>
#include <Trade\Trade.mqh>
#include <DynamicSR4\MasterLog2.mqh>
#include <DynamicSR4\TradeManager.mqh>
#include <DynamicSR4\ZoneStrategy.mqh>
CLogger logger;

enum ENUM_ZONE_TYPE
  {
   ZONE_SUPPORT,
   ZONE_RESISTANCE,
   ZONE_NEUTRAL
  };

enum ENUM_ZONE_STATUS
  {
   ZONE_VIRGIN,
   ZONE_BROKEN,
   ZONE_INACTIVE
  };

enum ENUM_ZONE_SOURCE
  {
   ZS_USER,
   ZS_EA
  };

input group "--- Core Engine Settings ---"
input int      ApproachPips        = 10;    // Proximity alert aura distance in pips
input int      LookbackBars        = 300;   // Historical structural scanning depth
input int      SwingBars           = 5;     // Symmetrical bars required for structural pivot
input double   MergeSensitivity    = 1.5;   // Proximity threshold multiplier for merging zones

input group "--- Breakout & Ghost State Settings ---"
input double   BreakBufferPct      = 0.10;  // Percentage of zone height required for breakout penetration
input int      BreakConfirmCloses  = 4;     // Number of consecutive candle closes required to confirm breakout
input int      GhostBarLimit       = 10;    // Lifetime limit in bars for broken hollow zones
input bool     AllowResurrection   = true;  // Re-activate ghost zones if price closes back inside range

input group "--- Part 3 Quantitative Scoring Matrix ---"
input int      MinZoneScore        = 50;      // Minimum mathematical score (0-100) required to track zone
input bool     EnableVolumeValidation = true; // Enable/disable tick-volume relationship checks
input int      VolumeWeight        = 30;      // Max points allocated to institutional volume (Default: 30)
input int      VelocityWeight      = 40;      // Max points allocated to escape velocity (Default: 40)
input int      StructureWeight     = 30;      // Max points allocated to geometric symmetry (Default: 30)
input int      VelocityLookaheadBars = 3;     // Bar count lookahead window for departure calculation

input group "--- Part 3 Live Zone Evolution Tracking ---"
input bool     EnableTemporalDecay = false;    // Enable score degradation over time
input double   DecayRatePerBar     = 0.05;     // Score reduction unit per bar age
input double   TouchScoreBonus     = 5.0;      // Score increase awarded for clean rejections
input double   PenetrationPenalty  = 5.0;      // Score reduction unit for deep structural test drillings

input group "--- Symmetrical Bounce Settings ---"
input int      BounceConfirmCloses = 7;       // Bars Away Required for Confirmation
input double   BounceATRDistance   = 0.5;     // ATR Multiplier Filter for Movement Away
input int      BounceTimeoutBars   = 5;       // Max Bars Allowed to Remain Pending

input group "--- Part IV Automation Framework Switches ---"
input bool     CheckTradingSignals   = true;        // Enable automated execution signals
input ulong    MagicNumber           = 123456;      // EA Magic Number
input double   LotSize               = 0.10;        // Lot size

input group "--- Risk & Spread Protection ---"
input int      MaxSpreadPoints       = 30;          // Maximum tolerated slippage / spread points
input double   RiskRewardRatio       = 2.0;         // Strategy mathematical target multiplier
input double   ATRBufferMultiplier   = 1.5;         // Structural volatility invalidation cushion

input group "--- Trailing Stop Settings ---"
input bool     UseTrailingStop       = true;        // Enable real-time profit preservation
input double   TrailingStartPips     = 15.0;        // Minimum pips gained to activate trailing layer
input double   TrailingStepPips      = 5.0;         // Trailing step distance adjustments

input group "--- HTF Trend Filter Parameters ---"
input bool            InpUseHTFFilter       = true;       // Enable Higher Timeframe Trend Filter
input ENUM_TIMEFRAMES InpHtfTimeframe       = PERIOD_H1;  // HTF Trend Timeframe
input int             InpHtfMaPeriod        = 50;         // HTF Trend EMA Period
input bool            InpUseHTFRsiFilter    = true;       // Enable HTF RSI Exhaustion Filter
input int             InpHtfRsiPeriod       = 14;         // HTF RSI Period
input double          InpHtfRsiOverbought   = 70.0;       // HTF RSI Overbought Threshold
input double          InpHtfRsiOversold     = 30.0;       // HTF RSI Oversold Threshold

input group "--- Approach Context Parameters"
input int             InpApproachBars     = 3;           // Bars Evaluated Before Touch (1-5)
input double          InpApproachThreshold = 1.5;        // Aggressive Sprint Threshold (ATR Mult)

CArrayObj      active_zones;                         // Active structural supply and demand tracking arrays
CArrayString   blacklist;                            // Blacklisted names of manually deleted automated zones
datetime       last_bar_time       = 0;              // Track bar time shifts to execute periodic functions
int            atr_handle          = INVALID_HANDLE; // Core handle for structural ATR calculation
double         g_cached_atr        = 0.0;            // Global structural volatility cache

CTradeManager *g_trade             = NULL;           // Decoupled institutional transaction routing engine
CZoneStrategy *g_strategy          = NULL;           // Analytical price action validation strategy module

class CZone : public CObject
  {
public:
   string              name;                        // Unique chart object identifier
   double              price_level;                 // Median reference price of the structure
   double              top;                         // Upper boundary ceiling price
   double              bottom;                      // Lower boundary floor price
   double              height;                      // Absolute distance within the zone range

   bool                is_broken;                   // Flag indicating the zone has been penetrated
   datetime            broken_time;                 // Exact timestamp when breakout confirmation occurred
   int                 consecutive_closes_outside;  // Counter for closing candles beyond boundaries

   bool              is_pending;                     // True if an interaction is underway but unresolved
   int               consecutive_rejection_closes;
   bool              was_recently_moved;

   ENUM_ZONE_TYPE     type;                          // Structural classification (Support/Resistance)
   ENUM_ZONE_STATUS  status;                         // Operational state tracking (Virgin/Broken/Inactive)
   bool              is_user_zone;                   // Identifies if manually drawn or auto-generated
   bool              was_drawn;                      // Confirmed visual presence on active chart
   datetime          created;                        // Original generation timestamp
   datetime          last_touch_time;                // Last recorded price test interaction

   bool              buy_triggered;                  // Internal signal flag for support interaction
   bool              sell_triggered;                 // Internal signal flag for resistance interaction
   double            strength;                       // Structural weight ranking score

   int                zone_score;                    // Final calculated evaluation score (0 - 100)
   double             Current_zone_score;            // Current active score used by the engine
   string             zone_tier;                     // Categorized tier ("HIGH", "MODERATE", "LOW")
   double             initial_volume_ratio;          // Calculated capital backing coefficient
   double             departure_velocity;            // Volatility-normalized momentum velocity

   int                touch_count;                   // Cumulative price test contacts
   int                bounce_count;                  // Successful rejections away from zone
   int                failure_count;                 // Minor penetrations / invalidations
   double             max_reaction_pips;             // Peak departure distance achieved before death
   int                resurrection_count;            // Total level reactivations logged
   string             breakout_quality;              // Classified breakout force ("WEAK", "MODERATE", "STRONG")

                     CZone()
     {
      name = "";
      price_level = 0.0;
      top = 0.0;
      bottom = 0.0;
      height = 0.0;
      is_broken = false;
      broken_time = 0;
      consecutive_closes_outside = 0;
      type = ZONE_NEUTRAL;
      status = ZONE_VIRGIN;
      is_user_zone = true; // Defaulting an empty declaration as user-driven until specified
      was_drawn = false;
      created = TimeCurrent();
      last_touch_time = 0;
      buy_triggered = false;
      sell_triggered = false;
      strength = 1.0;
      was_recently_moved = false;

      Current_zone_score   =0.0;
      zone_score           = 0;
      zone_tier            = "NONE";
      initial_volume_ratio = 1.0;
      departure_velocity   = 0.0;
      touch_count          = 0;
      bounce_count         = 0;
      failure_count        = 0;
      max_reaction_pips    = 0.0;
      resurrection_count   = 0;
      breakout_quality     = "NONE";

      is_pending                 = false;
      consecutive_rejection_closes = 0;

     }

                     CZone(double p, ENUM_ZONE_TYPE t, datetime ct, double current_atr)
     {
      price_level = p;
      type = t;
      status = ZONE_VIRGIN;
      is_user_zone = false;
      was_drawn = false;
      is_broken = false;
      broken_time = 0;

      double zone_height = 0.0;
      if(current_atr > 0.0)
        {
         zone_height = current_atr * 0.5;    // Zone size scales directly with volatility
        }
      else
        {
         zone_height = 20.0 * _Point * 10.0; // Fail-safe default size if data is empty
        }

      top = (type == ZONE_RESISTANCE) ? p : p + zone_height;
      bottom = (type == ZONE_RESISTANCE) ? p - zone_height : p;
      height = top - bottom;

      created = ct;
      last_touch_time = ct;
      consecutive_closes_outside = 0;
      buy_triggered = false;
      sell_triggered = false;
      strength = 1.0;

      zone_score           = 0;
      Current_zone_score   =0.0;
      zone_tier            = "NONE";
      initial_volume_ratio = 1.0;
      departure_velocity   = 0.0;
      touch_count          = 0;
      bounce_count         = 0;
      failure_count        = 0;
      max_reaction_pips    = 0.0;
      resurrection_count   = 0;
      breakout_quality     = "NONE";

      is_pending                 = false;
      consecutive_rejection_closes = 0;
      was_recently_moved = false;

      name = (type == ZONE_SUPPORT ? "S_" : "R_") + EnumToString(_Period) + "_" +
             DoubleToString(p, _Digits) + "_" + IntegerToString((long)ct);
     }

   bool              IsPriceNearZone(double price)
     {
      double pipMultiplier = (_Digits == 3 || _Digits == 5) ? 10.0 : 1.0;
      double proximityBuffer = ApproachPips * _Point * pipMultiplier;

      bool isInside = (price >= (bottom - proximityBuffer) && price <= (top + proximityBuffer));
      return isInside;
     }

   color             GetColor(void)
     {
      if(is_broken)
        {
         return clrWhite; // Ghost states render as a hollow white border
        }
      if(status == ZONE_INACTIVE)
        {
         return clrGray;  // Deactivated states render in neutral gray
        }
      if(type == ZONE_SUPPORT)
        {
         return (status == ZONE_VIRGIN ? clrLimeGreen : clrGreen);
        }

      return (status == ZONE_VIRGIN ? clrRed : clrOrangeRed);
     }
  };

bool   RegisterUserZone(string obj_name);      // renamed from RegisterHybridZone for part(III) compliance
void ResolvePendingInteractions(double atr);
void MonitorZoneLifecycle(CLogger &log_instance, CArrayObj &zones, double atr, double multiplier);
int    AnalyzeZoneCandidate(double p, ENUM_ZONE_TYPE t, double &out_vol_ratio, double &out_velocity, string &out_tier);

CZone* GetZoneByName(string obj_name);
void UpdateZoneCoordinates(string obj_name);
void RemoveZoneByName(string obj_name);
void NukeIrrelevantZones(void);
void MergeZones(double atr);
void DetectDynamicZones(double atr);
void TryCreateAutoZone(double p, ENUM_ZONE_TYPE t, datetime dt, double atr, int score, string tier, double vol_ratio, double velo_pips);
void UpdateZoneVisuals(bool force_time_extension);

bool UpdateGlobalVolatilityCache(void)
  {
   if(atr_handle == INVALID_HANDLE)
     {
      g_cached_atr = 0.0;
      return false;
     }

   static double atr_buffer[1]; // Static single-element buffer avoids per-tick array re-allocation

   if(CopyBuffer(atr_handle, 0, 0, 1, atr_buffer) > 0)
     {
      g_cached_atr = atr_buffer[0];
      return true;
     }

   return false;
  }

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

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

void OnDeinit(const int reason)
  {
   ObjectsDeleteAll(0, -1, OBJ_RECTANGLE);

   active_zones.Clear();
   blacklist.Clear();

   if(atr_handle != INVALID_HANDLE)
     {
      IndicatorRelease(atr_handle);
      atr_handle = INVALID_HANDLE;
     }

   if(CheckPointer(g_trade) == POINTER_DYNAMIC)
     {
      delete g_trade;
      g_trade = NULL;
     }
   if(CheckPointer(g_strategy) == POINTER_DYNAMIC)
     {
      delete g_strategy;
      g_strategy = NULL;
     }

   PrintFormat(">>> Deinitialization Engine detached smoothly. Reason Code: %d", reason);
   ChartRedraw();
  }

CZone* GetZoneByName(string obj_name)
  {
   for(int i = 0; i < active_zones.Total(); i++)
     {
      CZone *z = (CZone*)active_zones.At(i);
      if(z != NULL && z.name == obj_name)
         return z;
     }
   return NULL;
  }

void OnChartEvent(const int id, const long &lparam, const double &dparam, const string &sparam)
  {

   if(id == CHARTEVENT_OBJECT_CREATE)
     {

      if(StringSubstr(sparam, 0, 2) == "S_" || StringSubstr(sparam, 0, 2) == "R_")
         return;

      if(ObjectGetInteger(0, sparam, OBJPROP_TYPE) == OBJ_RECTANGLE)
        {
         if(RegisterUserZone(sparam))
           {

            CZone *z = GetZoneByName(sparam);
            double z_top = (z != NULL) ? z.top : ObjectGetDouble(0, sparam, OBJPROP_PRICE, 0);
            double z_bottom = (z != NULL) ? z.bottom : ObjectGetDouble(0, sparam, OBJPROP_PRICE, 1);
            string z_type = (z != NULL) ? EnumToString(z.type) : "ZONE_SUPPORT";

            string details = StringFormat(">>> Registered user zone: %s | Bounds: %.5f - %.5f", sparam, z_top, z_bottom);
            logger.LogZone("USER", ZE_CREATED, sparam, z_type, z_top, z_bottom, "Strength:1.0", details);
           }
        }
     }

   else
      if(id == CHARTEVENT_OBJECT_DRAG || id == CHARTEVENT_OBJECT_ENDEDIT)
        {
         if(ObjectGetInteger(0, sparam, OBJPROP_TYPE) == OBJ_RECTANGLE)
           {
            UpdateZoneCoordinates(sparam);

            CZone *z = GetZoneByName(sparam);
            if(z != NULL)
              {
               string details = StringFormat(">>> ZONE MANIPULATION Resized object: %s | New Bounds: %.5f - %.5f", sparam, z.top, z.bottom);
               logger.LogZone("USER", ZE_MODIFIED, sparam, EnumToString(z.type), z.top, z.bottom, "Strength:1.0", details);
              }
            ChartRedraw(0);
           }
        }

      else
         if(id == CHARTEVENT_OBJECT_DELETE)
           {

            CZone *z = GetZoneByName(sparam);
            if(z != NULL)
              {
               string details = ">>> Deletion Detected user extraction of: " + sparam;
               logger.LogZone(z.is_user_zone ? "USER" : "AUTO", ZE_DELETED, sparam, EnumToString(z.type), z.top, z.bottom, "Strength:0.0", details);
              }

            RemoveZoneByName(sparam);
            ChartRedraw(0);
           }
  }

bool RegisterUserZone(string obj_name)
  {
   if(ObjectFind(0, obj_name) < 0)
      return false;

   double boundary_p1 = ObjectGetDouble(0, obj_name, OBJPROP_PRICE, 0);
   double boundary_p2 = ObjectGetDouble(0, obj_name, OBJPROP_PRICE, 1);
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);

   double passed_atr = g_cached_atr;

   ENUM_ZONE_TYPE derived_type = ((boundary_p1 + boundary_p2) / 2.0 > bid) ? ZONE_RESISTANCE : ZONE_SUPPORT;
   CZone* new_zone = new CZone((boundary_p1 + boundary_p2) / 2.0, derived_type, TimeCurrent(), passed_atr);

   new_zone.name = obj_name;
   new_zone.is_user_zone = true;
   new_zone.was_recently_moved = true;
   new_zone.top = MathMax(boundary_p1, boundary_p2);
   new_zone.bottom = MathMin(boundary_p1, boundary_p2);
   new_zone.height = new_zone.top - new_zone.bottom;
   new_zone.price_level = (new_zone.top + new_zone.bottom) / 2.0;
   new_zone.was_drawn = true;

   ObjectSetInteger(0, obj_name, OBJPROP_TIME, 1, TimeCurrent());
   ObjectSetString(0, obj_name, OBJPROP_TEXT, "USER");
   ObjectSetInteger(0, obj_name, OBJPROP_RAY_RIGHT, true);
   ObjectSetInteger(0, obj_name, OBJPROP_BACK, true);
   ObjectSetInteger(0, obj_name, OBJPROP_FILL, true);
   ObjectSetInteger(0, obj_name, OBJPROP_COLOR, new_zone.GetColor());

   active_zones.Add(new_zone);
   return true;
  }

void UpdateZoneCoordinates(string obj_name)
  {
   CZone* existing_zone = NULL;

   for(int z = 0; z < active_zones.Total(); z++)
     {
      CZone* zone_ptr = (CZone*)active_zones.At(z);
      if(zone_ptr != NULL && zone_ptr.name == obj_name)
        {
         existing_zone = zone_ptr;
         break;
        }
     }

   if(existing_zone == NULL)
     {

      if(StringSubstr(obj_name, 0, 2) != "S_" && StringSubstr(obj_name, 0, 2) != "R_")
         RegisterUserZone(obj_name);
      return;
     }

   double boundary_p1 = ObjectGetDouble(0, obj_name, OBJPROP_PRICE, 0);
   double boundary_p2 = ObjectGetDouble(0, obj_name, OBJPROP_PRICE, 1);

   existing_zone.top = MathMax(boundary_p1, boundary_p2);
   existing_zone.bottom = MathMin(boundary_p1, boundary_p2);
   existing_zone.height = existing_zone.top - existing_zone.bottom;
   existing_zone.price_level = (existing_zone.top + existing_zone.bottom) / 2.0;
   existing_zone.was_recently_moved = true;

   if(!existing_zone.is_user_zone)
     {
      existing_zone.is_user_zone = true;
      ObjectSetString(0, existing_zone.name, OBJPROP_TEXT, "USER");

      double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
      existing_zone.type = (existing_zone.price_level > bid) ? ZONE_RESISTANCE : ZONE_SUPPORT;
     }

   ObjectSetInteger(0, obj_name, OBJPROP_TIME, 1, TimeCurrent()); // Force Time 2 forward again
   ObjectSetInteger(0, obj_name, OBJPROP_RAY_RIGHT, true);
   ObjectSetInteger(0, obj_name, OBJPROP_COLOR, existing_zone.GetColor());
  }

void RemoveZoneByName(string obj_name)
  {
   for(int i = active_zones.Total() - 1; i >= 0; i--)
     {
      CZone* z = (CZone*)active_zones.At(i);
      if(z == NULL)
         continue;

      if(z.name == obj_name)
        {
         if(!z.is_user_zone)
           {

            blacklist.Add(DoubleToString(z.price_level, _Digits));
           }

         z.was_drawn = false;

         string z_source = z.is_user_zone ? "USER" : "AUTO";
         string z_type = EnumToString(z.type);
         double z_top = z.top;
         double z_bottom = z.bottom;

         string details = ">>> Memory cleared for internal object tracking array handle: " + obj_name;

         logger.LogZone(z_source,
                        ZE_DELETED,
                        obj_name,
                        z_type,
                        z_top,
                        z_bottom,
                        "State:CLEANUP",
                        details);

         active_zones.Delete(i);
        }
     }
  }

void NukeIrrelevantZones(void)
  {
   double bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);
   double ask = SymbolInfoDouble(_Symbol, SYMBOL_ASK);
   int purged = 0;

   for(int i = active_zones.Total() - 1; i >= 0; i--)
     {
      CZone *z = (CZone*)active_zones.At(i);
      if(z == NULL)
         continue;

      bool is_dead = false;

      if(z.type == ZONE_SUPPORT && bid < z.bottom)
         is_dead = true;

      if(z.type == ZONE_RESISTANCE && ask > z.top)
         is_dead = true;

      if(is_dead)
        {
         ObjectDelete(0, z.name);
         active_zones.Delete(i);
         purged++;
        }
     }

   if(purged > 0)
      PrintFormat(">>> [INITIAL PURGE] DELETED %d irrelevant zones from memory and chart.", purged);

   ChartRedraw(0);
  }

void MonitorZoneLifecycle(CLogger &log_instance, CArrayObj &zones, double atr, double multiplier)
  {
   static datetime last_bar = 0;
   datetime bar_time = iTime(_Symbol, _Period, 1);
   bool is_new_bar = (bar_time != last_bar);

   if(!is_new_bar)
     {
      bool work_to_do = false;
      for(int i = 0; i < zones.Total(); i++)
        {
         CZone *z = (CZone*)zones.At(i);
         if(z != NULL)
           {
            if(z.is_user_zone && z.was_recently_moved)
              {
               work_to_do = true;
               break;
              }
           }
        }
      if(!work_to_do)
        {
         return;
        }
     }
   else
     {
      last_bar = bar_time; // Lock in the new bar completion stamp
     }

   double tolerance = atr * multiplier;

   double high  = iHigh(_Symbol, _Period, 1);
   double low   = iLow(_Symbol, _Period, 1);
   double close = iClose(_Symbol, _Period, 1);

   double live_bid = SymbolInfoDouble(_Symbol, SYMBOL_BID);

   for(int i = zones.Total() - 1; i >= 0; i--)
     {
      CZone *z = (CZone*)zones.At(i);
      if(z == NULL || z.is_broken) // Only track live active structures
         continue;

      bool evaluation_triggered = false;
      bool touched = false;

      if(z.is_user_zone && z.was_recently_moved)
        {
         evaluation_triggered = true;
         z.was_recently_moved = false; // Immediately lower the flag so it only evaluates on-tick once!

         double upper_limit = z.top + tolerance;
         double lower_limit = z.bottom - tolerance;
         touched = (live_bid <= upper_limit && live_bid >= lower_limit);
        }

      else
         if(is_new_bar)
           {
            evaluation_triggered = true;

            if(EnableTemporalDecay)
              {
               z.Current_zone_score = MathMax(0.0, z.Current_zone_score - DecayRatePerBar);
              }

            touched = (low <= z.top + tolerance && high >= z.bottom - tolerance);
           }

      if(!evaluation_triggered)
         continue;

      if(z.is_pending || !touched)
         continue;

      z.is_pending = true;
      z.touch_count++;
      z.last_touch_time = iTime(_Symbol, _Period, 1);
      z.consecutive_rejection_closes = 0; // Reset rejectio

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

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

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

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

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

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

Стоимость полного кода
3 356,60₽ ≈ $41.02