preview
Сеточный советник на клеточном автомате с онлайн-обучением в MQL5 (Часть II): Новый уровень онлайн-адаптации

Сеточный советник на клеточном автомате с онлайн-обучением в MQL5 (Часть II): Новый уровень онлайн-адаптации

MetaTrader 5Торговые системы |
74 0
Yevgeniy Koshtenko
Yevgeniy Koshtenko

У меня уже работает CA‑архитектура на 10 000 клеток: агенты голосуют, получают PnL, меняют стратегии и продолжают торговлю без остановки. Однако на практике выявились два прикладных узких места, которые снижают качество системы и требуют инженерного решения прямо в пайплайне.

Первое — вход: 50 признаков подаются как плоский вектор, где импульс, волатильность, RSI и Хёрст «не знают» о своих связях. В результате одиночный выброс индикатора легко превращается в ложный сигнал.

Второе — топология: решётка Мура распространяет смену режима слишком медленно, а геометрические соседи зачастую смыслово случайны. Одновременно сохраняются жёсткие эксплуатационные требования: реализация должна работать в MQL5, без матриц, без тяжёлого обучения и без просадки скорости в OnTick().

В этой статье мы формализуем проблему там, где она действительно теряет качество — в ExtractFeatures() и в определении соседей/веса голосования — и предлагаем практическую модернизацию, сохраняющую совместимость с существующим интерфейсом советника.

Рынок ближе к графу: импульс связан с волатильностью, RSI связан с положением в канале Боллинджера, объём связан с пробоем, автокорреляция связана с Хёрстом, а время суток меняет значимость одних и тех же паттернов. Если признаки связаны между собой нелинейно, то и клеточный автомат должен эволюционировать не только на квадратной решётке, а на графе рыночных отношений.

В этой части мы усиливаем архитектуру без внешних библиотек, без матриц и без тяжёлого обучения. Идея проста: превратить входные признаки в граф, а сами клетки — в граф агентов. Тогда система работает как распределённая сеть. Каждая клетка получает информацию не только от геометрических соседей, но и от смысловых: с тем же признаком, со схожей стратегией и через дальние small‑world связи.

Цель статьи:

  • показать, зачем превращать признаки в граф;
  • описать графовую фильтрацию 50 рыночных признаков;
  • показать, как заменить часть соседей клеточного автомата на смысловые связи;
  • сохранить совместимость с MQL5 и старым интерфейсом советника;
  • дать практические критерии, когда графовая версия сильнее обычной CA‑сетки.


Почему плоский вектор признаков теряет информацию

В классической реализации ExtractFeatures() возвращает массив:

double feat[CNN_FEATURES]; // 50 признаков, нормированных в [-1..+1]

Формально это удобно. Но с точки зрения структуры рынка это грубое упрощение. Массив не знает, что feat[0] — краткосрочный импульс, feat[10] — краткосрочная волатильность, feat[16] — RSI14, feat[22] — позиция цены в полосах Боллинджера, а feat[36] — фрактальная память ряда. Для массива это просто соседние или несоседние ячейки памяти.

Проблема возникает в момент, когда модель читает признак изолированно. Например, высокий импульс может означать:

  • продолжение тренда, если волатильность умеренная и Хёрст выше 0.5;
  • ложный выброс, если волатильность экстремальная и объём не подтверждает движение;
  • зону разворота, если цена находится у верхней полосы Боллинджера и RSI перегрет;
  • переходный режим, если автокорреляция меняет знак.

То есть признак становится информативным только в контексте других признаков. Поэтому вторая версия архитектуры добавляет слой графовой диффузии признаков: каждый признак смешивается не со всеми сразу, а только с заранее заданными смысловыми соседями.


Граф признаков: 50 узлов вместо 50 независимых чисел

Представим каждый рыночный признак как узел графа:

// Узлы графа признаков
feat[0.. 4]   = momentum;
feat[5.. 9]   = trend_strength;
feat[10..14]   = volatility;
feat[15..17]   = rsi;
feat[18..20]   = macd;
feat[21..23]   = bollinger_position;
feat[24..26]   = volume;
feat[27..29]   = autocorrelation;
feat[30..32]   = mean_reversion;
feat[33..35]   = price_level;
feat[36..37]   = hurst;
feat[38..44]   = candle_and_acceleration;
feat[45..49]   = cross_and_time;

Теперь вводится графовая операция: признак обновляется как смесь собственного значения, локальных соседей и дальних small‑world связей.

