preview
Арбитражный трейдинг Forex: Панель оценки взаимосвязей

Арбитражный трейдинг Forex: Панель оценки взаимосвязей

MetaTrader 5Торговые системы | 14 марта 2025, 12:15
974 10
Yevgeniy Koshtenko
Yevgeniy Koshtenko

Введение

Мой путь в алгоритмической торговле на Форексе длится уже много лет — годы проб, ошибок, бессонных ночей и редких, но ярких побед. За это время я перепробовал все: от простеньких индикаторов до сложных систем на машинном обучении. Но одна идея не давала мне покоя: что, если рынок не так уж идеален? Что, если за хаотичным мельтешением котировок скрываются трещины, через которые можно заглянуть в его суть и, возможно, вытащить немного профита? Так я пришел к арбитражному анализу — подходу, который стал для меня настоящим открытием, почти откровением.

Сегодня я хочу поделиться своим детищем — системой анализа справедливых цен валют с арбитражной оценкой, написанной на MQL5 для MetaTrader 5. Все началось с простого вопроса, который однажды ночью не дал мне уснуть: а что, если мы сможем вычислить "правильные" курсы валют — не те, что рынок нам подсовывает, а те, что должны быть? Из этого любопытства родилась панель, которая не только высвечивает отклонения цен от их "идеальных" значений, но и выискивает треугольные арбитражные пути — те самые моменты, когда рынок теряет бдительность, а мы можем это использовать.

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

Моя цель — не просто похвастаться кодом или покрасоваться перед публикой. Я хочу дать вам инструмент — нечто осязаемое, что можно взять, покрутить в руках, доработать под себя. Надеюсь, эта панель не только вдохновит вас на новые идеи, но и поможет увидеть рынок под другим углом — не как хаос, а как пазл, который можно разгадать.



Арбитражные хедж-фонды и масштабы арбитражной торговли на Форекс

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

Титаны валютного арбитража

Среди арбитражных хедж-фондов особенно выделяются несколько крупных игроков. Например, Millennium Management с активами под управлением более $50 млрд использует многостратегический подход, где статистический арбитраж на валютных рынках — одно из ключевых направлений. Их команды количественных аналитиков разрабатывают модели, концептуально схожие с нашей матрицей справедливых цен, но с намного более сложной математической базой и вычислительными мощностями.

Citadel Securities, Renaissance Technologies и DE Shaw — другие гиганты, активно использующие валютный арбитраж. Их преимущество не только в капитале, но и в технологиях: прямой доступ к межбанковскому рынку, серверы с минимальной задержкой (co-location), выделенные каналы связи между ключевыми торговыми площадками. Некоторые фонды инвестировали сотни миллионов долларов в инфраструктуру, сокращающую задержку исполнения ордеров до микросекунд — область, где наш МetaТrader 5-индикатор, к сожалению, не может конкурировать.



Теоретические основы анализа справедливых цен и арбитража

Идея анализа справедливых цен захватила меня, когда я задумался: а что, если рынок иногда ошибается? Годы торговли на Форексе научили меня, что валютные курсы — это не просто случайные числа на экране. Это сложная сеть взаимосвязей, где каждая пара тянет за собой другие, как нити в огромном полотне. И если где-то в этом полотне появляется дыра — несоответствие, — значит, есть шанс заработать.

Справедливая цена — это, по сути, "идеальный" курс валютной пары, который должен быть, если бы рынок был абсолютно рационален. Для прямых пар вроде EURUSD все кажется простым: берем Bid и Ask, усредняем — вот тебе ориентир. Но Форекс — это не только прямые котировки. Есть кросс-пары, вроде EURJPY, которые можно вычислить через базовые пары. И тут я вспомнил про треугольный арбитраж — старую, но до сих пор живую концепцию:

EUR/USD * USD/JPY = EUR/JPY

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

