preview
Причинный граф как признак машинного обучения

Причинный граф как признак машинного обучения

MetaTrader 5Эксперты |
40 0
Yevgeniy Koshtenko
Yevgeniy Koshtenko

Введение: от условной причинности Грейнджера к CatBoost в MQL5

В первой части цикла мы построили ориентированный граф причинности между валютными парами и отделили его от обычной корреляционной матрицы. Но сам факт существования ребра X→Y ещё не отвечает на главный инженерный вопрос: даёт ли динамическая структура графа дополнительную информацию модели машинного обучения или только красиво описывает уже известное движение цены?

В статье причинный граф преобразуется в воспроизводимый набор числовых признаков. Для десяти валютных пар и трёх таймфреймов строится условный многомерный Granger‑граф. Каждое направление проверяется с учётом лагов остальных пар; устойчивость оценивается на двух половинах окна. Гетероскедастичность учитывается через Newey–West/HAC, множественные проверки — методом Benjamini–Hochberg.Затем узловые, рёберные и глобальные метрики графа присоединяются к ценовым строкам только через backward as‑of join. Последняя точка графа должна быть сформирована не позже момента решения.

Эксперимент построен как абляция. На одинаковых ежедневных решениях сравниваются три CatBoost-модели: price-only, graph-only и price+causal graph. Начальный train заканчивается 31 декабря 2009 года, тест занимает 2010–2023 годы, а чистый форвард — период с 1 января 2024 по 31 июля 2026 года. Результат оказался содержательнее простого "граф улучшил модель": graph-only почти не предсказывает направление, на тесте совместная модель немного улучшает AUC и LogLoss, а на форварде снижает просадку и повышает Profit Factor, но не даёт статистически доказанного прироста AUC. Это и есть правильный вывод: причинный граф полезен как контекст и фильтр режима, но не должен превращаться в самостоятельную кнопку Buy/Sell.

Рисунок 1. Полный исследовательский контур: синхронизированные закрытые бары, условный VAR-граф, статистическая фильтрация, backward as-of join, три абляционные CatBoost-модели и отдельный форвард.


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

Корреляция отвечает на вопрос, насколько два ряда движутся совместно. Она симметрична: корреляция EURUSD с GBPUSD равна корреляции GBPUSD с EURUSD. Причинность Грейнджера проверяет другую гипотезу: уменьшают ли прошлые значения одного ряда ошибку прогноза другого ряда после учёта собственной истории цели.

Но даже статистически значимая связь не означает готовую сделку. Ребро может отражать:

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

Поэтому граф используется не как правило "если CHFJPY ведёт GBPCHF — купить GBPCHF", а как описание состояния рынка. Модель получает ответ на более широкий набор вопросов: кто сейчас ведёт, кто принимает импульс, насколько граф разрежен, стабильно ли ребро, не устарел ли последний снимок и насколько численно надёжно оценена VAR-система.

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


Данные и временной протокол

Использован архив RoboForex_Top_History200001.zip. В него входят десять пар:

AUDUSD, CADJPY, CHFJPY, EURJPY, EURUSD, GBPCHF, GBPUSD, USDCAD, USDCHF и USDJPY.

Для каждой пары доступны H1, M30 и M15. После пересечения временных меток по всем десяти символам осталось:

Таймфрейм Синхронных доходностей Назначение
H1 130 017 медленный причинный режим и основной торговый горизонт
M30 246 692 промежуточное подтверждение направленности
M15 479 593 краткосрочная структура передачи информации

Граф строится на последовательных окнах по 2 500 наблюдений. Получено 371 состояние графа и выполнено 33 390 направленных тестов. Полный фильтр прошли 664 наблюдения рёбер.

Для ML-эксперимента используется одно решение в день по каждой паре — закрытый H1-бар с меткой 23:00 серверного времени. Цель:

target(t) = 1, если Close(t+24 H1) > Close(t), иначе 0.