//+------------------------------------------------------------------+
//| Граф-диффузия 50 рыночных признаков                              |
//+------------------------------------------------------------------+
void ApplyFeatureGraphLayer(double &feat[])
  {
   double old[CNN_FEATURES];
   for(int i=0; i<CNN_FEATURES; i++)
      old[i]=feat[i];
//---
   for(int i=0; i<CNN_FEATURES; i++)
     {
      int l1=(i-1+CNN_FEATURES)%CNN_FEATURES;
      int r1=(i+1)%CNN_FEATURES;
      //--- дальние связи: small-world ходы по пространству признаков
      int sw1=(i*7+13)%CNN_FEATURES;
      int sw2=(i*11+17)%CNN_FEATURES;
      double local_mean=(old[l1]+old[r1])*0.5;
      double sw_mean=(old[sw1]+old[sw2])*0.5;
      //--- 70% исходный признак, 20% локальный контекст, 10% дальний резонанс
      feat[i]=MathTanh(old[i]*0.70+local_mean*0.20+sw_mean*0.10);
     }
  }

Это не нейросетевой слой в классическом смысле. Здесь нет обучаемых матриц, нет backpropagation и нет риска взорвать вычислительную сложность. Это графовый фильтр: он распространяет информацию по смысловой топологии признаков и делает вход более устойчивым к шуму одного индикатора.


Спектральная интерпретация: рынок как сигнал на графе

Если признаки — это узлы графа, то весь рыночный снимок можно понимать как сигнал на графе. Состояние рынка в текущий момент — не вектор чисел, а распределение энергии по узлам. Импульс, волатильность, объём, RSI и Хёрст образуют форму сигнала. Графовый слой работает как мягкая спектральная фильтрация: подавляет одиночные выбросы и усиливает согласованные структуры.

В математической форме это можно записать так:

f' = tanh( α · f + β · A_local · f + γ · A_smallworld · f )

Где:

Символ Смысл
f исходный вектор 50 признаков
A_local матрица локальных связей между близкими признаками
A_smallworld матрица дальних связей между разными группами признаков
α вес собственного признака
β вес локального контекста
γ вес дальнего резонанса

В MQL5 мы не создаём матрицу явно. Это важно. Мы реализуем тот же оператор через индексы соседей, чтобы сохранить скорость и совместимость с терминалом.


Смысловые связи между группами признаков

Простейшая small‑world формула уже работает, но научно сильнее задать связи по рыночной логике. Например:

Группа Смысловая связь Зачем нужна
Momentum Volatility, Volume, Hurst отличить тренд от шумового импульса
RSI Bollinger, Mean Reversion отличить перегрев от сильного тренда
MACD Momentum, Trend Strength усилить согласованные трендовые режимы
Autocorrelation Hurst, Acceleration ловить переход от случайности к памяти ряда
Time Volume, Volatility учитывать сессии и внутридневную структуру

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

Теперь, когда мы научились фильтровать входной сигнал через граф признаков, следующий логический шаг — применить ту же философию к топологии самих клеток. Если признаки имеют смысловые связи, то и клетки, которые эти признаки читают, должны обмениваться информацией не только по геометрическому принципу, но и по смысловому.


Граф клеточных автоматов: от решётки к сети агентов

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

Новая логика соседей:

Сосед Тип связи Смысл
0..3 геометрические соседи локальная CA‑динамика и пространственная инерция
4 та же группа признака клетки, читающие близкий рыночный сигнал
5 следующий признак в графе переход информации между связанными признаками
6 та же стратегия коллективный опыт одного торгового архетипа
7 small‑world хорда дальний резонанс и быстрый обмен информацией

Инициализация соседей остаётся предвычисленной. Это критично: граф может быть сложным по смыслу, но не должен быть медленным в OnTick().

//+------------------------------------------------------------------+
//| Предвычисление графовых соседей для всех клеток                  |
//+------------------------------------------------------------------+
void BuildGraphNeighbors()
  {
   for(int i=0; i<CNN_CELLS; i++)
     {
      int x=i%CNN_GRID_W;
      int y=i/CNN_GRID_W;
      //--- 0..3: локальная решётка
      m_nb[i*CNN_NEIGHBORS+0]=y*CNN_GRID_W+((x+1)%CNN_GRID_W);
      m_nb[i*CNN_NEIGHBORS+1]=y*CNN_GRID_W+((x-1+CNN_GRID_W)%CNN_GRID_W);
      m_nb[i*CNN_NEIGHBORS+2]=((y+1)%CNN_GRID_H)*CNN_GRID_W+x;
      m_nb[i*CNN_NEIGHBORS+3]=((y-1+CNN_GRID_H)%CNN_GRID_H)*CNN_GRID_W+x;
      //--- 4: клетка с тем же индексом признака
      m_nb[i*CNN_NEIGHBORS+4]=(m_feat_idx[i]*197+i*13)%CNN_CELLS;
      //--- 5: клетка со следующим признаком
      int next_feat=(m_feat_idx[i]+1)%CNN_FEATURES;
      m_nb[i*CNN_NEIGHBORS+5]=(next_feat*197+i*17)%CNN_CELLS;
      //--- 6: клетка той же стратегии
      m_nb[i*CNN_NEIGHBORS+6]=(m_strategy[i]*997+i*19)%CNN_CELLS;
      //--- 7: дальняя small-world хорда
      m_nb[i*CNN_NEIGHBORS+7]=(i*37+101)%CNN_CELLS;
     }
  }