Дальше я пошел глубже. Прямые котировки — это только верхушка айсберга. Чтобы понять "справедливость" цен, нужно построить матрицу всех валютных отношений. Представьте: у вас есть 8 валют — EUR, USD, GBP, JPY и так далее. Каждая из них может быть выражена через другую через доступные пары. Например, если у меня есть EURUSD и GBPUSD, я могу вычислить EURGBP как:

EURGBP = EURUSD / GBPUSD

А если добавить обратные пары, вроде USDJPY и JPYUSD, то можно уточнять расчеты до бесконечности. Меня особенно зацепила идея "динамической калибровки". Что если вместо того, чтобы полагаться на одну пару, мы возьмем все доступные котировки и "усредним" их в единую систему? Например, для EURJPY я могу использовать не только EURUSD и USDJPY, но и другие пути: EURGBP и GBPJPY, или даже более длинные цепочки через CHF или AUD. Это как собирать пазл, где каждая деталь должна идеально лечь на свое место. 

Но как вычислить одну пару из всех других, содержащих те же валюты? Возьмем EURUSD. У меня есть прямой курс — допустим, 1. 10. Но я могу проверить его через кроссы: через GBP (EURGBP и GBPUSD), через JPY (EURJPY и USDJPY), через CHF и так далее. Теоретически, все эти пути должны дать одно и то же значение. Если нет — вот вам сигнал. Я начал размышлять: а что, если построить матрицу 8x8, где каждая ячейка — это курс одной валюты относительно другой, и заставить эту матрицу "сойтись" к единому решению? Это как решать систему уравнений, где каждая пара — это уравнение, а переменные — курсы валют. Например: 

EURUSD = 1. 10

USDJPY = 150

EURJPY = EURUSD * USDJPY = 165

Если реальный EURJPY = 166, значит, где-то есть перекос. И таких "уравнений" десятки — по числу пар. Можно взять среднее по всем путям, можно искать медиану, а можно и вовсе применить итеративный метод, как в решении систем линейных уравнений, чтобы найти "наилучшую" цену. 

Арбитраж стал второй частью этой головоломки. Треугольный арбитраж — это когда ты идешь по циклу из трех пар (EURUSD -> USDJPY -> EURJPY) и возвращаешься с прибылью. Но я задумался: а что, если искать не только треугольники, но и более длинные пути? Например, через четыре или пять пар? Теория подсказывала, что чем длиннее путь, тем больше шума, но и тем интереснее находки. Каждая концепция проверялась на практике: я гонял данные через терминал, смотрел, где расчеты расходятся с реальностью, и учился на этом. 

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


Реализация арбитражной панели: от идеи к коду

Перевод теории в код — это всегда вызов. Вот как я воплотил свою арбитражную панель в MQL5:

void CalculateFairValues() {
    GetCurrentMarketRates();
    InitializeCurrencyMatrix();
    FillCurrencyMatrixFromDirectRates();
    CalculateCrossRatesArbitrage();
    CalculateDiscrepancies();
    FindArbitrageOpportunities();
    GenerateSignals();
    UpdateDisplay();
}
Эта функция — сердце системы. Она собирает текущие котировки, строит матрицу справедливых курсов и ищет возможности. Помню, как долго бился над CalculateCrossRatesArbitrage — рынок не всегда давал прямые пары, и приходилось выкручиваться с инверсиями:
if(!g_market_rates[i].is_direct) {
    double temp_bid = 1.0 / g_market_rates[i].ask;
    double temp_ask = 1.0 / g_market_rates[i].bid;
    g_market_rates[i].bid = temp_bid;
    g_market_rates[i].ask = temp_ask;
}
Для арбитража я написал отдельную логику:
double CalculateArbitrageProfit(int pair1_idx, int pair2_idx, int pair3_idx, double amount) {
    double result = amount;
    // Логика расчета через Bid/Ask для треугольника
    return result;
}

