# Dynamic Equilibrium Implementation Plan > **For Claude:** REQUIRED SUB-SKILL: Use superpowers:executing-plans to implement this plan task-by-task. **Goal:** После пробоя BOS/MSS Equilibrium динамически обновляется по новым экстремумам цены до появления следующего BOS/MSS. **Architecture:** Вся логика трекинга внутри CEquilibrium. Добавляются 2 параметра (price_high, price_low) в Calculate(). Новый динамический режим (m_dynamic_mode) активируется при BOS/MSS, трекает running extreme, пересчитывает буферы с backfill. Деактивируется при следующем BOS/MSS. **Tech Stack:** MQL5, MetaEditor compiler (validate_mql_code) **Design doc:** `docs/plans/2026-03-04-dynamic-equilibrium-design.md` --- ### Task 1: Добавить новые поля в CEquilibrium **Files:** - Modify: `CEquilibrium.mqh:50-65` (private секция, после m_fixed_disc2) **Step 1: Добавить поля динамического режима** В `CEquilibrium.mqh`, после строки 64 (`m_fixed_disc2`), добавить: ```cpp //--- Динамический режим после пробоя BOS/MSS bool m_dynamic_mode; // Активен ли динамический режим int m_break_dir; // Направление пробоя: 1=вверх, -1=вниз double m_track_high; // Running max(high) с момента пробоя double m_track_low; // Running min(low) с момента пробоя int m_break_bar; // AS_SERIES индекс бара начала трекинга ``` **Step 2: Инициализация в конструкторе** В `CEquilibrium::CEquilibrium()` (строка ~71-84), перед закрывающей `}`, добавить: ```cpp m_dynamic_mode = false; m_break_dir = 0; m_track_high = EMPTY_VALUE; m_track_low = EMPTY_VALUE; m_break_bar = -1; ``` **Step 3: Инициализация в Init()** В `CEquilibrium::Init()` (строка ~96-112), перед `return true;`, добавить: ```cpp m_dynamic_mode = false; m_break_dir = 0; m_track_high = EMPTY_VALUE; m_track_low = EMPTY_VALUE; m_break_bar = -1; ``` **Step 4: Сброс в FullReset()** В `CEquilibrium::FullReset()` (строка ~117-133), перед закрывающей `}`, добавить: ```cpp m_dynamic_mode = false; m_break_dir = 0; m_track_high = EMPTY_VALUE; m_track_low = EMPTY_VALUE; m_break_bar = -1; ``` **Step 5: Обновить AdjustShift()** Заменить `AdjustShift` (строка 38): ```cpp void AdjustShift(int shift) { if(m_bar_eq_prev >= 0) m_bar_eq_prev += shift; if(m_break_bar >= 0) m_break_bar += shift; } ``` **Step 6: Компиляция** Run: `validate_mql_code(mq_file_path="/Ind_Aleks_ICT_Entry_V2_TS_Indie.mq5")` Expected: success: true (поля добавлены, но ещё не используются — всё компилируется) **Step 7: Commit** ```bash git add CEquilibrium.mqh git commit -m "feat(CEquilibrium): add dynamic mode fields for post-BOS/MSS tracking" ``` --- ### Task 2: Изменить сигнатуру Calculate() и обновить вызов **Files:** - Modify: `CEquilibrium.mqh:25-29` (объявление Calculate) - Modify: `CEquilibrium.mqh:161-165` (определение Calculate) - Modify: `CSwingDetector.mqh:492-493` (вызов equilibrium.Calculate) **Step 1: Обновить объявление Calculate()** В `CEquilibrium.mqh`, строка 25-29. Заменить: ```cpp void Calculate(int bar, const SStructureSwingState &state, double &buf_equilibrium[], double &buf_premium2[], double &buf_discount2[], int rates_total); ``` На: ```cpp void Calculate(int bar, const SStructureSwingState &state, double price_high, double price_low, double &buf_equilibrium[], double &buf_premium2[], double &buf_discount2[], int rates_total); ``` **Step 2: Обновить определение Calculate()** В `CEquilibrium.mqh`, строка 161-165. Заменить: ```cpp void CEquilibrium::Calculate(int bar, const SStructureSwingState &state, double &buf_equilibrium[], double &buf_premium2[], double &buf_discount2[], int rates_total) ``` На: ```cpp void CEquilibrium::Calculate(int bar, const SStructureSwingState &state, double price_high, double price_low, double &buf_equilibrium[], double &buf_premium2[], double &buf_discount2[], int rates_total) ``` **Step 3: Обновить вызов в CSwingDetector.mqh** В `CSwingDetector.mqh`, строка 493. Заменить: ```cpp equilibrium.Calculate(bar, m_str, buf_equilibrium, buf_premium2, buf_discount2, rates_total); ``` На: ```cpp equilibrium.Calculate(bar, m_str, high[bar], low[bar], buf_equilibrium, buf_premium2, buf_discount2, rates_total); ``` **Step 4: Компиляция** Run: `validate_mql_code(mq_file_path="/Ind_Aleks_ICT_Entry_V2_TS_Indie.mq5")` Expected: success: true (сигнатура обновлена, новые параметры передаются но не используются) **Step 5: Commit** ```bash git add CEquilibrium.mqh CSwingDetector.mqh git commit -m "refactor(CEquilibrium): add price_high/price_low params to Calculate()" ``` --- ### Task 3: Реализовать логику динамического режима **Files:** - Modify: `CEquilibrium.mqh:161-308` (метод Calculate) **Step 1: Добавить динамическую логику в Calculate()** В метод `CEquilibrium::Calculate()`, ПОСЛЕ блока геттеров (строка ~215, перед комментарием `//=== Стабильные значения для буферов`) вставить: ```cpp //=== Динамический режим: трекинг после BOS/MSS === bool is_bos_mss = state.bos_up || state.bos_down || state.mss_up || state.mss_down; if(is_bos_mss) { //--- Новый BOS/MSS → начать (или перезапустить) динамический режим m_dynamic_mode = true; m_break_bar = bar; if(state.bos_up || state.mss_up) { m_break_dir = 1; m_track_high = price_high; m_track_low = EMPTY_VALUE; } else { m_break_dir = -1; m_track_low = price_low; m_track_high = EMPTY_VALUE; } } else if(m_dynamic_mode) { //--- Обновление трекинга (без BOS/MSS на этом баре) if(m_break_dir == 1) m_track_high = MathMax(m_track_high, price_high); else m_track_low = MathMin(m_track_low, price_low); } ``` **Step 2: Добавить динамический пересчёт геттеров** Сразу после блока из Step 1, ПЕРЕД `//=== Стабильные значения для буферов`, добавить: ```cpp //=== Динамический пересчёт геттеров в dynamic mode === if(m_dynamic_mode) { if(m_break_dir == 1 && state.in_low != EMPTY_VALUE && m_track_high != EMPTY_VALUE) { double dyn_range = m_track_high - state.in_low; if(dyn_range > 0.0) { m_discount = m_track_high - (pre_dis_cal * dyn_range); m_premium = EMPTY_VALUE; if(m_eq_con) { m_discount2 = m_track_high - (pre_dis_cal2 * dyn_range); m_premium2 = EMPTY_VALUE; } } } else if(m_break_dir == -1 && state.in_high != EMPTY_VALUE && m_track_low != EMPTY_VALUE) { double dyn_range = state.in_high - m_track_low; if(dyn_range > 0.0) { m_premium = m_track_low + (pre_dis_cal * dyn_range); m_discount = EMPTY_VALUE; if(m_eq_con) { m_premium2 = m_track_low + (pre_dis_cal2 * dyn_range); m_discount2 = EMPTY_VALUE; } } } } ``` **Step 3: Добавить динамическую отрисовку буферов** В блок `//=== Отрисовка ===` (строка ~259), ПОСЛЕ текущей логики записи буферов (строка ~304, `buf_discount2[bar] = m_fixed_disc2;`), добавить блок перезаписи буферов в динамическом режиме: ```cpp //=== Динамическая отрисовка: перезаписать буфер, если dynamic mode активен === if(m_dynamic_mode) { double dyn_eq = EMPTY_VALUE; double dyn_prem2 = EMPTY_VALUE; double dyn_disc2 = EMPTY_VALUE; if(m_break_dir == 1 && state.in_low != EMPTY_VALUE && m_track_high != EMPTY_VALUE) { double dyn_range = m_track_high - state.in_low; if(dyn_range > 0.0) { dyn_eq = m_track_high - (pre_dis_cal * dyn_range); if(m_eq_con) dyn_disc2 = m_track_high - (pre_dis_cal2 * dyn_range); } } else if(m_break_dir == -1 && state.in_high != EMPTY_VALUE && m_track_low != EMPTY_VALUE) { double dyn_range = state.in_high - m_track_low; if(dyn_range > 0.0) { dyn_eq = m_track_low + (pre_dis_cal * dyn_range); if(m_eq_con) dyn_prem2 = m_track_low + (pre_dis_cal2 * dyn_range); } } //--- Backfill от бара пробоя до текущего if(dyn_eq != EMPTY_VALUE) { int fill_start = MathMin(m_break_bar, rates_total - 1); for(int i = fill_start; i >= bar && i >= 0; i--) { buf_equilibrium[i] = dyn_eq; buf_premium2[i] = (dyn_prem2 != EMPTY_VALUE) ? dyn_prem2 : EMPTY_VALUE; buf_discount2[i] = (dyn_disc2 != EMPTY_VALUE) ? dyn_disc2 : EMPTY_VALUE; } } } ``` **Step 4: Компиляция** Run: `validate_mql_code(mq_file_path="/Ind_Aleks_ICT_Entry_V2_TS_Indie.mq5")` Expected: success: true **Step 5: Commit** ```bash git add CEquilibrium.mqh git commit -m "feat(CEquilibrium): implement dynamic equilibrium tracking after BOS/MSS" ``` --- ### Task 4: Визуальная проверка на графике **Step 1: Открыть MetaTrader 5, наложить индикатор на график** Проверить визуально: 1. До пробоя BOS/MSS — Equilibrium рисуется как раньше (без изменений) 2. После пробоя BOS Up — линия Equilibrium динамически сдвигается вверх при новых максимумах 3. После пробоя BOS Down — линия динамически сдвигается вниз при новых минимумах 4. При появлении нового BOS/MSS — dynamic mode перезапускается с новыми уровнями 5. Backfill корректный — вся линия от точки пробоя обновляется, а не только текущий бар **Step 2: Проверить в тестере стратегий** Запустить визуальный тестер на исторических данных, чтобы убедиться что: - `AdjustShift` корректно сдвигает `m_break_bar` - Нет вылетов за границы буфера - Линия не "улетает" на ноль **Step 3: Если всё ОК — финальный commit** ```bash git add -A git commit -m "verified: dynamic equilibrium visual test passed" ```