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? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.