Этот метод считает прибыль от цикла вроде EURUSD->USDJPY->EURJPY. Сначала результаты были хаотичными — спреды съедали всю выгоду. Пришлось добавить порог InpArbitrageThreshold, чтобы отсеивать шум.

Дальше — матрица справедливых курсов. InitializeCurrencyMatrix задает единицы на диагонали (EUR/EUR = 1), а FillCurrencyMatrixFromDirectRates заполняет ее прямыми котировками. Но настоящая магия — в CalculateCrossRatesArbitrage

void CalculateCrossRatesArbitrage() {
    for(int iterations = 0; iterations < 3; iterations++) {
        for(int i = 0; i < g_currencies_count; i++) {
            for(int j = 0; j < g_currencies_count; j++) {
                if(i == j) continue;
                for(int k = 0; k < g_currencies_count; k++) {
                    if(k == i || k == j) continue;
                    if(g_currency_matrix[i][k] != 0 && g_currency_matrix[k][j] != 0) {
                        double triangleRate = g_currency_matrix[i][k] * g_currency_matrix[k][j];
                        if(g_currency_matrix[i][j] == 0) g_currency_matrix[i][j] = triangleRate;
                        else g_currency_matrix[i][j] = (g_currency_matrix[i][j] * 0.7 + triangleRate * 0.3);
                        g_currency_matrix[j][i] = 1.0 / g_currency_matrix[i][j];
                    }
                }
            }
        }
    }
}

Тут я трижды перебираю валюты, уточняя кросс-курсы через треугольники. Идея простая: если у меня есть EURUSD и USDJPY, я вычисляю EURJPY. Если прямой EURJPY уже есть, я беру средневзвешенное — 70% от старого значения, 30% от нового. Три итерации — компромисс между точностью и скоростью. Помню, как тестировал это на паре EURJPY: сначала расхождения были в 0.1%, после трех циклов — в 0.01%. Но рынок не ждет, и я остановился на этом.

А как получать одну пару из всех других? Допустим, я хочу "справедливый" EURUSD. У меня есть:

  • EURGBP и GBPUSD: EURUSD = EURGBP * GBPUSD
  • EURJPY и USDJPY: EURUSD = EURJPY / USDJPY
  • EURCHF и USDCHF: EURUSD = EURCHF / USDCHF

Я могу взять все эти пути, посчитать среднее или медиану. Или пойти дальше — сделать итеративную сходимость, как в методе Гаусса-Зейделя для систем уравнений. Например:

double CalculatePairFairValue(string base, string quote) {
    int baseIdx = GetCurrencyIndex(base);
    int quoteIdx = GetCurrencyIndex(quote);
    double sum = 0.0;
    int count = 0;
    for(int k = 0; k < g_currencies_count; k++) {
        if(k == baseIdx || k == quoteIdx) continue;
        if(g_currency_matrix[baseIdx][k] != 0 && g_currency_matrix[k][quoteIdx] != 0) {
            sum += g_currency_matrix[baseIdx][k] * g_currency_matrix[k][quoteIdx];
            count++;
        }
        if(g_currency_matrix[k][baseIdx] != 0 && g_currency_matrix[quoteIdx][k] != 0) {
            sum += g_currency_matrix[quoteIdx][k] / g_currency_matrix[k][baseIdx];
            count++;
        }
    }
    return (count > 0) ? sum / count : g_currency_matrix[baseIdx][quoteIdx];
}

Каждый кусок кода — это борьба с реальностью. Но когда я увидел первые сигналы и треугольники, то понял: это работает.


Графический интерфейс: визуализация возможностей

Без понятной визуализации код оставался бы просто набором чисел. Я вложил душу в интерфейс:

bool CreateGraphics() {
    ObjectCreate(0, "FVPanel_Main", OBJ_RECTANGLE_LABEL, 0, 0, 0);
    ObjectSetInteger(0, "FVPanel_Main", OBJPROP_XDISTANCE, 20);
    ObjectSetInteger(0, "FVPanel_Main", OBJPROP_YDISTANCE, 20);
    ObjectSetInteger(0, "FVPanel_Main", OBJPROP_XSIZE, 900);
    ObjectSetInteger(0, "FVPanel_Main", OBJPROP_YSIZE, 560);
    ObjectSetInteger(0, "FVPanel_Main", OBJPROP_BGCOLOR, InpBgColor);
    CreateText("FVPanel_Header", 220, 30, "АНАЛИЗ СПРАВЕДЛИВЫХ ЦЕН ВАЛЮТ", InpHeaderTextColor, 12, true);
    CreateText("FVPanel_Signals", 60, 60, "СИГНАЛЫ ОТКЛОНЕНИЯ ОТ СПРАВЕДЛИВОЙ ЦЕНЫ", InpBuySignalColor, 10, true);
    CreateText("FVPanel_Arbitrage", 460, 60, "АРБИТРАЖНЫЕ ВОЗМОЖНОСТИ", InpArbitrageColor, 10, true);
    return true;
}

Панель делится на три зоны: сигналы отклонений, арбитражные пути и матрица курсов. Сигналы вроде "EURUSD: +0.04% — ПРОДАЖА" подсвечиваются зеленым или красным, а арбитражные треугольники — типа "EURUSD->USDJPY->EURJPY: +0.02%" — сразу показывают направления сделок.

Матрица курсов — мой личный фетиш. Она показывает все 8 валют в виде таблицы, где отклонения от справедливых цен выделяются цветом. Помню, как часами подбирал шрифты и отступы, чтобы все выглядело аккуратно.

Обновление идет через таймер:

void OnTimer() {
    g_timer_counter++;
    if(g_timer_counter >= InpUpdateInterval) {
        CalculateFairValues();
        g_timer_counter = 0;
    }
}

Это делает систему живой — данные текут в реальном времени, как пульс рынка.


Результаты работы и честная оценка

На реальных данных я систему пока не пробовал - делаю робота по ней, и это уже примерно 5-6 попытка создания рабочего арбитражного робота. Вот видео работы системы:



Размышления о справедливых ценах и матрицах

Как получать справедливые цены из матриц? Это стало моей навязчивой идеей. Матрица 8x8 — это как карта рынка. Каждая ячейка — курс одной валюты к другой. Но данные шумные: брокер дает не все пары, котировки прыгают, спреды мешают. Я начал экспериментировать.

Подход 1: Среднее по путям

Для EURUSD я беру все кроссы:

  • EURGBP * GBPUSD
  • EURJPY / USDJPY
  • EURCHF / USDCHF

Считаю среднее. Просто, но игнорирует веса — ведь EURJPY может быть ликвиднее, чем EURCHF.

Подход 2: Итеративная сходимость

Как в методе Гаусса-Зейделя: обновляю каждую ячейку матрицы, пока изменения не станут минимальными. Код выше (CalculateCrossRatesArbitrage) — это упрощенный вариант. Но я думал дальше: а что, если добавить веса по объему торгов? Или учесть волатильность пары?

Подход 3: Минимизация ошибок

Можно поставить задачу оптимизации: минимизировать сумму квадратов расхождений между текущими котировками и матрицей. Например:

Ошибка = Σ (MarketRate[i] - MatrixRate[i])^2

Решать через градиентный спуск или что-то вроде SVD. Это уже может быть долго для MQL5, но в Python я бы попробовал.

Подход 4: Длинные пути

Почему только треугольники? Я могу вычислить EURUSD через цепочку EURGBP->GBPCHF->CHFUSD. Чем больше путей, тем точнее, но и тем больше шума. На практике длинные цепочки тонут в спредах и комиссиях, как в болоте...

Эти размышления пока теоретические. Реальный рынок — это не учебник, и идеальные цены остаются мечтой. Но даже приблизиться к ним — уже шаг вперед.


