English 中文 Deutsch 日本語
preview
Разработка инструментария для анализа движения цен (Часть 20): Внешние библиотеки (IV) — Correlation Pathfinder

Разработка инструментария для анализа движения цен (Часть 20): Внешние библиотеки (IV) — Correlation Pathfinder

MetaTrader 5Примеры |
44 0
Christian Benjamin
Christian Benjamin

Содержание


Введение

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

Знание этих взаимосвязей может улучшить вашу торговую стратегию и снизить риски. Например, покупка пар EURUSD и GBPUSD в период высокой положительной корреляции удваивает вашу подверженность одним и тем же рыночным силам и увеличивает риск. В качестве альтернативы, такое понимание позволяет трейдерам формировать диверсифицированные портфели и эффективно реализовывать стратегии хеджирования.

В этой статье объясняется, как добавить анализ корреляции валютных курсов в ваш торговый инструментарий. В ней представлены практические рекомендации и действенные стратегии для повышения эффективности торговли. На двух графиках ниже показана структура рынка для EURUSD и GBPUSD на одни и те же даты. Обе пары показали бычий тренд 2 апреля и перешли в медвежий тренд 3 апреля, демонстрируя положительную корреляцию. Трейдеры могут использовать одну валютную пару для подтверждения разворотов в другой. Например, если пара EURUSD находится в зоне перекупленности, а пара GBPUSD — в зоне продаж, это является четким сигналом о потенциальном развороте EURUSD. Инструмент Correlation Pathfinder крайне важен, поскольку он наглядно демонстрирует взаимосвязь между валютными парами, помогая трейдерам получить более точную картину рынка.

GBPUSD

GPBUSD

Рис 1. GBPUSD


EURUSD

EURUSD

Рис 2. EURUSD



Обзор системы

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

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

Система состоит из двух взаимосвязанных компонентов. Во-первых, советник MQL5 непрерывно получает исторические данные о ценах для пар EURUSD и GBPUSD. Программа упаковывает эти данные в структуру JSON и отправляет ее на сервер Python. Второй компонент — это аналитический движок на основе Python. В нем используется библиотека Pandas для расчета как общей, так и скользящей корреляции, а также библиотека Matplotlib для генерации графика скользящей корреляции фиксированной ширины. Кроме того, сервер предоставляет четкие комментарии, объясняющие, движутся ли валютные пары синхронно или расходятся, и описывающие последствия для торговых стратегий.

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

Блок-схема

Рис. 3. Блок-схема

Эта схема дает наглядное представление о рабочем процессе системы, отслеживая все этапы — от получения данных в MetaTrader 5 до анализа и комментариев на сервере Python. Узлы, обозначенные буквами от A до H, представляют каждый этап процесса, иллюстрируя, как данные собираются, упаковываются в формат JSON, передаются на сервер, анализируются с помощью Pandas, визуализируются с помощью Matplotlib и, наконец, сопровождаются пояснительными комментариями перед возвратом результатов анализа.


Технические подробности

Советник MQL5

Извлечение данных

Советник получает исторические данные о ценах, используя встроенную функцию CopyRates(). Эта функция извлекает массив записей о ценах (структурированных как MqlRates), содержащий такую информацию, как время, цена открытия, максимальная, минимальная и цена закрытия для заданного символа и таймфрейма. Пользователь может настроить таймфрейм (например, 15-минутные интервалы с помощью параметра PERIOD_M15) и количество баров (точек данных) для экспорта, используя соответствующий параметр BarsToExport. Благодаря возможности настройки этих параметров, советник может быть адаптирован к различным торговым стратегиям, независимо от того, нужен ли трейдеру краткосрочный снимок ситуации или более широкий обзор исторических тенденций.

MqlRates rates1[];
if(CopyRates(Symbol1, TimeFrame, 0, BarsToExport, rates1) <= 0)
{
   Print("Failed to copy rates for ", Symbol1);
   return "";
}
ArraySetAsSeries(rates1, true);

После получения данных для каждой валютной пары (например, EURUSD и GBPUSD) советник обеспечивает установку массива данных в виде последовательности. Этот шаг имеет решающее значение, поскольку он упорядочивает массив таким образом, чтобы самый последний бар находился по индексу 0, что соответствует тому, как многие другие функции в среде MQL5 ожидают форматирования данных. Такая подготовка исторических данных гарантирует получение правильного количества баров и сохранение надлежащего хронологического порядка, что крайне важно для последующего анализа.

Полезная нагрузка JSON

После сбора данных о ценах советник формирует JSON-данные, которые аккуратно упорядочивают информацию в структурированный формат для передачи. Функция BuildJSONPayload() начинается с создания JSON-объекта, содержащего названия двух валютных пар. Затем для каждой валютной пары функция создает массив объектов данных. Каждый объект в массиве представляет собой столбец исторических данных и включает в себя два ключевых элемента информации: время (последовательно отформатированное с использованием TimeToString() с параметрами TIME_DATE и TIME_SECONDS) и цена закрытия (отформатирована с пятью знаками после запятой с помощью DoubleToString()).

string json = "{";
json += "\"symbol1\":\"" + Symbol1 + "\",";
json += "\"symbol2\":\"" + Symbol2 + "\",";
json += "\"data1\":[";
for(int i = 0; i < ArraySize(rates1); i++)
{
   string timeStr = TimeToString(rates1[i].time, TIME_DATE | TIME_SECONDS);
   json += "{\"time\":\"" + timeStr + "\",\"close\":" + DoubleToString(rates1[i].close, 5) + "}";
   if(i < ArraySize(rates1) - 1)
      json += ",";
}
json += "],";
// The same pattern repeats for Symbol2's data array.
json += "}";
return json;