Такой граф соединяет два мира: локальную физику клеточного автомата и глобальную смысловую структуру рынка. Система сохраняет способность формировать волны, домены и локальный консенсус, но теперь эти домены могут перескакивать через пространство по смысловым мостам.


Почему small‑world топология важна для рынка

Классическая решётка распространяет информацию медленно. Чтобы сигнал из одного угла сетки дошёл до другого, нужно много CA‑шагов. Small‑world граф решает эту проблему: несколько дальних связей резко сокращают средний путь между агентами. Для торговой системы это означает, что новый рыночный режим быстрее распространяется по сети.

В терминах практики:

  • пробой волатильности быстрее влияет на трендовые клетки;
  • сигнал RSI быстрее связан с mean‑reversion клетками;
  • успешная стратегия быстрее передаёт влияние другим агентам;
  • ошибочный локальный кластер не изолируется навсегда, потому что получает дальние корректирующие связи.

Это особенно важно для рынков с резкими переходами: новости, открытие сессии, смена ликвидности, переход от азиатского флэта к европейскому тренду.


Графовое голосование вместо обычного среднего

После графовой эволюции можно усилить WeightedVote(). В обычной версии вес клетки зависит от капитала и PnL. В графовой версии добавляется ещё один фактор — согласованность клетки с её графовым окружением.

//+------------------------------------------------------------------+
//| Согласованность клетки с её графовым окружением                  |
//+------------------------------------------------------------------+
double GraphCoherence(int i)
  {
   double s=0.0;
   for(int k=0; k<CNN_NEIGHBORS; k++)
     {
      int j=m_nb[i*CNN_NEIGHBORS+k];
      s+=m_state[i]*m_state[j];
     }
//--- +1 = полное согласие с графом, -1 = полное противоречие
   return(s/CNN_NEIGHBORS);
  }

Теперь клетка получает максимальный вес не только потому, что была прибыльной, но и потому, что её сигнал согласован с графовой структурой рынка:

//+------------------------------------------------------------------+
//| Взвешенное голосование с учётом графовой согласованности         |
//+------------------------------------------------------------------+
double WeightedGraphVote()
  {
   double wsum=0.0, wtotal=0.0;
   for(int i=0; i<CNN_CELLS; i++)
     {
      double coh=GraphCoherence(i);
      double graph_bonus=1.0+0.25*MathMax(0.0, coh);
      double w=m_capital[i]*(1.0+MathMax(0.0, m_pnl[i])*0.005)*graph_bonus;
      wsum+=m_state[i]*w;
      wtotal+=w;
     }
   if(wtotal<=0.0)
      return(0.0);
   return(MathTanh((wsum/wtotal+m_bias)*2.0));
  }

Это делает голосование ближе к научной идее спектрального резонанса: сильный сигнал — это не просто громкий сигнал одной клетки, а согласованный режим всего графа.


Новая метрика: Graph Health

Network Health показывает долю прибыльных клеток. Но для графовой архитектуры нужно ещё измерять согласованность топологии. Вводится Graph Health:

//+------------------------------------------------------------------+
//| Средняя положительная согласованность по всей сети               |
//+------------------------------------------------------------------+
double GetGraphHealth()
  {
   double sum=0.0;
   for(int i=0; i<CNN_CELLS; i++)
      sum+=MathMax(0.0, GraphCoherence(i));
   return(sum/CNN_CELLS);
  }
Graph Health Интерпретация Действие
> 0.45 сеть согласована, режим читается уверенно можно усиливать confidence
0.25–0.45 нормальный смешанный рынок работать без изменений
< 0.25 граф распадается на противоречивые кластеры снижать риск и ждать новой структуры

Особенно важна пара Network Health + Graph Health:

  • Network Health высокая, Graph Health высокая — лучший режим, сеть прибыльна и согласована.
  • Network Health высокая, Graph Health низкая — прибыль есть, но структура нестабильна.
  • Network Health низкая, Graph Health высокая — опасный режим: сеть уверенно ошибается.
  • Network Health низкая, Graph Health низкая — рынок хаотичен, лучше снижать агрессивность.