Цена будущего бара не входит ни в один признак. После формирования rolling-признаков и присоединения графа получено 66 443 решения. Граф начинается не с 2000 года, а после накопления первого окна в 2 500 наблюдений, поэтому фактическая ML-выборка начинается в 2005 году.

Период Строк Как используется
2005–2009 10 575 начальное обучение для теста 2010–2023
2010–2023 35 776 длинный вневыборочный тест
2005–2023 46 351 финальное обучение перед форвардом
2024–31.07.2026 6 543 чистый forward

Параметры CatBoost одинаковы во всех абляциях. Форвард не используется для выбора признаков, глубины деревьев, порога или торгового правила.


Почему парного Granger-теста недостаточно

Парный тест проверяет X→Y, учитывая историю X и Y. Для валютной корзины этого мало. EURUSD и GBPUSD могут выглядеть причинно связанными просто потому, что обе пары реагируют на скрытый USD-фактор. Поэтому новая версия использует условный многомерный тест.

Для N=10 пар и порядка лагов p строится единая матрица:

Y(t) = c + A₁R(t−1) + ... + AₚR(t−p) + ε(t),

где R — вектор доходностей всех десяти пар. Для проверки ребра X→Y из полной модели удаляются только лаги X, а лаги Y и остальных восьми пар остаются. Если restricted-модель заметно хуже полной, прошлое X содержит дополнительную предсказательную информацию для Y.

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

Статистический конвейер одного окна

Каждое состояние графа проходит десять этапов.

  1. Закрытые бары всех десяти пар синхронизируются по времени.
  2. Цены переводятся в логарифмические доходности в базисных пунктах.
  3. Экстремальные значения ограничиваются робастным MAD-порогом.
  4. ADF-защита проверяет стационарность каждого ряда.
  5. Для каждой целевой пары порядок VAR от 1 до 3 выбирается по BIC.
  6. Полная VAR-регрессия решается один раз сразу для всех целей.
  7. Для каждого источника рассчитывается HAC/Newey–West Wald-тест.
  8. Для всех 90 направлений применяется Benjamini–Hochberg FDR 5%.
  9. Кандидат дополнительно подтверждается через частичный F‑тест и частичным ΔR².
  10. Связь должна сохраняться на первой и второй половинах окна.

Важное отличие от первой упрощённой реализации — точные q-values вместо эвристического повышения F-порога. Ниже приведена функция Benjamini–Hochberg из Python-эталона.

def bh_qvalues(pvalues): p = np.asarray(pvalues, dtype=float) order = np.argsort(p) ranked = p[order] m = len(ranked) q = ranked * m / np.arange(1, m + 1) q = np.minimum.accumulate(q[::-1])[::-1] q = np.clip(q, 0.0, 1.0) result = np.empty_like(q) result[order] = q return result

HAC/Newey–West нужен потому, что финансовые остатки гетероскедастичны и могут иметь краткую автокорреляцию. Обычная OLS-ковариация способна принять совместный всплеск волатильности за значимую направленную связь.

def hac_covariance(X, resid, xtx_inv, max_lag): xe = X * resid[:, None] S = xe.T @ xe for lag in range(1, max_lag + 1): w = 1.0 - lag / (max_lag + 1.0) gamma = xe[lag:].T @ xe[:-lag] S += w * (gamma + gamma.T) cov = xtx_inv @ S @ xtx_inv return 0.5 * (cov + cov.T)

Ребро признаётся активным только при одновременном выполнении условий:

  • оба ряда проходят ADF-защиту;
  • q-value после BH-FDR не выше 0.05;
  • частичный F‑тест p-value не выше 0.05;
  • устойчивость на половинах окна (half-window stability)не ниже 0.10;
  • число обусловленности матрицы ниже 10⁸.

Вес активного ребра равен:

weight = sqrt(Wald / p) × 1000 × ΔR² × (0.25 + 0.75 × stability).

Здесь p — выбранное число лагов. Формула не пытается интерпретировать вес как ожидаемую доходность. Она объединяет статистическую силу ограничения, добавочную объясняющую способность и устойчивость связи.

