Human-Level SMC Market Structure Engine
Похожие материалы по тегам
Сообщите нам, если считаете, что материал размещён без разрешения.
Сообщить о материале
Обращение по товару «human_level_structure_engine.mq5» отправится на рассмотрение. Укажите контакт для ответа и опишите причину.
О программе
Human-Level SMC Market Structure Engine — это индикатор для MetaTrader 5, отображающий аналитическую структуру рынка на графике через объекты. Продукт реализует автоматическое обнаружение ключевых свечных точек (HH, HL, LH, LL) и анализ ценовых данных с применением технических показателей.
Индикатор рассчитывает фрактальные свинги на основе параметра силы, а затем классифицирует их как максимумы и минимумы более высокого или более низкого уровня. На основе чередующихся свингов определяются события BOS (прорыв структуры) и CHoCH (изменение характера) с хронологической обработкой без задержек.
Дополнительно индикатор строит уровни Фибоначчи на подтверждённых событиях CHoCH, определяет сигналы отката на уровне 50%, а также обнаруживает зоны FVG (Fair Value Gap) в трёхсвечной последовательности после CHoCH и сигнализирует о их митигации. Все отрисовки управляются параметрами визуализации и отображают статус в виде HUD на графике.
Настройки программы
| Настройка | Описание |
|---|---|
| InpSwingStrength | Количество баров слева и справа от анализируемой точки для определения фрактального свинга (пивота). |
| InpMinPullbackATR | Минимальная глубина отката между свингами, выраженная в кратности ATR, для признания чередования структуры. |
| InpATRPeriod | Период расчёта индикатора ATR (Average True Range), используемого для определения глубины отката и отступов при отрисовке меток. |
| InpMaxBars | Максимальное количество баров для анализа при расчёте свингов и событий. |
| InpShowSwingPoints | Отображение точечных маркеров (кружков) на свинговых точках HH, HL, LH, LL на графике. |
| InpShowStructureLabels | Отображение текстовых меток HH, HL, LH, LL рядом с соответствующими свинговыми точками на графике. |
| InpTextSize | Размер шрифта меток свинговых точек (HH, HL, LH, LL) и маркеров на графике. |
| InpBullishColor | Цвет отрисовки бычьих объектов: метки HH, HL, линии BOS ↑ и CHoCH ↑, а также стрелки и тексты бычьих сигналов. |
| InpBearishColor | Цвет отрисовки медвежьих объектов: метки LH, LL, линии BOS ↓ и CHoCH ↓, а также стрелки и тексты медвежьих сигналов. |
| InpShowBOS | Отображение событий BOS (Break of Structure — прорыв структуры) на графике в виде линий и меток. |
| InpShowCHoCH | Отображение событий CHoCH (Change of Character — изменение характера) на графике в виде линий и меток. |
| InpShowBreakLines | Отображение горизонтальных линий прорыва для событий BOS и CHoCH на графике. |
| InpUseCloseForBreak | Признание прорыва структуры по закрытию свечи (true) или по экстремуму свечи (false — по верхней/нижней тени). |
| InpBreakLineWidth | Толщина линий прорыва (BOS и CHoCH) в пикселях. |
| InpBreakLineStyle | Стиль линий прорыва (BOS и CHoCH), задающий тип линии для отрисовки событий на графике. |
| InpEventTextSize | Размер шрифта текстовых меток событий BOS и CHoCH на графике. |
| InpShowCHoCHFibo | Автоматическая отрисовка уровней Фибоначчи на подтверждённых событиях CHoCH. |
| InpFiboColor | Цвет линий и уровней Фибоначчи, рисуемых на событиях CHoCH. |
| InpFiboWidth | Толщина линий Фибоначчи в пикселях. |
| InpFiboStyle | Стиль линий Фибоначчи, задающий тип линии для отрисовки уровней. |
| InpShowRetestSignals | Отображение сигналов отката на уровне 50% Фибоначчи после CHoCH в виде стрелок и текстовых меток. |
| InpSignalArrowSize | Размер стрелок сигналов отката на 50% уровня Фибоначчи и сигналов митигации FVG. |
| InpShowSignalText | Отображение текстовых меток Buy/Sell рядом со стрелками сигналов отката и митигации FVG. |
| InpShowCHoCHFVG | Обнаружение и отрисовка зон FVG (Fair Value Gap) после событий CHoCH на графике. |
| InpShowFVGSignals | Отображение стрелок и текстовых меток сигналов митигации (тапа) зон FVG на графике. |
| InpBullishFVGColor | Цвет прямоугольника зоны FVG (Fair Value Gap) для бычьих событий CHoCH. |
| InpBearishFVGColor | Цвет прямоугольника зоны FVG (Fair Value Gap) для медвежьих событий CHoCH. |
| InpFillFVGBox | Заливка прямоугольника зоны FVG цветом при отрисовке на графике. |
| InpFVGTextSize | Размер шрифта текста метки зоны FVG на графике. |
| InpShowStatus | Отображение информационной панели (HUD) в левом верхнем углу графика с текущим состоянием структуры и количеством объектов. |
| InpDeleteObjectsOnExit | При деинициализации индикатора удаляет все созданные им графические объекты с графика, если установлено в true. |
Поиск по коду файла
#property version "2.70"
#property description "Human-Level SMC Market Structure Engine with CHoCH Fibo & FVG Mitigation Signals."
#property indicator_chart_window
#property indicator_plots 0
enum ENUM_SWING_TYPE
{
SW_NONE = 0,
SW_HIGH,
SW_LOW
};
enum ENUM_LABEL_TYPE
{
LB_NONE = 0,
LB_HH,
LB_HL,
LB_LH,
LB_LL
};
enum ENUM_TREND_STATE
{
TREND_UNKNOWN = 0,
TREND_BULL,
TREND_BEAR
};
struct SSwingPoint
{
int bar_idx;
datetime time;
double price;
ENUM_SWING_TYPE type;
ENUM_LABEL_TYPE label;
};
struct SBreakEvent
{
int break_bar;
int swing_bar;
int anchor_bar; // Origin swing bar for Fibonacci anchor
bool is_bullish;
bool is_choch;
double level; // Broken level (100%)
double anchor_level; // Origin level (0%)
datetime t_start;
datetime t_end;
};
struct SFiboSignal
{
int bar_idx;
datetime time;
double price;
bool is_buy;
double fibo_50_level;
};
struct SFVGZone
{
int fvg_idx;
int choch_evt_idx;
int formed_bar;
datetime t_start;
datetime t_end;
double top;
double bottom;
bool is_bullish;
bool is_mitigated;
int mitigate_bar;
datetime mitigate_time;
double mitigate_price;
};
input group "=== Structural Wave & Pivot Filter ==="
input int InpSwingStrength = 15; // Pivot Strength (Bars on Left/Right)
input double InpMinPullbackATR = 0.85; // Minimum Pullback Depth (ATR Multiplier)
input int InpATRPeriod = 14; // ATR Period
input int InpMaxBars = 2000; // Max Lookback Bars
input group "=== Visuals: Swings & Labels ==="
input bool InpShowSwingPoints = true; // Show Dot Markers at Swings
input bool InpShowStructureLabels = true; // Show HH / HL / LH / LL Labels
input int InpTextSize = 9; // Label Font Size
input color InpBullishColor = C'0,225,120'; // Bullish Color (HH / HL / BOS ↑ / CHoCH ↑)
input color InpBearishColor = C'255,75,90'; // Bearish Color (LH / LL / BOS ↓ / CHoCH ↓)
input group "=== Visuals: BOS & CHoCH ==="
input bool InpShowBOS = true; // Show BOS (Continuation)
input bool InpShowCHoCH = true; // Show CHoCH (Reversal)
input bool InpShowBreakLines = true; // Show Break Lines
input bool InpUseCloseForBreak = true; // Confirm Break by Candle Close (false = Wick)
input int InpBreakLineWidth = 1; // Line Width
input ENUM_LINE_STYLE InpBreakLineStyle = STYLE_DASH; // Line Style
input int InpEventTextSize = 8; // Event Label Size
input group "=== CHoCH Fibonacci & 50% Retest Signals ==="
input bool InpShowCHoCHFibo = true; // Draw Fibonacci on CHoCH
input color InpFiboColor = clrYellow; // Fibonacci Color
input int InpFiboWidth = 1; // Fibonacci Line Width
input ENUM_LINE_STYLE InpFiboStyle = STYLE_SOLID; // Fibonacci Line Style
input bool InpShowRetestSignals = true; // Show 50% Fibo Retest Signals
input int InpSignalArrowSize = 2; // Signal Arrow Size (Wingdings 233/234)
input bool InpShowSignalText = true; // Show Buy/Sell Text Label
input group "=== CHoCH Post-3-Candle FVG & Mitigation Signals ==="
input bool InpShowCHoCHFVG = true; // Detect & Draw FVG after CHoCH
input bool InpShowFVGSignals = true; // Show FVG Mitigation Buy/Sell Signals
input color InpBullishFVGColor = C'0,120,65'; // Bullish FVG Box Color
input color InpBearishFVGColor = C'130,35,45'; // Bearish FVG Box Color
input bool InpFillFVGBox = true; // Fill FVG Box
input int InpFVGTextSize = 8; // FVG Text Size
input group "=== Display & Dashboard ==="
input bool InpShowStatus = true; // Show Status HUD
input bool InpDeleteObjectsOnExit = true; // Delete Objects on Remove
const string PREFIX = "SMC_PRO_";
MqlRates Rates[];
double ATR[];
int BarsCount = 0;
string g_active_objects[];
int g_active_count = 0;
void ResetActiveTracker()
{
ArrayResize(g_active_objects, 0);
g_active_count = 0;
}
void RegisterActiveObject(const string name)
{
ArrayResize(g_active_objects, g_active_count + 1);
g_active_objects[g_active_count] = name;
g_active_count++;
}
void CleanupUnusedObjects()
{
int total = ObjectsTotal(0, -1, -1);
for(int i = total - 1; i >= 0; i--)
{
string name = ObjectName(0, i, -1, -1);
if(StringFind(name, PREFIX) == 0 || StringFind(name, "HLSE2_") == 0 || StringFind(name, "HLSE_") == 0)
{
bool is_active = false;
for(int j = 0; j < g_active_count; j++)
{
if(name == g_active_objects[j])
{
is_active = true;
break;
}
}
if(!is_active)
ObjectDelete(0, name);
}
}
}
void DeleteAllIndicatorObjects()
{
ObjectsDeleteAll(0, PREFIX);
ObjectsDeleteAll(0, "HLSE2_");
ObjectsDeleteAll(0, "HLSE_");
}
void CalcATR()
{
ArrayResize(ATR, BarsCount);
if(BarsCount <= 0)
return;
int p = MathMax(1, InpATRPeriod);
double tr[];
ArrayResize(tr, BarsCount);
tr[0] = Rates[0].high - Rates[0].low;
for(int i = 1; i < BarsCount; i++)
{
double a = Rates[i].high - Rates[i].low;
double b = MathAbs(Rates[i].high - Rates[i - 1].close);
double c = MathAbs(Rates[i].low - Rates[i - 1].close);
tr[i] = MathMax(a, MathMax(b, c));
}
double sum = 0.0;
for(int i = 0; i < BarsCount; i++)
{
sum += tr[i];
if(i >= p)
sum -= tr[i - p];
ATR[i] = sum / MathMin(i + 1, p);
}
}
bool IsPivotHigh(int idx)
{
int s = MathMax(1, InpSwingStrength);
if(idx < s || idx + s >= BarsCount)
return false;
double h = Rates[idx].high;
for(int k = 1; k <= s; k++)
{
if(Rates[idx - k].high >= h || Rates[idx + k].high >= h)
return false;
}
return true;
}
bool IsPivotLow(int idx)
{
int s = MathMax(1, InpSwingStrength);
if(idx < s || idx + s >= BarsCount)
return false;
double l = Rates[idx].low;
for(int k = 1; k <= s; k++)
{
if(Rates[idx - k].low <= l || Rates[idx + k].low <= l)
return false;
}
return true;
}
int BuildCleanSwings(SSwingPoint &swings[])
{
ArrayResize(swings, 0);
int s = MathMax(1, InpSwingStrength);
SSwingPoint raw[];
int raw_cnt = 0;
for(int i = s; i < BarsCount - s; i++)
{
bool hi = IsPivotHigh(i);
bool lo = IsPivotLow(i);
if(!hi && !lo)
continue;
SSwingPoint sp;
sp.bar_idx = i;
sp.time = Rates[i].time;
sp.label = LB_NONE;
if(hi && !lo)
{
sp.type = SW_HIGH;
sp.price = Rates[i].high;
}
else
if(lo && !hi)
{
sp.type = SW_LOW;
sp.price = Rates[i].low;
}
else
{
if(Rates[i].close > (Rates[i].high + Rates[i].low) * 0.5)
{
sp.type = SW_HIGH;
sp.price = Rates[i].high;
}
else
{
sp.type = SW_LOW;
sp.price = Rates[i].low;
}
}
ArrayResize(raw, raw_cnt + 1);
raw[raw_cnt] = sp;
raw_cnt++;
}
if(raw_cnt == 0)
return 0;
for(int i = 0; i < raw_cnt; i++)
{
int n = ArraySize(swings);
if(n == 0)
{
ArrayResize(swings, 1);
swings[0] = raw[i];
continue;
}
SSwingPoint last = swings[n - 1];
if(raw[i].type == last.type)
{
if(raw[i].type == SW_HIGH && raw[i].price > last.price)
swings[n - 1] = raw[i];
else
if(raw[i].type == SW_LOW && raw[i].price < last.price)
swings[n - 1] = raw[i];
}
else
{
double min_pullback = (ATR[raw[i].bar_idx] > 0) ? (ATR[raw[i].bar_idx] * InpMinPullbackATR) : (15 * _Point);
double delta = MathAbs(raw[i].price - last.price);
if(delta >= min_pullback)
{
ArrayResize(swings, n + 1);
swings[n] = raw[i];
}
}
}
return ArraySize(swings);
}
void ClassifySwings(SSwingPoint &swings[])
{
double last_high = -1.0;
double last_low = DBL_MAX;
int n = ArraySize(swings);
for(int i = 0; i < n; i++)
{
swings[i].label = LB_NONE;
if(swings[i].type == SW_HIGH)
{
if(last_high < 0.0)
swings[i].label = LB_HH;
else
if(swings[i].price > last_high + (_Point * 0.5))
swings[i].label = LB_HH;
else
swings[i].label = LB_LH;
last_high = swings[i].price;
}
else
if(swings[i].type == SW_LOW)
{
if(last_low == DBL_MAX)
swings[i].label = LB_HL;
else
if(swings[i].price < last_low - (_Point * 0.5))
swings[i].label = LB_LL;
else
swings[i].label = LB_HL;
last_low = swings[i].price;
}
}
}
void DetectBreaksChronological(const SSwingPoint &swings[], SBreakEvent &events[], ENUM_TREND_STATE &final_trend)
{
ArrayResize(events, 0);
int n = ArraySize(swings);
if(n < 2)
{
final_trend = TREND_UNKNOWN;
return;
}
ENUM_TREND_STATE current_trend = TREND_UNKNOWN;
for(int i = 0; i < MathMin(3, n); i++)
{
if(swings[i].label == LB_HH || swings[i].label == LB_HL)
current_trend = TREND_BULL;
else
if(swings[i].label == LB_LH || swings[i].label == LB_LL)
current_trend = TREND_BEAR;
}
int next_swing_idx = 0;
int active_high_idx = -1;
int active_low_idx = -1;
for(int b = 0; b < BarsCount; b++)
{
while(next_swing_idx < n && swings[next_swing_idx].bar_idx <= b)
{
if(swings[next_swing_idx].type == SW_HIGH)
active_high_idx = next_swing_idx;
else
if(swings[next_swing_idx].type == SW_LOW)
active_low_idx = next_swing_idx;
next_swing_idx++;
}
if(active_high_idx >= 0)
{
double target_h = swings[active_high_idx].price;
bool broken_h = InpUseCloseForBreak ? (Rates[b].close > target_h) : (Rates[b].high > target_h);
if(broken_h && b > swings[active_high_idx].bar_idx)
{
bool is_choch = (swings[active_high_idx].label == LB_LH) || (current_trend == TREND_BEAR);
int anchor_idx = active_low_idx;
if(anchor_idx < 0 || anchor_idx >= active_high_idx)
{
for(int k = active_high_idx - 1; k >= 0; k--)
{
if(swings[k].type == SW_LOW)
{
anchor_idx = k;
break;
}
}
}
SBreakEvent ev;
ev.break_bar = b;
ev.swing_bar = swings[active_high_idx].bar_idx;
ev.anchor_bar = (anchor_idx >= 0) ? swings[anchor_idx].bar_idx : swings[active_high_idx].bar_idx;
ev.is_bullish = true;
ev.is_choch = is_choch;
ev.level = target_h;
ev.anchor_level = (anchor_idx >= 0) ? swings[anchor_idx].price : target_h;
ev.t_start = swings[active_high_idx].time;
ev.t_end = Rates[b].time;
int cnt = ArraySize(events);
ArrayResize(events, cnt + 1);
events[cnt] = ev;
current_trend = TREND_BULL;
active_high_idx = -1;
}
}
if(active_low_idx >= 0)
{
double target_l = swings[active_low_idx].price;
bool broken_l = InpUseCloseForBreak ? (Rates[b].close < target_l) : (Rates[b].low < target_l);
if(broken_l && b > swings[active_low_idx].bar_idx)
{
bool is_choch = (swings[active_low_idx].label == LB_HL) || (current_trend == TREND_BULL);
int anchor_idx = active_high_idx;
if(anchor_idx < 0 || anchor_idx >= active_low_idx)
{
for(int k = active_low_idx - 1; k >= 0; k--)
{
if(swings[k].type == SW_HIGH)
{
anchor_idx = k;
break;
}
}
}
SBreakEvent ev;
ev.break_bar = b;
ev.swing_bar = swings[active_low_idx].bar_idx;
ev.anchor_bar = (anchor_idx >= 0) ? swings[anchor_idx].bar_idx : swings[active_low_idx].bar_idx;
ev.is_bullish = false;
ev.is_choch = is_choch;
ev.level = target_l;
ev.anchor_level = (anchor_idx >= 0) ? swings[anchor_idx].price : target_l;
ev.t_start = swings[active_low_idx].time;
ev.t_end = Rates[b].time;
int cnt = ArraySize(events);
ArrayResize(events, cnt + 1);
events[cnt] = ev;
current_trend = TREND_BEAR;
active_low_idx = -1;
}
}
}
final_trend = current_trend;
}
void DetectFiboRetestSignals(const SBreakEvent &events[], SFiboSignal &signals[])
{
ArrayResize(signals, 0);
int event_cnt = ArraySize(events);
for(int i = 0; i < event_cnt; i++)
{
if(!events[i].is_choch)
continue;
double p_0 = events[i].anchor_level; // 0.0%
double p_100 = events[i].level; // 100.0%
double p_50 = p_0 + (p_100 - p_0) * 0.50; // 50% level
for(int b = events[i].break_bar + 1; b < BarsCount; b++)
{
if(events[i].is_bullish)
{
if(Rates[b].low <= p_50)
{
SFiboSignal sig;
sig.bar_idx = b;
sig.time = Rates[b].time;
sig.price = Rates[b].low;
sig.is_buy = true;
sig.fibo_50_level = p_50;
int sc = ArraySize(signals);
ArrayResize(signals, sc + 1);
signals[sc] = sig;
break;
}
}
else
{
if(Rates[b].high >= p_50)
{
SFiboSignal sig;
sig.bar_idx = b;
sig.time = Rates[b].time;
sig.price = Rates[b].high;
sig.is_buy = false;
sig.fibo_50_level = p_50;
int sc = ArraySize(signals);
ArrayResize(signals, sc + 1);
signals[sc] = sig;
break;
}
}
}
}
}
void DetectCHoCHFVGs(const SBreakEvent &events[], SFVGZone &fvgs[])
{
ArrayResize(fvgs, 0);
int event_cnt = ArraySize(events);
for(int i = 0; i < event_cnt; i++)
{
if(!events[i].is_choch)
continue;Показано первые 50% кода (символов: 21252)
Открыть по тарифу
Купите тариф с пакетом открытий или войдите, если тариф уже есть. Открытый файл останется в вашем кабинете навсегда.
Разовая покупка файла
На этой странице откроется полный исходный код файла вместо ознакомительного фрагмента.
Зачем нужен email? После подтверждения оплаты файл сохранится в кабинете на этот email. Если аккаунта ещё нет, мы создадим его и пришлём ссылку для задания пароля. Если аккаунт уже есть, покупка добавится в него. Укажите адрес, к которому у вас есть доступ.
Чтобы оформить заказ, введите email и перейдите к оплате.