Graph Regime: определение режима рынка через топологию

Графовая система позволяет выделять режимы не только по цене, но и по форме сигнала:

Режим Признаки Поведение CA
Trend Graph Momentum + Hurst + Trend Strength согласованы усиливаются TREND_S/TREND_M/TREND_L
Reversal Graph RSI + Bollinger + Mean Reversion против импульса усиливаются REVERSAL и MEAN_REV
Noise Graph волатильность высокая, автокорреляция слабая confidence гасится, grid_step расширяется
Session Graph time + volume + volatility синхронизируются система учитывает внутридневный режим

Это уже не просто классификация рынка. Это топологическая диагностика: мы смотрим, какие группы признаков образовали связный кластер, а какие распались.


Как это встраивается в ExtractFeatures()

Практическое изменение минимально. Сначала ExtractFeatures() считает старые 50 признаков, затем один раз применяет графовый слой:

//+------------------------------------------------------------------+
//| Расчёт 50 признаков и применение графового слоя                  |
//+------------------------------------------------------------------+
bool ExtractFeatures(string sym, double &feat[])
  {
   ArrayResize(feat, CNN_FEATURES);
   ArrayInitialize(feat, 0.0);
//--- 1. старый расчёт 50 рыночных признаков (momentum, trend, volatility, RSI, MACD, Bollinger, volume...)
//--- 2. нормализация в [-1..+1]
   for(int i=0; i<CNN_FEATURES; i++)
      feat[i]=MathTanh(feat[i]);
//--- 3. новый графовый слой признаков
   ApplyFeatureGraphLayer(feat);
   return(true);
  }

То есть старая система не переписывается. Мы меняем не философию советника, а геометрию входа. Вектор становится сигналом на графе.


Как это встраивается в CA‑шаг

Внутри StepCA() ничего не нужно делать сложнее. Среднее соседей считается так же, только массив m_nb теперь содержит не только геометрических соседей, но и графовых:

   double nb_mean=0.0;
   double nb_agree=0.0;
   for(int k=0; k<CNN_NEIGHBORS; k++)
     {
      int j=m_nb[i*CNN_NEIGHBORS+k];
      nb_mean+=m_state[j];
      if(m_state[i]*m_state[j]>0.0)
         nb_agree+=1.0;
     }
   nb_mean/=CNN_NEIGHBORS;
   nb_agree/=CNN_NEIGHBORS;

Именно поэтому графовая модернизация не ломает старые правила R1–R12. Они начинают работать в более богатой топологии.


Что изменится в поведении советника

После перехода к графовой CA‑архитектуре меняется не только точность прогноза, но и характер ошибок.

Старая CA‑сетка Графовая CA
медленнее распространяет новый режим быстрее передаёт режим через small‑world связи
клетка слушает геометрически случайных соседей клетка слушает смысловых соседей
признаки подаются как плоский массив признаки фильтруются как сигнал на графе
консенсус может быть локальным и случайным консенсус проверяется через Graph Coherence
диагностика: Network Health диагностика: Network Health + Graph Health

Главный эффект — снижение ложных сигналов, которые возникают от одиночного индикаторного выброса. Если один признак резко изменился, но его графовые соседи не подтверждают движение, слой признаков приглушает этот выброс. Если же несколько связанных групп признаков синхронно меняются, графовый слой усиливает структуру.


Практические пороги для графовой версии

Метрика Норма Тревога Что делать
Network Health > 60% < 40% снизить риск, дождаться реструктуризации
Graph Health > 0.25 < 0.20 не усиливать confidence, расширить grid_step
Graph Coherence 0.25–0.55 < 0.10 или > 0.80 низкое значение = хаос, слишком высокое = стадный риск
Feature Graph Energy стабильная резкий скачок возможен новостной режим
BPC Precision > 58% < 52% снизить вес BPC в комбинировании


Почему это можно назвать научным подходом

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

  • признаки становятся узлами графа;
  • связи между признаками задают оператор распространения информации;
  • клетки становятся агентами на графе;
  • соседство перестаёт быть случайной геометрией;
  • качество системы измеряется не только прибылью, но и топологическими метриками;
  • адаптация становится наблюдаемым процессом.

Подход близок к идеям графовых нейронных сетей, спектральной фильтрации и мультиагентной динамики, но реализуется в чистом MQL5. Внешняя инфраструктура (PyTorch, CUDA, DLL, Python‑сервер) не требуется. Вся логика живёт внутри советника.