Заключение

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

Рынок — это не хаос, а сложный механизм. Справедливые цены и арбитраж — как лупа, через которую можно разглядеть его детали. Визуализация делает данные живыми, адаптация — гибкими. Панель не идеальна, но она уже дает мне уверенность.

У меня куча планов — от ML до реальных тестов. Форекс не стоит на месте, и я тоже. Надеюсь, мой опыт вдохновит вас заглянуть за кулисы рынка и найти свои "несправедливости".

Прикрепленные файлы |
Последние комментарии | Перейти к обсуждению на форуме трейдеров (10)
Sergey Chalyshev
Sergey Chalyshev | 18 мар. 2025 в 21:03
Vladimir Gulakov #:

Совершенно так, всё проверено уже. К тому же брокер может в любой момент подрегулировать размер спреда в свою пользу, что они и делают.

Вы путаете дилера с брокерами.

Брокер не может подрегулировать - это уголовная статья.

Изучайте матчасть.

Vitaly Muzichenko
Vitaly Muzichenko | 18 мар. 2025 в 21:09
Sergey Chalyshev #:

Вы путаете дилера с брокерами.

Брокер не может подрегулировать - это уголовная статья.

Изучайте матчасть.

Тут ещё ордера и позиции путают, ничего удивительного.

Vladimir Gulakov
Vladimir Gulakov | 19 мар. 2025 в 17:04
Sergey Chalyshev #:

Вы путаете дилера с брокерами.

Брокер не может подрегулировать - это уголовная статья.

Изучайте матчасть.

Хорошо, пусть буде дилер.

pivomoe
pivomoe | 22 мар. 2025 в 22:21
Yevgeniy Koshtenko #:

и расхождение синтетика и реала по сравнению со стандартным отклонением часто огромно....

   А можно какой нибудь пример из лога огромного расхождения ?

pivomoe
pivomoe | 23 мар. 2025 в 11:36
Yevgeniy Koshtenko #:

Про это будет во второй статье

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

Разработка системы репликации (Часть 69): Настройка времени (II) Разработка системы репликации (Часть 69): Настройка времени (II)
Сегодня мы рассмотрим, зачем нам нужна функция iSpread. Одновременно с этим мы поймем, как система информирует нас об оставшемся времени бара, когда для этого нет ни одного доступного тика. Представленные здесь материалы предназначены только для обучения. Ни в коем случае не рассматривайте его как окончательное приложение, целью которого не является изучение представленных концепций.
Нейросети в трейдинге: Двойная кластеризация временных рядов (Окончание) Нейросети в трейдинге: Двойная кластеризация временных рядов (Окончание)
Продолжаем реализацию подходов, предложенных авторами фреймворка DUET, который предлагает инновационный подход к анализу временных рядов, сочетая временную и канальную кластеризацию для выявления скрытых закономерностей в анализируемых данных.
Переосмысливаем классические стратегии (Часть VII): Анализ валютных рынков и суверенного долга на USDJPY Переосмысливаем классические стратегии (Часть VII): Анализ валютных рынков и суверенного долга на USDJPY
Мы проанализируем взаимосвязь между валютными курсами и государственными облигациями. Облигации являются одной из самых популярных форм ценных бумаг с фиксированным доходом. Посмотрим, можно ли улучшить классическую стратегию с помощью ИИ.
Применение теории игр Нэша с фильтрацией НММ в трейдинге Применение теории игр Нэша с фильтрацией НММ в трейдинге
Настоящая статья посвящена применению теории игр Джона Нэша, в частности теории равновесия Нэша, в трейдинге. В ней обсуждается, как трейдеры могут использовать скрипты Python и платформу MetaTrader 5 для выявления и использования неэффективности рынка спомощью принципов Нэша. В статье приводится пошаговое руководство по реализации этих стратегий, включая использование скрытых Марковских моделей (HMM) и статистического анализа, для повышения эффективности торговли.