Какие признаки извлекаются из графа

После статистической фильтрации матрица превращается в ориентированный взвешенный граф. Для каждого момента времени формируются четыре группы признаков.

Группа Примеры Что описывает
Узловые in/out degree, in/out strength, net leadership, PageRank, hub, authority роль конкретной пары в передаче и приёме информации
Рёберные входящий/исходящий stable weight для каждой другой пары конкретные направления влияния относительно целевого символа
Статистические min q, max ΔR², mean stability, persistence значимость, эффект и устойчивость активных связей
Глобальные density, reciprocity, edge count, total weight, condition number состояние всего мультивалютного рынка и качество оценки
Эксплуатационные graph age, availability свежесть последнего снимка и готовность таймфрейма

Признаки рассчитываются отдельно для H1, M30 и M15. В ML-эксперимент вошло 150 графовых полей. Они дополняют 36 локальных ценовых признаков и десять one-hot идентификаторов пары.

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

  • число обусловленности H1/M30/M15-систем;
  • возраст последнего графа;
  • число активных H1-рёбер;
  • M15 PageRank и hub-score;
  • M30-влияние CHFJPY на целевую пару;
  • минимальные входящие q-value;
  • максимальный входящий ΔR²;
  • плотность и persistence графа.

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

Рисунок 2. Наиболее используемые графовые признаки финальной совместной модели. Высокая важность age и condition number показывает, что метаданные качества графа не менее важны, чем сами рёбра.

Главный контракт: только backward as-of join

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

Разрешён только следующий контракт:

для решения t используется последний graph_end_time, удовлетворяющий graph_end_time ≤ t.

features = pd.merge_asof( price_rows.sort_values("decision_time"), graph_snapshots.sort_values("graph_time"), left_on="decision_time", right_on="graph_time", direction="backward" ) features["graph_age_days"] = ( features.decision_time - features.graph_time ).dt.total_seconds() / 86400.0

Интерполяция между соседними графами также запрещена: правая точка интервала ещё не существовала в момент решения. Если история одного таймфрейма не готова, его графовые поля обнуляются, а отдельный availability-признак сообщает модели о недоступности.


Три модели для честной абляции

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

Модель Признаков Назначение
Price only 46 36 локальных price/volume/regime + 10 one-hot символов
Graph only 160 150 причинных + 10 one-hot символов
Price + causal graph 196 полная совместная модель

Все модели содержат 100 симметричных деревьев глубины 4, learning rate 0.06 и одинаковые параметры регуляризации. Это не попытка выжать максимальный результат из конкретной выборки, а воспроизводимый эксперимент на добавочную ценность признаков.

model = CatBoostClassifier( iterations=100, depth=4, learning_rate=0.06, loss_function="Logloss", l2_leaf_reg=10.0, random_strength=0.5, rsm=0.85, random_seed=24081986, verbose=False )

Первый цикл обучается только на данных до 2010 года и проверяется на 2010–2023. После фиксации метода модель переобучается на всей истории до 2024 года и один раз запускается на форварде 2024–2026.

Метрики прогноза на тесте 2010–2023

Модель AUC LogLoss Brier Balanced accuracy
Price only 0.51590 0.69402 0.25043 0.50779
Graph only

0.50605

0.69470 0.25076 0.50208
Price + causal graph 0.51874 0.69333 0.25009 0.51482

На длинном тесте совместная модель улучшила все четыре прогнозные метрики. Разница AUC относительно price-only составила +0.00284, а LogLoss уменьшился примерно на 0.00069.

Но month-block bootstrap не позволяет объявить этот прирост доказанным:

  • Δ AUC: среднее +0.00329, 95% интервал −0.00148…+0.00783;
  • Δ LogLoss: −0.00072, 95% интервал −0.00148…+0.00018;
  • Δ Brier: −0.00036, 95% интервал −0.00073…+0.00009.

Интервалы пересекают ноль. Граф выглядит полезным, но эффект слаб и режимно зависим.