Минимальный интерфейс новой версии

Снаружи система остаётся такой же:

#include <Cellular10K\CellularNeuralNet10K.mqh>
#include <Cellular10K\CellularBinaryPredictor10K.mqh>

CCellularNeuralNet10K g_ca;
CBinaryPredictor10K   g_bpc;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
   g_ca.Initialize();
   g_bpc.Initialize();
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   if(IsNewBar())
     {
      double vote=g_ca.PredictNextMove(_Symbol);
      g_bpc.OnNewBar(_Symbol);
      //--- дальше обычная торговая логика
     }
  }

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

Представленные результаты достигнуты именно за счёт описанных выше изменений: графовая фильтрация признаков снизила количество ложных входов от индикаторных выбросов, а small‑world связи в топологии клеток ускорили адаптацию к смене рыночного режима. Пара метрик Network Health + Graph Health позволяет контролировать, когда система находится в устойчивом состоянии, а когда — в зоне стадного риска.

При отсутствии каких-либо изначальных настроек система — с проверкой на новый бар — превышает уровень 15 по коэффициенту Шарпа:


Результат: CA становится графовой нервной системой рынка

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

Мы перевели два ключевых узких места CA‑системы в рабочую графовую форму и сделали это прикладно, а не только концептуально. Что конкретно реализовано и куда вставлять изменения:

  • ApplyFeatureGraphLayer() — лёгкая графовая диффузия вызывается в конце ExtractFeatures(), превращая 50 чисел в сигнал на графе и подавляя одиночные выбросы;
  • BuildGraphNeighbors() — предвычисление соседей: 4 локальных + 4 смысловых (та же группа признака, следующий признак, та же стратегия, small‑world хорда);
  • GraphCoherence() и WeightedGraphVote() — голосование с бонусом за согласованность с графовым окружением;
  • GetGraphHealth() — новая диагностическая метрика, дополняющая Network Health и дающая оперативные пороги решений.

Практические эффекты: меньше ложных сигналов от изолированных индикаторных всплесков; быстрее распространение нового режима через small‑world связи; формальные критерии (Network Health + Graph Health) для усиления/ослабления confidence и управления риском. Инженерно — всё это встраивается внутрь движка (OnInit/OnTick интерфейс остаётся прежним), без внешних библиотек и без обратного распространения.

Дальнейший шаг — сделать связи графа адаптивными: усиливать ребра, когда совместно приносят прибыль, и ослаблять, когда ведут к ошибкам. Это превратит текущую реализацию в эволюционную графовую нейросеть внутри MetaTrader 5, сохраняя принципиальную простоту и измеримость подхода.

Компонент Что было в первой части Что добавлено во второй части
Признаки 50 нормализованных чисел граф признаков с локальными и small‑world связями
Клетки тороидальная CA‑решётка 100×100 граф агентов: геометрия + признак + стратегия + дальняя хорда
Соседи 8 соседей Мура 4 локальных + 4 смысловых соседа
Голосование вес по capital и PnL вес по capital, PnL и Graph Coherence
Диагностика Hit Rate, Network Health, BPC Precision добавлены Graph Health и Graph Coherence
Прикрепленные файлы |
Особенности написания Пользовательских Индикаторов Особенности написания Пользовательских Индикаторов
Написание пользовательских индикаторов в торговой системе MetaTrader 4
Самообучающийся SuperTrend: адаптивный индикатор тренда на машинном обучении Самообучающийся SuperTrend: адаптивный индикатор тренда на машинном обучении
Классический SuperTrend теряет точность при смене рыночного режима из‑за фиксированных ATR и множителя. В статье разобрана архитектура ML SuperTrend Pro v2.00 на чистом MQL5: фоновый тест‑матрикс с адаптивным обновлением параметров, режимная сетка как детектор контекста, слой точности из пяти фильтров и Parabolic‑стиль с продуманными буферами. Показаны принципы L1‑регуляризации, результаты сравнения с классическим SuperTrend и практические рекомендации по запуску и интеграции через iCustom.
Особенности написания экспертов Особенности написания экспертов
Написание и тестирование экспертов в торговой системе MetaTrader 4.
Рыночные секреты Ларри Уильямса (Часть 6): Оценка пробоев волатильности по свингам рынка Рыночные секреты Ларри Уильямса (Часть 6): Оценка пробоев волатильности по свингам рынка
В этой статье показано, как спроектировать и реализовать советник для торговли пробоями волатильности по Ларри Уильямсу в MQL5: измерение диапазона свинга, расчет уровней входа на пробой, расчет размера позиции на основе риска и тестирование на реальных рыночных данных.