Такой модульный подход гарантирует, что полезная нагрузка будет содержать все необходимые детали для анализа на сервере Python. Структура JSON упрощает поддержание согласованности и гарантирует, что сервер сможет обрабатывать данные без путаницы. Например, обозначив массивы как data1 и data2, серверный скрипт точно знает, какой набор данных соответствует какой валютной паре. Четкое разделение имеет решающее значение для последующего объединения данных при расчете корреляции. Функция перебирает каждый массив исторических данных, объединяя каждую запись с соответствующим форматированием JSON, а затем завершает создание, закрывая объект JSON.

Интеграция WebRequest

После формирования JSON-данных советник отправляет их, используя функцию WebRequest() в MetaTrader — важный инструмент для выполнения HTTP-запросов непосредственно с торговой платформы. Этот компонент обеспечивает обмен данными между советником MQL5 и сервером Python, который выполняет дальнейший анализ. Перед отправкой данных советник преобразует строку JSON в динамический массив uchar с помощью функции StringToCharArray(), поскольку WebRequest() принимает тело запроса в этом формате. Это преобразование необходимо для обеспечения корректной передачи полезной нагрузки по сети.

string requestHeaders = "Content-Type: application/json\r\n";
uchar result[];
string responseHeaders;
int webRequestResult = WebRequest("POST", pythonUrl, requestHeaders, timeout, requestData, result, responseHeaders);
if(webRequestResult == -1)
{
   Print("Error in WebRequest. Error code = ", GetLastError());
   return;
}

string response = CharArrayToString(result);
Print("Server response: ", response);

Затем советник настраивает HTTP-заголовки, указывая, что данные находятся в формате JSON с помощью заголовка "Content-Type: application/json\r\n". Настраиваемые входные параметры, такие как pythonUrl (конечная точка сервера) и таймаут (время ожидания ответа советника) позволяют пользователю точно настраивать параметры сети в соответствии со своей средой. Функция WebRequest() используется с указанными заголовками и настройками таймаута для отправки HTTP POST-запроса на сервер. Если запрос не удается, советник выводит код ошибки, который помогает в устранении проблем с подключением. В противном случае, он преобразует массив uchar обратно в строку, а затем выводит ответ сервера — ожидается, что этот ответ будет содержать полезную информацию, такую как вычисленное значение корреляции и любые комментарии, сгенерированные механизмом анализа Python.

Сервер анализа Python

Серверная среда

Система построена на основе сервера Flask, который принимает POST-запросы. При запуске сервер инициализируется с использованием настроек Flask по умолчанию и устанавливает уровень логирования на DEBUG. Данная конфигурация гарантирует детальную регистрацию всех входящих запросов и этапов их обработки. Сервер предназначен для приема данных в формате JSON, их обработки, проведения анализа и возврата результатов в формате JSON. Благодаря использованию Flask сервер остается легковесным и эффективным, способным обрабатывать веб-запросы в среде без графического интерфейса, что идеально подходит для приложений автоматизированной торговли.

import matplotlib
matplotlib.use("Agg")  # Use non-interactive backend to avoid GUI overhead
import matplotlib.pyplot as plt
from flask import Flask, request, jsonify
import logging

app = Flask(__name__)
logging.basicConfig(level=logging.DEBUG)

if __name__ == "__main__":
    app.run(host="127.0.0.1", port=5000)

Анализ и обработка данных

После получения POST-запроса сервер начинает попытку анализа входящего JSON-сообщения. Если стандартный парсер не срабатывает, код декодирует необработанные данные запроса, удаляет все лишние символы после последней закрывающей фигурной скобки, а затем загружает JSON. Полученные данные затем преобразуются в два отдельных объекта Pandas DataFrames, по одному для каждой валютной пары. Поле time из полезной нагрузки анализируется и преобразуется в объекты типа datetime для обеспечения точного объединения и анализа временных рядов. После объединения двух DataFrames в общем столбце Time сервер вычисляет два ключевых показателя корреляции. Во-первых, вычисляется общая корреляция между ценами закрытия двух символов. Во-вторых, вычисляется скользящая корреляция с окном в 50 баров. Эта скользящая корреляция позволяет понять, как меняется корреляция между парами во времени, что имеет решающее значение для понимания динамики рынка и выявления периодов, когда взаимосвязь усиливается или ослабевает.

import pandas as pd
import json

@app.route('/analyze', methods=['POST'])
def analyze():
    # Parse JSON payload
    data = request.get_json(silent=True)
    if not data:
        raw_data = request.data.decode('utf-8').strip()
        app.logger.debug("Raw request data: %s", raw_data)
        try:
            end_index = raw_data.rfind("}")
            trimmed_data = raw_data[:end_index+1] if end_index != -1 else raw_data
            data = json.loads(trimmed_data)
        except Exception as e:
            app.logger.error("Failed to parse JSON: %s", str(e))
            return jsonify({"error": "Invalid JSON received"}), 400

    # Convert incoming JSON arrays to DataFrames
    data1 = pd.DataFrame(data["data1"])
    data2 = pd.DataFrame(data["data2"])
    
    # Convert time strings to datetime objects
    data1['Time'] = pd.to_datetime(data1['time'])
    data2['Time'] = pd.to_datetime(data2['time'])
    
    # Merge DataFrames on 'Time'
    merged = pd.merge(data1, data2, on="Time", 
                      suffixes=('_' + data["symbol1"], '_' + data["symbol2"]))
    
    # Calculate overall correlation between the close prices
    correlation = merged[f'close_{data["symbol1"]}'].corr(merged[f'close_{data["symbol2"]}'])
    
    # Calculate rolling correlation with a 50-bar window
    merged['RollingCorrelation'] = merged[f'close_{data["symbol1"]}'].rolling(window=50).corr(merged[f'close_{data["symbol2"]}'])
    
    # [Graph generation and commentary code follows here, see next sections]