Рисунок 3. Graph-only почти не отличается от случайного классификатора. Причинная структура начинает работать только совместно с локальной ценой.

Исследовательский портфель: одинаковое торговое правило

Прогнозная метрика не равна торговому результату. Для одинакового сравнения используется простое правило без индивидуальной настройки пар:

  1. каждый день в 23:00 рассчитываются вероятности всех десяти пар;
  2. выбираются две пары с максимальным |p−0.5|;
  3. направление равно знаку p−0.5;
  4. позиция удерживается 24 H1-бара;
  5. из результата вычитается текущий spread и 0.10 базисного пункта условного slippage.

Это исследовательская симуляция для price‑only модели. Она не моделирует внутрибалансовую маржу, корреляцию одновременных позиций, swap, очередь исполнения и изменение spread на выходе.

Test 2010–2023 Net, bps PF Max DD, bps
Price only +2 212.7 1.0139 −6 114.7
Graph only

-16 611.9

0.9039 −19 235.8
Price + causal graph −112.7 0.9993 −4 928.4

Тест показывает важное противоречие: совместная модель лучше классифицирует направление и имеет меньшую просадку, но её простейшее ранжирование двух пар не превосходит price-only по Net. Следовательно, граф меняет форму вероятностей и выбор состояний, но его полезность нельзя оценивать одной метрикой.

Чистый форвард 2024–2026

Перед форвардом модели переобучаются на всей истории до 1 января 2024 года. Параметры, признаки и торговое правило остаются прежними.

Модель AUC LogLoss Net, bps PF Max DD, bps
Price only 0.53406 0.69146 +4 170.1 1.1966 −1 803.9
Graph only 0.49973 0.69289 +343.8 1.0148 −1 682.2
Price + causal graph

0.52917

0.69181 +4 470.9 1.2164 −1 225.7

На форварде граф не улучшил AUC: совместная модель уступила price-only примерно 0.0049. LogLoss также немного хуже. При этом портфельный результат оказался лучше:

  • Net вырос на 300.7 базисного пункта;
  • Profit Factor вырос с 1.1966 до 1.2164;
  • максимальная просадка уменьшилась примерно на 32%;
  • средний результат сделки вырос с 3.18 до 3.41 bps.

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

  • Δ AUC: −0.00510, 95% интервал −0.01374…+0.00251;
  • Δ LogLoss: +0.00037, 95% интервал −0.00019…+0.00106;
  • разница портфельного Net: +300.7 bps, 95% интервал −2 550.7…+3 247.0 bps.

Вероятность положительной разницы Net в month-block bootstrap равна 58.7%. Этого недостаточно, чтобы объявить граф источником доказанного edge.

Рисунок 4. На форварде совместная модель имеет более ровную кривую и меньшую просадку, но преимущество над price-only невелико относительно межмесячной вариативности.

Рисунок 5. Причинный граф улучшил форвардный PF только в совместной модели. Graph-only остаётся почти нейтральным.

Рисунок 6. Наиболее заметный практический эффект graph-features — уменьшение просадки, а не рост AUC.

Где граф помог и где навредил

Агрегат скрывает различия между парами. На форварде добавление графа изменило all-daily результат относительно price-only следующим образом:

Пара Price only Price + graph Разница, bps
GBPCHF +24.2 +1 317.8 +1 293.6
CHFJPY +1 133.3 +2 014.0 +880.8
USDCHF +1 066.4 +1 867.2 +800.8
USDCAD +1 315.3 +1 403.9 +88.6
EURUSD +693.2 +732.4 +39.2
AUDUSD −459.6 −861.2 −401.6
USDJPY +1 288.1 +225.1 −1 063.0
GBPUSD +1 746.0 +479.9 −1 266.0
CADJPY +2 367.8 +1 056.3 −1 311.5
EURJPY +3 251.7 +1 870.6 −1 381.1

Наиболее сильный положительный эффект наблюдается вокруг CHF-структуры: GBPCHF, CHFJPY и USDCHF. Это согласуется с текущим мульти-ТФ графом, где GBPCHF является главным принимающим узлом, а CHFJPY — одним из лидеров.

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

