Ind_Aleks_ICT_Entry_V2_TS_I.../docs/plans/2026-03-04-dynamic-equilibrium.md

337 lines
12 KiB
Markdown
Raw Permalink Normal View History

# 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="<full_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="<full_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="<full_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"
```