Генерация и хранение графиков

Для визуального представления сервер использует Matplotlib при использовании бэкэнда Agg. Эта серверная часть обходит необходимость в графическом пользовательском интерфейсе, гарантируя генерацию графика в среде без запуска каких-либо дополнительных операций, связанных с графическим интерфейсом. График построен с фиксированным размером изображения, установленным на 7,5 дюймов в ширину при разрешении 100 DPI. Такая конфигурация гарантирует фиксированную ширину выходного изображения в 750 пикселей, обеспечивая единообразие во всех отчетах и упрощая интерпретацию визуальных данных с первого взгляда. После создания график, отображающий скользящую корреляцию, сохраняется в виде файла PNG в той же директории, что и скрипт Python. Локальное хранение изображения позволяет легко получить к нему доступ и поделиться им в дальнейшем, не включая само изображение в JSON-ответ сервера.

import matplotlib.pyplot as plt

# Generate a rolling correlation plot
plt.figure(figsize=(7.5, 6), dpi=100)  # 7.5 inches * 100 dpi = 750 pixels width
plt.plot(merged['Time'], merged['RollingCorrelation'], label="Rolling Correlation (50 bars)")
plt.xlabel("Time")
plt.ylabel("Correlation")
plt.title(f"{data['symbol1']} and {data['symbol2']} Rolling Correlation")
plt.legend()
plt.grid(True)
plt.tight_layout()

# Save the graph as a PNG file in the same folder
plot_filename = "rolling_correlation.png"
plt.savefig(plot_filename)
plt.close()

Интерпретация

Помимо самих числовых данных и графиков, сервер расширяет возможности анализа, генерируя пояснительные комментарии. Комментарий создается с помощью специальной функции, которая анализирует как общие, так и недавние (скользящие) значения корреляции. Например, если общая корреляция очень высока (близка к +1), в комментарии поясняется, что две валютные пары в целом движутся синхронно, что может свидетельствовать об ограниченной эффективности диверсификации при торговле несколькими парами. В качестве альтернативы, если корреляция низкая или становится отрицательной, в комментарии указывается потенциальная возможность расхождения пар и возможности хеджирования или корректировки рисков.

def generate_commentary(corr, rolling_series):
    """Generate a commentary based on overall and recent correlation values."""
    commentary = ""
    if corr >= 0.8:
        commentary += ("The currency pairs have a very strong positive correlation, meaning "
                       "they typically move together. This may support the use of hedging strategies.\n")
    elif corr >= 0.5:
        commentary += ("The pairs display a moderately strong positive correlation with some deviations, "
                       "indicating they often move in the same direction.\n")
    elif corr >= 0.0:
        commentary += ("The overall correlation is weakly positive, suggesting occasional movement together "
                       "but limited consistency, which may offer diversification opportunities.\n")
    elif corr >= -0.5:
        commentary += ("The pairs exhibit a weak to moderate negative correlation; they tend to move in opposite "
                       "directions, which can be useful for diversification.\n")
    else:
        commentary += ("The pairs have a strong negative correlation, implying they generally move in opposite "
                       "directions, a factor exploitable in hedging strategies.\n")
    
    if not rolling_series.empty:
        recent_trend = rolling_series.iloc[-1]
        commentary += f"Recently, the rolling correlation is at {recent_trend:.2f}. "
        if recent_trend > 0.8:
            commentary += ("This high correlation suggests near mirror-like movement. "
                           "Relative strength approaches may need reconsideration for diversification.")
        elif recent_trend < 0.3:
            commentary += ("A significant drop in correlation indicates potential decoupling. "
                           "This may signal opportunities in pair divergence trades.")
        else:
            commentary += ("The correlation remains moderate, meaning the pairs show some synchronization but also "
                           "retain independent movement.")
    return commentary

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


Результаты

Прежде чем перейти к результатам, необходимо объяснить, как запустить сервер на Python. Сначала скачаем и установим Python с сайта python.org и настроим виртуальную среду, запустив python -m venv venv и активировав его. Далее установим необходимые пакеты, выполнив команду pip install Flask pandas matplotlib. Создадим скрипт на Python (например, server.py), содержащий код вашего Flask-сервера и необходимые конечные точки. Наконец, перейдем в каталог со скриптом и запустите сервер с помощью команды python server.py. Подробности можно найти в одной из моих предыдущих статей о внешних библиотеках.

Ниже представлены результаты тестирования, проведенного на валютных парах EURUSD и GBPUSD. Для достижения наилучших результатов убедитесь, что вы тестируете систему на тех же валютных парах, которые указаны в вашем советнике. Первоначально логи командной строки указывают на успешную инициализацию системы и четко отображают данные, передаваемые из MetaTrader 5 советником MQL5 на сервер Python, включая значения открытия, закрытия и времени за период со 2 по 9 апреля. Запись в журнале "POST /analyze HTTP/1.1" 200, подтверждает успешное соединение и то, что сервер Python выполнил необходимую обработку должным образом.