Что показывает текущий реальный граф

Последние снимки на 31 июля 2026 года содержат:

  • 9 активных рёбер на H1;
  • 5 активных рёбер на M30;
  • 0 активных рёбер на M15;
  • 3 направления, подтверждённых одновременно на H1 и M30.
Источник Цель Активных TF Средний stable weight Минимальный q
CHFJPY GBPCHF 2 18.7158 0.000052
EURJPY GBPCHF 2 2.3137 0.003881
EURUSD GBPCHF 2 1.1352 0.000052

Отсутствие M15-рёбер не считается ошибкой. Строгий граф должен уметь быть пустым. Если статистические фильтры не подтверждают связь, нулевой граф честнее принудительно заполненной сети.

Рисунок 7. Последний мульти-ТФ снимок. Толщина ребра отражает устойчивый вес, а не прогнозируемую прибыль.


Как считать граф в MQL5

Python остаётся исследовательским эталоном: он использует HAC/Newey–West и точный BH-FDR. В MQL5 реализован автономный runtime-граф с условным VAR, выбором лагов по BIC, точными F-p-value, BH-FDR, ADF и устойчивость на половинах окна (half-window stability).

Сначала загружаются строго синхронные закрытые бары:

//+------------------------------------------------------------------+
//| Загружает строго синхронные доходности закрытых баров            |
//| Проверяет совпадение временных меток всех символов               |
//+------------------------------------------------------------------+
bool CG_LoadSyncReturns(const ENUM_TIMEFRAMES tf,
                        const int bars,
                        const string prefix,
                        const string suffix)
  {
   if(bars<200 || bars>CG_MAX_BARS)
      return(false);

   MqlRates reference[];
   ArraySetAsSeries(reference,true);

   const string reference_symbol=prefix+CG_BaseSymbols[0]+suffix;

   if(!SymbolSelect(reference_symbol,true))
      return(false);

   if(CopyRates(reference_symbol,tf,1,bars+1,reference)!=bars+1)
      return(false);

   //--- загружаем каждый символ и проверяем полную синхронизацию
   for(int s=0;s<CG_N;s++)
     {
      CG_Symbols[s]=prefix+CG_BaseSymbols[s]+suffix;

      if(!SymbolSelect(CG_Symbols[s],true))
         return(false);

      MqlRates rates[];
      ArraySetAsSeries(rates,true);

      if(CopyRates(CG_Symbols[s],tf,1,bars+1,rates)!=bars+1)
         return(false);

      //--- должны совпадать не только последние бары,
      //--- но и все временные метки используемого окна
      for(int k=0;k<=bars;k++)
        {
         if(rates[k].time!=reference[k].time)
            return(false);
        }

      //--- CG_Returns хранится в хронологическом порядке:
      //--- от старой доходности к самой новой
      for(int t=0;t<bars;t++)
        {
         const int newer=bars-1-t;
         const int older=bars-t;

         const double c0=rates[newer].close;
         const double c1=rates[older].close;

         if(c0<=0.0 || c1<=0.0)
            return(false);

         CG_Returns[s][t]=MathLog(c0/c1)*10000.0;
        }
     }

   CG_Bars=bars;
   CG_LastTime=reference[0].time;

   return(true);
  }

Далее для каждого кандидата строится restricted-модель без лагов источника. После BH-FDR рёбра проходят проверку на двух половинах окна:

//+------------------------------------------------------------------+
//| Применяет шаг Benjamini-Hochberg                                 |
//+------------------------------------------------------------------+
if(pv[order[rank]]<=alpha*(rank+1.0)/edge)
  {
   cutoff=rank;
  }

//+------------------------------------------------------------------+
//| Проверяет устойчивость выбранных рёбер на двух половинах окна    |
//+------------------------------------------------------------------+
for(int e=0;e<edge;e++)
  {
   if(!selected[e])
      continue;

   CG_PartialFRange(source,target,p,p,half,f1,p1,d1);
   CG_PartialFRange(source,target,p,half,CG_Bars,f2,p2,d2);

   const double stability=MathMin(f1,f2)/
                          MathMax(MathMax(f1,f2),1e-12);

   if(stability<min_stability)
      continue;
  }

Полный HAC-пересчёт тяжелее и остаётся в Python. Поэтому production-контракт должен быть двухуровневым:

  1. Research graph. Python HAC-граф используется для аудита, отбора устойчивых семейств рёбер и научного эксперимента.
  2. Runtime-compatible graph. Модель для реальной торговли должна обучаться на признаках, рассчитанных Python-зеркалом формул MQL5, либо использовать live-граф только как внешний regime/veto слой.

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

Как интегрировать признаки в советник

Практически графовые поля лучше использовать в трёх ролях:

  1. Контекст direction-модели. Price-признаки отвечают за локальное состояние пары, а incoming/outgoing strength и leadership сообщают, является ли движение локальным или частью передачи импульса по корзине.
  2. Meta-фильтр. Отдельная модель может решать, разрешать ли основной сигнал. Для meta-модели особенно полезны graph age, condition number, density, q-value и stability: они описывают качество контекста, а не направление.
  3. Распределение риска. Мультиклассовая или регрессионная allocation-модель может снижать лот в плотном, взаимном или плохо обусловленном графе и повышать его только при устойчивом одностороннем лидерстве.

Самостоятельное направление сделки по одному ребру использовать не рекомендуется. Даже самое устойчивое направление CHFJPY→GBPCHF не содержит информации о знаке будущего движения GBPCHF — оно сообщает только о добавочной предсказательной ценности прошлых CHFJPY-доходностей.

Self-test и parity

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

x(t)=0.3x(t−1)+εx(t),

y(t)=0.2y(t−1)+0.5x(t−1)+εy(t).

Ожидается ребро x→y и отсутствие y→x. Python-self-test прошёл. В комплект входит отдельный MIDAS_GRANGER_SELFTEST.mq5, который должен вывести PASS перед включением live-графа.

Для ML-контура нужны три разные проверки:

  • совпадение ценовых признаков Python и MQL5;
  • совпадение runtime-compatible графовых признаков;
  • совпадение инференса экспортированных деревьев.

PASS модели при несовпадающем графе ничего не доказывает: CatBoost точно вычислит прогноз для неправильного входного вектора.


Ограничения эксперимента

  • Granger-причинность является предсказательной, а не механистической.
  • Условие на девять других пар уменьшает confounding, но не включает ставки, индексы доллара, опционы, новости и ликвидность разных площадок.
  • Граф линейный и не обнаруживает нелинейную transfer entropy.
  • Снимки строятся на окне 2 500 баров и обновляются относительно редко; это медленный regime-признак.
  • Graph-only результат около случайного показывает, что топология не заменяет локальную цену.
  • Исследовательский портфель использует OHLC/close-to-close модель и упрощённые издержки.
  • Прирост forward Net и снижение просадки не имеют статистически значимого paired bootstrap-интервала.
  • Отдельные пары реагируют на граф в противоположных направлениях.
  • Текущий форвард уже раскрыт; любые новые правила на основе GBPCHF/CHFJPY должны проверяться на новом периоде.
  • Полная компиляция MQL5 должна быть подтверждена локальным MetaEditor и demo-forward.


Что находится в приложенном пакете

Файл Назначение
run_ablation.py полный сбор датасета и первоначальный абляционный эксперимент
train_one.py воспроизводимое обучение отдельной модели и периода
ablation_metrics_final.csv общие test/forward метрики трёх моделей
forward_by_symbol_final.csv форвардная разбивка по десяти парам
paired_bootstrap_final.json month-block bootstrap различий AUC, LogLoss и Brier
portfolio_difference_bootstrap.json bootstrap разницы портфельного результата
combined_feature_importance_v2.csv важность price и causal graph признаков
MIDAS_REAL_CAUSAL_GRAPH.py точный Python-движок conditional Granger/HAC/BH-FDR
MIDAS_REAL_CAUSAL_GRAPH_CORE.mqh ядро live-графа MQL5
MIDAS_REAL_CAUSAL_GRAPH_LIVE.mq5 автономный терминальный граф
MIDAS_GRANGER_SELFTEST.mq5 синтетическая проверка направления причинности
all_rolling_edges.csv 33 390 последовательных направленных тестов
all_rolling_node_features.csv узловые признаки всех 371 снимков
figures/ архитектура, граф, ablation и форвардные иллюстрации