DEBUG:plotter:Raw request data: {"symbol1":"EURUSD","symbol2":"GBPUSD","data1":[{"time":"2025.04.09 07:00:00"
,"close":1.10766},{"time":"2025.04.09 06:45:00","close":1.10735},{"time":"2025.04.09 06:30:00","close":1.10602}
,{"time":"2025.04.09 06:15:00","close":1.10538},{"time":"2025.04.09 06:00:00","close":1.10486},
{"time":"2025.04.09 05:45:00","close":1.10615},{"time":"2025.04.09 05:30:00","close":1.10454},
{"time":"2025.04.09 05:15:00","close":1.10402},{"time":"2025.04.09 05:00:00","close":1.10447},
{"time":"2025.04.09 04:45:00","close":1.10685},{"time":"2025.04.09 04:30:00","close":1.10582},
{"time":"2025.04.09 04:15:00","close":1.10617},{"time":"2025.04.09 04:00:00","close":1.10384},
{"time":"2025.04.09 03:45:00","close":1.10196},{"time":"2025.04.09 03:30:00","close":1.10184},
{"time":"2025.04.09 03:15:00","close":1.10339},{"time":"2025.04.09 03:00:00","close":1.10219},
{"time":"2025.04.09 02:45:00","close":1.10197},{"time":"2025.04.09 02:30:00","close":1.10130},
{"time":"2025.04.09 02:15:00","close":1.10233},{"time":"2025.04.09 02:00:00","close":1.10233},
{"time":"2025.04.09 01:45:00","close":1.10200},{"time":"2025.04.09 01:30:00","close":1.10289},
{"time":"2025.04.09 01:15:00","close":1.10382},{"time":"2025.04.09 01:00:00","close":1.10186},
{"time":"2025.04.09 00:45:00","close":1.10148},{"time":"2025.04.09 00:30:00","close":1.09985},
{"time":"2025.04.09 00:15:00","close":1.09894},{"time":"2025.04.09 00:00:00","close":1.09747},
{"time":"2025.04.08 23:45:00","close":1.09776},{"time":"2025.04.08 23:30:00","close":1.09789},
{"time":"2025.04.08 23:15:00","close":1.09793},{"time":"2025.04.08 23:00:00","close":1.09740},
{"time":"2025.04.08 22:45:00","close":1.09681},{"time":"2025.04.08 22:30:00","close":1.09718},
{"time":"2025.04.08 22:15:00","close":1.09669},{"time":"2025.04.08 22:00:00","close":1.09673},
{"time":"2025.04.08 21:45:00","close":1.09586},{"time":"2025.04.08 21:30:00","close":1.09565},
{"time":"2025.04.08 21:15:00","close":1.09507},{"time":"2025.04.08 21:00:00","close":1.09493},
{"time":"2025.04.08 20:45:00","close":1.09529},{"time":"2025.04.08 20:30:00","close":1.09442},
{"time":"2025.04.08 20:15:00","close":1.09417},{"time":"2025.04.08 20:00:00","close":1.09533},
{"time":"2025.04.08 19:45:00","close":1.09541},{"time":"2025.04.08 19:30:00","close":1.09587},
{"time":"2025.04.08 19:15:00","close":1.09684},{"time":"2025.04.08 19:00:00","close":1.09724},
{"time":"2025.04.08 18:45:00","close":1.09521},{"time":"2025.04.08 18:30:00","close":1.09551},
{"time":"2025.04.08 18:15:00","close":1.09561},{"time":"2025.04.08 18:00:00","close":1.09474},
{"time":"2025.04.08 17:45:00","close":1.09337},{"time":"2025.04.08 17:30:00","close":1.09334},
{"time":"2025.04.08 17:15:00","close":1.09421},{"time":"2025.04.08 17:00:00","close":1.09429},
{"time":"2025.04.08 16:45:00","close":1.09296},{"time":"2025.04.08 16:30:00","close":1.09210},
{"time":"2025.04.08 16:15:00","close":1.09123},{"time":"2025.04.08 16:00:00","close":1.09073},
{"time":"2025.04.08 15:45:00","close":1.09116},{"time":"2025.04.08 15:30:00","close":1.09083},
{"time":"2025.04.08 15:15:00","close":1.09119},{"time":"2025.04.08 15:00:00","close":1.08986},
{"time":"2025.04.08 14:45:00","close":1.09102},{"time":"2025.04.08 14:30:00","close":1.08954},
{"time":"2025.04.08 14:15:00","close":1.09051},{"time":"2025.04.08 14:00:00","close":1.09213},
{"time":"2025.04.08 13:45:00","close":1.09357},{"time":"2025.04.08 13:30:00","close":1.09300},
{"time":"2025.04.08 13:15:00","close":1.09548},{"time":"2025.04.08 13:00:00","close":1.09452},
{"time":"2025.04.08 12:45:00","close":1.09485},{"time":"2025.04.08 12:30:00","close":1.09585},
{"time":"2025.04.08 12:15:00","close":1.09477},{"time":"2025.04.08 12:00:00","close":1.09512},
{"time":"2025.04.08 11:45:00","close":1.09342},{"time":"2025.04.08 11:30:00","close":1.09311},
{"time":"2025.04.07 09:45:00","close":1.09627},{"time":"2025.04.07 09:30:00","close":1.09545},
{"time":"2025.04.07 09:15:00","close":1.09597},{"time":"2025.04.07 09:00:00","close":1.09729},
{"time":"2025.04.07 08:45:00","close":1.09918},{"time":"2025.04.07 08:30:00","close":1.09866},
{"time":"2025.04.07 08:15:00","close":1.09705},{"time":"2025.04.07 08:00:00","close":1.10051},
{"time":"2025.04.07 07:45:00","close":1.10006},{"time":"2025.04.07 07:30:00","close":1.10232},
{"time":"2025.04.07 07:15:00","close":1.10273},{"time":"2025.04.07 07:00:00","close":1.10397},
{"time":"2025.04.07 06:45:00","close":1.10029},{"time":"2025.04.07 06:30:00","close":1.10083},
{"time":"2025.04.07 06:15:00","close":1.10012},{"time":"2025.04.07 06:00:00","close":1.10084},
{"time":"2025.04.07 05:45:00","close":1.10183},{"time":"2025.04.07 05:30:00","close":1.09905},
{"time":"2025.04.07 05:15:00","close":1.09941},{"time":"2025.04.07 05:00:00","close":1.09826},
{"time":"2025.04.07 04:45:00","close":1.09848},{"time":"2025.04.07 04:30:00","close":1.09830},
{"time":"2025.04.07 04:15:00","close":1.09739},{"time":"2025.04.07 04:00:00","close":1.09608},
{"time":"2025.04.07 03:45:00","close":1.09503},{"time":"2025.04.07 03:30:00","close":1.09456},
{"time":"2025.04.07 03:15:00","close":1.09373},{"time":"2025.04.07 03:00:00","close":1.09343},
{"time":"2025.04.07 02:45:00","close":1.09353},{"time":"2025.04.07 02:30:00","close":1.09248},
{"time":"2025.04.07 02:15:00","close":1.09360},{"time":"2025.04.07 02:00:00","close":1.09550},
{"time":"2025.04.07 01:45:00","close":1.09673},{"time":"2025.04.07 01:30:00","close":1.09740},
{"time":"2025.04.07 01:15:00","close":1.09688},{"time":"2025.04.07 01:00:00","close":1.09649},
{"time":"2025.04.07 00:45:00","close":1.09667},{"time":"2025.04.07 00:30:00","close":1.09526},
{"time":"2025.04.07 00:15:00","close":1.09555},{"time":"2025.04.07 00:00:00","close":1.09517},
{"time":"2025.04.06 23:45:00","close":1.09825},{"time":"2025.04.06 23:30:00","close":1.09981},
{"time":"2025.04.06 23:15:00","close":1.09872},{"time":"2025.04.06 23:00:00","close":1.09981},
{"time":"2025.04.06 22:45:00","close":1.09822},{"time":"2025.04.06 22:30:00","close":1.09803},
{"time":"2025.04.06 22:15:00","close":1.09826},{"time":"2025.04.06 22:00:00","close":1.09529},
{"time":"2025.04.06 21:45:00","close":1.09147},{"time":"2025.04.06 21:30:00","close":1.09046},
{"time":"2025.04.06 21:15:00","close":1.08910},{"time":"2025.04.06 21:00:00","close":1.08818},
{"time":"2025.04.04 20:45:00","close":1.09623},{"time":"2025.04.04 20:30:00","close":1.09435},
{"time":"2025.04.04 20:15:00","close":1.09339},{"time":"2025.04.04 20:00:00","close":1.09502},
{"time":"2025.04.04 19:45:00","close":1.09436},{"time":"2025.04.04 19:30:00","close":1.09631},
{"time":"2025.04.04 19:15:00","close":1.09425},{"time":"2025.04.04 19:00:00","close":1.09358},
{"time":"2025.04.04 18:45:00","close":1.09447},{"time":"2025.04.04 18:30:00","close":1.09611},
{"time":"2025.04.04 18:15:00","close":1.09604},{"time":"2025.04.04 18:00:00","close":1.09531},
{"time":"2025.04.04 17:45:00","close":1.09472},{"time":"2025.04.04 17:30:00","close":1.09408},
{"time":"2025.04.04 17:15:00","close":1.09311},{"time":"2025.04.04 17:00:00","close":1.09407},
{"time":"2025.04.04 16:45:00","close":1.09714},{"time":"2025.04.04 16:30:00","close":1.09690},
{"time":"2025.04.04 16:15:00","close":1.09845},{"time":"2025.04.04 16:00:00","close":1.09892},
{"time":"2025.04.04 15:45:00","close":1.10139},{"time":"2025.04.04 15:30:00","close":1.09998},
{"time":"2025.04.04 15:15:00","close":1.09837},{"time":"2025.04.04 15:00:00","close":1.09970},
{"time":"2025.04.04 14:45:00","close":1.09862},{"time":"2025.04.04 14:30:00","close":1.09706},
{"time":"2025.04.04 14:15:00","close":1.09991},{"time":"2025.04.04 14:00:00","close":1.10068},
{"time":"2025.04.04 13:45:00","close":1.10057},{"time":"2025.04.04 13:30:00","close":1.10252},
{"time":"2025.04.04 13:15:00","close":1.10288},{"time":"2025.04.04 13:00:00","close":1.10358},
{"time":"2025.04.04 12:45:00","close":1.10200},{"time":"2025.04.04 12:30:00","close":1.10289},
{"time":"2025.04.04 12:15:00","close":1.10794},{"time":"2025.04.04 12:00:00","close":1.10443},
{"time":"2025.04.04 11:45:00","close":1.10601},{"time":"2025.04.04 11:30:00","close":1.10697},
{"time":"2025.04.04 11:15:00","close":1.10502},{"time":"2025.04.04 11:00:00","close":1.10517},
{"time":"2025.04.04 10:45:00","close":1.10305},{"time":"2025.04.04 10:30:00","close":1.10340},
{"time":"2025.04.04 10:15:00","close":1.10447},{"time":"2025.04.04 10:00:00","close":1.09869},
{"time":"2025.04.04 09:45:00","close":1.09844},{"time":"2025.04.04 09:30:00","close":1.09757},
{"time":"2025.04.04 09:15:00","close":1.09820},{"time":"2025.04.04 09:00:00","close":1.09786},
{"time":"2025.04.04 08:45:00","close":1.09962},{"time":"2025.04.04 08:30:00","close":1.10002},
{"time":"2025.04.04 08:15:00","close":1.10062},{"time":"2025.04.04 08:00:00","close":1.10034},
{"time":"2025.04.04 07:45:00","close":1.10042},{"time":"2025.04.04 07:30:00","close":1.10223},
{"time":"2025.04.04 07:15:00","close":1.10490},{"time":"2025.04.04 07:00:00","close":1.10641},
{"time":"2025.04.04 06:45:00","close":1.10506},{"time":"2025.04.04 06:30:00","close":1.10638},
{"time":"2025.04.04 06:15:00","close":1.10649},{"time":"2025.04.04 06:00:00","close":1.10747},
{"time":"2025.04.04 05:45:00","close":1.10843},{"time":"2025.04.04 05:30:00","close":1.10809},
{"time":"2025.04.04 05:15:00","close":1.11057},{"time":"2025.04.04 05:00:00","close":1.10984},
{"time":"2025.04.04 04:45:00","close":1.10874},{"time":"2025.04.04 04:30:00","close":1.10896},
{"time":"2025.04.04 04:15:00","close":1.10906},{"time":"2025.04.04 04:00:00","close":1.10876},
{"time":"2025.04.04 03:45:00","close":1.10937},{"time":"2025.04.04 03:30:00","close":1.10918},
{"time":"2025.04.04 03:15:00","close":1.10766},{"time":"2025.04.04 03:00:00","close":1.10695},
{"time":"2025.04.04 02:45:00","close":1.10632},{"time":"2025.04.04 02:30:00","close":1.10668},
{"time":"2025.04.04 02:15:00","close":1.10625},{"time":"2025.04.04 02:00:00","close":1.10773},
{"time":"2025.04.04 01:45:00","close":1.10677},{"time":"2025.04.04 01:30:00","close":1.10625},
{"time":"2025.04.04 01:15:00","close":1.10610},{"time":"2025.04.04 01:00:00","close":1.10589},
{"time":"2025.04.04 00:45:00","close":1.10606},{"time":"2025.04.04 00:30:00","close":1.10603},
{"time":"2025.04.04 00:15:00","close":1.10403},{"time":"2025.04.04 00:00:00","close":1.10432},
{"time":"2025.04.03 23:45:00","close":1.10452},{"time":"2025.04.03 23:30:00","close":1.10467},
{"time":"2025.04.03 23:15:00","close":1.10446},{"time":"2025.04.03 23:00:00","close":1.10524},
{"time":"2025.04.03 22:45:00","close":1.10642},{"time":"2025.04.03 22:30:00","close":1.10631},
{"time":"2025.04.03 22:15:00","close":1.10582},{"time":"2025.04.03 22:00:00","close":1.10577},
{"time":"2025.04.03 21:45:00","close":1.10515},{"time":"2025.04.03 21:30:00","close":1.10497},
{"time":"2025.04.03 21:15:00","close":1.10505},{"time":"2025.04.03 21:00:00","close":1.10488},
{"time":"2025.04.03 20:45:00","close":1.10514},{"time":"2025.04.03 20:30:00","close":1.10448},
{"time":"2025.04.03 20:15:00","close":1.10312},{"time":"2025.04.03 20:00:00","close":1.10253},
{"time":"2025.04.03 19:45:00","close":1.10275},{"time":"2025.04.03 19:30:00","close":1.10164},
{"time":"2025.04.03 19:15:00","close":1.10192},{"time":"2025.04.03 19:00:00","close":1.10320},
{"time":"2025.04.03 18:45:00","close":1.10373},{"time":"2025.04.03 18:30:00","close":1.10362},
{"time":"2025.04.03 18:15:00","close":1.10322},{"time":"2025.04.03 18:00:00","close":1.10236},
{"time":"2025.04.03 17:45:00","close":1.10245},{"time":"2025.04.03 17:30:00","close":1.10222},
{"time":"2025.04.03 17:15:00","close":1.10273},{"time":"2025.04.03 17:00:00","close":1.10267},
{"time":"2025.04.03 16:45:00","close":1.10386},{"time":"2025.04.03 16:30:00","close":1.10404},
{"time":"2025.04.03 16:15:00","close":1.10367},{"time":"2025.04.03 16:00:00","close":1.10491},
{"time":"2025.04.03 15:45:00","close":1.10506},{"time":"2025.04.03 15:30:00","close":1.10452},
{"time":"2025.04.03 15:15:00","close":1.10613},{"time":"2025.04.03 15:00:00","close":1.10922},
{"time":"2025.04.03 14:45:00","close":1.11182},{"time":"2025.04.03 14:30:00","close":1.11197},
{"time":"2025.04.03 14:15:00","close":1.10950},{"time":"2025.04.03 14:00:00","close":1.10981},
{"time":"2025.04.03 13:45:00","close":1.10784},{"time":"2025.04.03 13:30:00","close":1.10911},
{"time":"2025.04.03 13:15:00","close":1.10943},{"time":"2025.04.03 13:00:00","close":1.11064},
{"time":"2025.04.03 12:45:00","close":1.10816},{"time":"2025.04.03 12:30:00","close":1.10910},
{"time":"2025.04.03 12:15:00","close":1.10858},{"time":"2025.04.03 12:00:00","close":1.10867},
{"time":"2025.04.03 11:45:00","close":1.10876},{"time":"2025.04.03 11:30:00","close":1.10839},
{"time":"2025.04.03 11:15:00","close":1.10570},{"time":"2025.04.03 11:00:00","close":1.10596},
{"time":"2025.04.03 10:45:00","close":1.10521},{"time":"2025.04.03 10:30:00","close":1.10696},
{"time":"2025.04.03 10:15:00","close":1.10859},{"time":"2025.04.03 10:00:00","close":1.11052},
{"time":"2025.04.03 09:45:00","close":1.10305},{"time":"2025.04.03 09:30:00","close":1.10280},
{"time":"2025.04.03 09:15:00","close":1.10336},{"time":"2025.04.03 09:00:00","close":1.10304},
{"time":"2025.04.03 08:45:00","close":1.10093},{"time":"2025.04.03 08:30:00","close":1.10092},
{"time":"2025.04.03 08:15:00","close":1.09885},{"time":"2025.04.03 08:00:00","close":1.09803},
{"time":"2025.04.03 07:45:00","close":1.09707},{"time":"2025.04.03 07:30:00","close":1.09658},
{"time":"2025.04.03 07:15:00","close":1.09497},{"time":"2025.04.03 07:00:00","close":1.09733},
{"time":"2025.04.03 06:45:00","close":1.09896},{"time":"2025.04.03 06:30:00","close":1.09775},
{"time":"2025.04.03 06:15:00","close":1.09488},{"time":"2025.04.03 06:00:00","close":1.09457},
{"time":"2025.04.03 05:45:00","close":1.09444},{"time":"2025.04.03 05:30:00","close":1.09515},
{"time":"2025.04.03 05:15:00","close":1.09431},{"time":"2025.04.03 05:00:00","close":1.09171},
{"time":"2025.04.03 04:45:00","close":1.09069},{"time":"2025.04.03 04:30:00","close":1.09104},
{"time":"2025.04.03 04:15:00","close":1.09109},{"time":"2025.04.03 04:00:00","close":1.09110},
{"time":"2025.04.03 03:45:00","close":1.09148},{"time":"2025.04.03 03:30:00","close":1.09118},
{"time":"2025.04.03 03:15:00","close":1.09196},{"time":"2025.04.03 03:00:00","close":1.09115},
{"time":"2025.04.03 02:45:00","close":1.09122},{"time":"2025.04.03 02:30:00","close":1.09207},
{"time":"2025.04.03 02:15:00","close":1.09220},{"time":"2025.04.03 02:00:00","close":1.09134},
{"time":"2025.04.03 01:45:00","close":1.09132},{"time":"2025.04.03 01:30:00","close":1.09137},
{"time":"2025.04.03 01:15:00","close":1.09078},{"time":"2025.04.03 01:00:00","close":1.08970},
{"time":"2025.04.03 00:45:00","close":1.08906},{"time":"2025.04.03 00:30:00","close":1.08995},
{"time":"2025.04.03 00:15:00","close":1.08831},{"time":"2025.04.03 00:00:00","close":1.08905},
{"time":"2025.04.02 23:45:00","close":1.09044},{"time":"2025.04.02 23:30:00","close":1.09068},
{"time":"2025.04.02 23:15:00","close":1.08874},{"time":"2025.04.02 23:00:00","close":1.08552},
{"time":"2025.04.02 22:45:00","close":1.08389},{"time":"2025.04.02 22:30:00","close":1.08277},
{"time":"2025.04.02 22:15:00","close":1.08221},{"time":"2025.04.02 22:00:00","close":1.08161},
{"time":"2025.04.02 21:45:00","close":1.08274},{"time":"2025.04.02 21:30:00","close":1.08286},
{"time":"2025.04.02 21:15:00","close":1.08156},{"time":"2025.04.02 21:00:00","close":1.08350},
{"time":"2025.04.02 20:45:00","close":1.08507},{"time":"2025.04.02 20:30:00","close":1.08184},
INFO:werkzeug:127.0.0.1 - - [09/Apr/2025 09:04:18] "POST /analyze HTTP/1.1" 200 -

Ниже представлены логи из вкладки "Эксперты" MetaTrader 5, содержащие комментарии сервера Python к анализу корреляции. В логах содержатся подробные данные, полученные за предыдущие дни вплоть до текущего дня, показывающие, как менялись две валютные пары, EURUSD и GBPUSD, относительно друг друга. В комментарии дается интерпретация графика корреляции, поясняется, что за исследуемый период пары, как правило, сохраняют сильную положительную корреляцию. 

2025.04.09 00:57:33.296 Correlation Pathfinder (GBPUSD,M15)     Server response: 
{"commentary":"The overall correlation is weakly positive, suggesting occasional movement together but 
limited consistency, which may offer diversification opportunities.\nRecently, the rolling correlation is at 
0.82. This high correlation suggests near mirror-like movement. Relative strength approaches may need 
reconsideration for diversification.","correlation":0.3697032305325312,"message":"Plot saved as rolling_
correlation.png"}
Это указывает на то, что они, как правило, движутся синхронно, хотя иногда и наблюдаются небольшие отклонения. Эти отклонения могут указывать на временную дивергенцию рынка, подчеркивая потенциальные возможности для диверсификации портфеля или хеджирования. В целом, логи подтверждают успешную передачу данных и их точную обработку, предоставляя информацию, которая может помочь усовершенствовать торговые стратегии с учетом меняющихся взаимоотношений между валютными парами.
2025.04.09 00:
57 :33.296 Correlation Pathfinder (EURUSD,M15)     Server response: 
{"commentary":"The overall correlation is weakly positive, suggesting occasional movement together but 
limited consistency, which may offer diversification opportunities.\nRecently, the rolling correlation is at
 0.83. This high correlation suggests near mirror-like movement. Relative strength approaches may need 
reconsideration for diversification.","correlation":0.33874205977082567,"message":"Plot saved as 
rolling_correlation.png"}

Ниже представлен результат анализа корреляционного графика. Со 2 по 9 апреля скользящая корреляция между EURUSD и GBPUSD оставалась высокой, близкой к 0,8–1,0, что свидетельствует о том, что пары в целом двигались синхронно. В некоторые моменты корреляция резко падала примерно до 0,3, что указывает на кратковременное расхождение, вероятно, вызванное непродолжительными рыночными событиями или новостями, касающимися конкретных валют. Корреляция быстро восстановилась и приблизилась к значению 1,0, подтверждая, что лежащие в основе рыночные силы перестраивают эти валютные пары. Трейдеры могут использовать эти периодические падения цен как сигналы для выявления возможностей дивергенции, а затем наблюдать за ситуацией до тех пор, пока не вернутся нормальные уровни корреляции.

Корреляция

Рис 4. Скользящая корреляция


Заключение

Эта схема дает наглядное представление о рабочем процессе системы, отслеживая все этапы — от получения данных в MetaTrader 5 до анализа и комментариев на сервере Python. Узлы, обозначенные буквами от A до H, представляют каждый этап процесса, иллюстрируя, как данные собираются, упаковываются в формат JSON, передаются на сервер, анализируются с помощью Pandas, визуализируются с помощью Matplotlib и, наконец, сопровождаются пояснительными комментариями перед возвратом результатов анализа.

Дата Название инструмента  Описание Версия  Обновления  Примечания
01/10/24 Chart Projector Скрипт для наложения эффекта призрака на движение цены за предыдущий день 1.0 Первоначальная версия Инструмент номер 1
18/11/24 Analytical Comment Предоставляет информацию за предыдущий день в табличном формате, а также прогнозирует будущее направление рынка 1.0 Первоначальная версия Инструмент номер 2
27/11/24 Analytics Master Регулярное обновление рыночных показателей каждые два часа  1.01 Вторая версия Инструмент номер 3
02/12/24 Analytics Forecaster  Регулярное обновление рыночных показателей каждые два часа с интеграцией с Telegram 1.1 Третья версия Инструмент номер 4
09/12/24 Volatility Navigator Советник анализирует рыночные условия с помощью полос Боллинджера, RSI и ATR 1.0 Первоначальная версия Инструмент номер 5
19/12/24 Mean Reversion Signal Reaper  Анализирует рынок и генерирует сигналы, используя стратегию возврата к среднему  1.0  Первоначальная версия  Инструмент номер 6 
9/01/25  Signal Pulse  Анализирует несколько таймфреймов 1.0  Первоначальная версия  Инструмент номер 7 
17/01/25  Metrics Board  Панель с кнопками для анализа  1.0  Первоначальная версия Инструмент номер 8 
21/01/25 External Flow Аналитика с помощью внешних библиотек 1.0  Первоначальная версия Инструмент номер 9 
27/01/25 VWAP Взвешенная по объему средняя цена   1.3  Первоначальная версия  Инструмент номер 10 
02/02/25  Heikin Ashi  Сглаживание тренда и идентификация сигналов разворота  1.0  Первоначальная версия  Инструмент номер 11
04/02/25  FibVWAP  Генерация сигнала с помощью анализа Python  1.0  Первоначальная версия  Инструмент номер 12
14/02/25  RSI DIVERGENCE  Дивергенция цены и RSI  1.0  Первоначальная версия  Инструмент номер 13 
17/02/25  Parabolic Stop and Reverse (PSAR)  Автоматизация стратегии PSAR 1.0 Первоначальная версия  Инструмент номер 14
20/02/25  Скрипт Quarters Drawer  Нанесение уровней четвертей на график  1.0  Первоначальная версия  Инструмент номер 15 
27/02/25  Intrusion Detector Обнаружение и оповещение о достижении ценой уровней четвертей 1.0   Первоначальная версия Инструмент номер 16 
27/02/25  TrendLoom Tool Панель мультитаймфреймового анализа 1.0 Первоначальная версия Инструмент номер 17
11/03/25  Quarters Board  Панель с кнопками для включения/отключения уровней четвертей  1.0  Первоначальная версия Инструмент номер 18
26/03/25  ZigZag Analyzer  Построение линий тренда с помощью индикатора ZigZag  1.0  Первоначальная версия  Инструмент номер 19 
10/04/25  Correlation Pathfinder Построение графиков корреляции валютных курсов с использованием библиотек Python 1.0 Первоначальная версия  Инструмент номер 20 


Перевод с английского произведен MetaQuotes Ltd.
Оригинальная статья: https://www.mql5.com/en/articles/17742

Прикрепленные файлы |
plotter.py (4.46 KB)
Знакомство с языком MQL5 (Часть 28): Освоение API и функции WebRequest в языке MQL5 (II) Знакомство с языком MQL5 (Часть 28): Освоение API и функции WebRequest в языке MQL5 (II)
В этой статье вы научитесь получать ценовые данные с внешних платформ с помощью API и функции WebRequest на языке MQL5. Вы узнаете, как структурируются URL, как форматируются ответы API, как преобразовать серверные данные в читаемые строки, а также как находить конкретные значения в ответах JSON и получать их оттуда.
Интеграция AI-модели в существующую торговую стратегию на MQL5 Интеграция AI-модели в существующую торговую стратегию на MQL5
Данная статья посвящена интеграции обученной модели искусственного интеллекта (например, модели обучения с подкреплением LSTM или прогностической модели на основе машинного обучения) в существующую торговую стратегию на MQL5.
Особенности написания экспертов Особенности написания экспертов
Написание и тестирование экспертов в торговой системе MetaTrader 4.
Создание торговой панели администратора на MQL5 (Часть IX): Организация кода (V). Класс AnalyticsPanel Создание торговой панели администратора на MQL5 (Часть IX): Организация кода (V). Класс AnalyticsPanel
В этой статье мы рассмотрим, как получать рыночные данные в реальном времени и информацию о торговом счете, выполнять различные вычисления и отображать результаты на настраиваемой панели. Для достижения этой цели мы углубимся в разработку класса AnalyticsPanel, который будет включать в себя все эти функции, в том числе создание панелей. Эта работа является частью нашего продолжающегося расширения советника новой панели администратора (New Admin Panel EA), внедряющей расширенные функции с использованием принципов модульного проектирования и лучших практик организации кода.