Заключение

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

Эксперимент дал три принципиальных результата.

  • Первый: graph-only модель почти случайна. Топология не заменяет цену и не является готовым торговым сигналом.
  • Второй: на тесте 2010–2023 совместная модель улучшила AUC, Balanced Accuracy, LogLoss и Brier, но доверительные интервалы различий включают ноль.
  • Третий: на чистом форварде 2024–2026 price+graph модель не улучшила AUC, зато повысила Profit Factor, увеличила Net и уменьшила максимальную просадку примерно на треть. Этот результат похож на режимную фильтрацию, но его статистическая устойчивость пока не доказана.

Поэтому правильное место причинного графа в MIDAS — не отдельный предсказатель будущего, а слой контекста, meta-фильтрации и управления риском. Следующий строгий шаг — обучить runtime-compatible графовые признаки с полной Python/MQL5 parity, заморозить модель и проверить её на новом периоде, который не использовался ни в одном из текущих экспериментов.


Литература

  1. Granger C. W. J. Investigating Causal Relations by Econometric Models and Cross-Spectral Methods. Econometrica, 1969.
  2. Dickey D. A., Fuller W. A. Distribution of the Estimators for Autoregressive Time Series with a Unit Root. JASA, 1979.
  3. Newey W. K., West K. D. A Simple, Positive Semi-definite, Heteroskedasticity and Autocorrelation Consistent Covariance Matrix. Econometrica, 1987.
  4. Benjamini Y., Hochberg Y. Controlling the False Discovery Rate. Journal of the Royal Statistical Society, Series B, 1995.
  5. Kleinberg J. M. Authoritative Sources in a Hyperlinked Environment. Journal of the ACM, 1999.
  6. Page L., Brin S., Motwani R., Winograd T. The PageRank Citation Ranking. Stanford InfoLab, 1999.
  7. Prokhorenkova L. et al. CatBoost: Unbiased Boosting with Categorical Features. NeurIPS, 2018.
Прикрепленные файлы |
MQL5.zip (1821.5 KB)
Особенности написания Пользовательских Индикаторов Особенности написания Пользовательских Индикаторов
Написание пользовательских индикаторов в торговой системе MetaTrader 4
От начального до среднего уровня: Перегрузка операторов (III) От начального до среднего уровня: Перегрузка операторов (III)
В этой статье мы рассмотрим, как реализовать перегрузку как логических операторов, так и операторов сравнения. Для этого требуется определённая осторожность и немалая доля внимания. Даже небольшая оплошность при реализации перегрузки этих операторов может привести к тому, что весь код окажется совершенно непригодным для использования. Если в перегрузке возникнут какие-либо проблемы, всю базу данных, созданную на основе результатов, сгенерированных кодом, придётся либо полностью отбросить, либо, как минимум, целиком перепроверить.
Особенности написания экспертов Особенности написания экспертов
Написание и тестирование экспертов в торговой системе MetaTrader 4.
Моделирование рынка: В единстве — сила (I) Моделирование рынка: В единстве — сила (I)
Мы подходим к финишной прямой. Разработка системы репликации/моделирования почти завершена. Конечно, нам ещё предстоит доделать кое-что, но по сравнению со всем, что мы уже сделали, реализовать оставшееся будет несложно. Однако всё, что будет показано в этой статье, необходимо как следует усвоить и понять. Поэтому я желаю вам приятного чтения и, прежде всего, получить удовольствие от этого последнего этапа пути.