English 中文 Español Deutsch 日本語 Português
preview
Интеграция MQL5 с пакетами обработки данных (Часть 2): Машинное обучение и предиктивная аналитика

Интеграция MQL5 с пакетами обработки данных (Часть 2): Машинное обучение и предиктивная аналитика

MetaTrader 5Торговые системы |
469 3
Hlomohang John Borotho
Hlomohang John Borotho

Введение

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

Процесс включает использование мощных библиотек обработки данных и машинного обучения Python, таких как scikit-learn, в сочетании с MQL5. Такая интеграция позволяет трейдерам обучать прогностические модели с использованием исторических данных, проверять их эффективность с помощью методов тестирования на истории, а затем использовать эти модели для принятия торговых решений в реальном времени. Гибкость сочетания этих инструментов позволяет создавать стратегии, выходящие за рамки типичных технических индикаторов, включая предиктивную аналитику и распознавание паттернов, которые могут значительно улучшить результаты торговли.


Сбор исторических данных

Для начала нам нужны исторические данные из MetaTrader 5 в .csv-формате. Запустите платформу MetaTrader, "Сервис" > "Настройки" вкладка "Графики". Затем нужно выбрать количество баров на графике, которое необходимо загрузить. Лучше всего выбрать вариант с неограниченным количеством баров, поскольку мы будем работать с датой и не будем знать, сколько баров в определенном периоде времени.

"Сервис" > "Настройки"

После этого загрузим реальные данные. "Вид" > "Символы". Вы окажетесь на вкладке "Спецификация". Переключитесь на вкладку "Бары" или "Тики" в зависимости от того, какие данные вы хотите загрузить. Введите начальную и конечную даты периода исторических данных, которые вы хотите загрузить, после чего нажмите "Запрос", чтобы загрузить данные и сохранить их в формате .csv.

Бары для скачивания

Исторические данные загружены. Теперь необходимо загрузить и настроить среду Jupyter Lab для анализа. Перейдите на официальный сайт Jupyter Lab и следуйте простым шагам, чтобы загрузить его. В зависимости от вашей операционной системы у вас будет несколько вариантов установки с помощью pip, conda или brew.


Обработка исторических данных MetaTrader 5 в Jupyter Lab

Для успешной загрузки исторических данных MetaTrader 5 в Jupyter Lab нужно знать папку, которую вы выбрали для загрузки данных, а затем в Jupyter Lab просто перейти в эту папку. Для начала вам нужно будет загрузить данные и проверить имена столбцов. Нам необходимо проверить имена столбцов, чтобы правильно обрабатывать их и избегать ошибок, которые могут возникнуть при использовании неправильного имени столбца.

код python:

import pandas as pd

# assign variable to the historical data
file_path = '/home/int_junkie/Documents/ML/predi/XAUUSD.m_H1_201510010000_202408052300.csv'

data = pd.read_csv(file_path, delimiter='\t')

# Display the first few rows and column names
print(data.head())
print(data.columns)

Результат:

Вывод исторических данных

Мы работаем с историческими данными MetaTrader 5 с 2015 по 2024 год - 9 лет. Такого рода данные помогают охватить широкие рыночные циклы. Набор данных, вероятно, будет охватывать различные фазы рынка, что позволит лучше понять и смоделировать эти циклы. Более длинные наборы данных снижают вероятность чрезмерной подгонки, предоставляя более полный диапазон сценариев.

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

Линейный график на основе исторических данных

data.plot.line(y = "<CLOSE>", x = "<DATE>", use_index = True)

Результат:

График цены

Мы используем приведенный выше код при визуализации данных временных рядов, таких как финансовые активы, с течением времени. Если индекс фрейма данных (Data-Frame) уже содержит даты, вы можете пропустить указание x="<DATE>" и просто использовать use_index=True.

del data["<VOL>"]
del data["<SPREAD>"]

Затем мы удаляем указанные столбцы из наших исторических данных. Для этого мы используем библиотеку pandas.

data.head()

Результат:

Фрейм данных

Из приведенного выше результата видно, что указанные столбцы действительно были удалены.

# We add a colunm for tommorows price
data["<NexH>"] = data["<CLOSE>"].shift(-1)

1. 'data["<NexH>"]':

  • Во фрейм данных 'data' добавляется новый столбец "<NexH>" (следующий час). Значение в этом столбце будет представлять цены закрытия на следующий час относительно каждой строки.

2. 'data["<CLOSE>"].shift(-1)':

  • data["<CLOSE>"] относится к существующему столбцу во фрейме данных, который содержит цены закрытия для каждой даты и времени.
  • Метод .shift(-1) сдвигает дату-время в столбце <CLOSE> вверх на 1 строку (потому что аргумент равен '-1'), что фактически перемещает каждое значение в предыдущую строку.
  • В результате значение, которое изначально соответствовало определенной дате, теперь будет отображаться в строке, соответствующей предыдущей дате.

Результат:

Столбец Next Hour

data["<TRGT>"] = (data["<NexH>"] > data["<CLOSE>"]).astype(int)

data

Затем мы используем код выше для создания нового столбца во фрейме данных 'data', который содержит двоичные значения (0 или 1), указывающие, превышает ли максимальная цена следующего периода (NexH) текущую цену закрытия (<CLOSE>).

1. 'data["<TRGT>"]':

  • Это новый столбец <TRGT> (цель) во фрейме данных 'data'. В нем будут храниться двоичные целевые значения (0 или 1) в зависимости от условия.

2. '(data["<NexH>"] > data["<CLOSE>"])':

  • Выражение сравнивает значение в столбце <NexH> (максимальная цена следующего периода) со значением в столбце <CLOSE> (текущая цена закрытия) для каждой строки.
  • Это логический ряд, где каждое значение равно либо True (если следующий максимум больше текущего закрытия), либо False (если нет).

3. '.astype(int)':

  • Функция преобразует логические значения (True или False) в целые числа (1 или 0 соответственно).
  • True становится 1, а False превращается в 0.

Результат:

Цель

from sklearn.ensemble import RandomForestClassifier

model = RandomForestClassifier(n_estimators = 50, min_samples_split = 50, random_state = 1)

train = data.iloc[:-50]
test = data.iloc[-50:]

predictors = ["<CLOSE>","<TICKVOL>", "<OPEN>", "<HIGH>", "<LOW>"]
model.fit(train[predictors], train["<TRGT>"])

Результат:

Случайный лес

1. Импорт классификатора случайного леса (Random Forest Classifier):

  • Random-Forest-Classifier - это сборная модель машинного обучения, которая строит несколько деревьев решений и объединяет их результаты для повышения точности прогнозирования и контроля переобучения.

2. Инициализация модели:

  • estimator - количество деревьев решений в лесу. В этом случае модель построит 50 деревьев.
  • min_sample_split - минимальное количество выборок, необходимое для разделения внутреннего узла. Более высокое значение снижает переобучение, гарантируя, что разделения будут происходить только при наличии достаточного количества данных.
  • random_state - случайное начальное значение для воспроизводимости результатов. Использование одного и того же начального числа (например, 1) будет давать одни и те же результаты при каждом запуске кода.

3. Разделение данных на обучающие и тестовые наборы:

  • data.iloc[:-50] выбирает все строки, кроме последних 50, в качестве обучающих данных.
  • data.iloc[-50:] выбирает последние 50 строк в качестве тестовых данных
  • Такое разделение обычно используется в данных временных рядов, когда модель обучается на исторических данных и тестируется на самых последних данных для оценки эффективности будущих прогнозов.

4. Указание переменных-предикторов:

  • Список "предикторов" содержит названия столбцов, представляющих признаки, используемые моделью для составления прогнозов. Он включает в себя <CLOSE>, <TICKVOL>, <OPEN>, <HIGH> и <LOW>).

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

Измерение точности модели

from sklearn.metrics import precision_score

prcsn = model.predict(test[predictors])

Мы импортируем функцию precision-score (показатель точности) из модуля sklearn.metrics. Показатель точности — это метрика, используемая для оценки моделей классификации, особенно полезная, когда классы несбалансированы. Он измеряет, сколько из прогнозируемых положительных результатов на самом деле являются положительными. Высокая точность указывает на низкие показатели положительных результатов.

Уравнение точности

prcsn = pd.Series(prcsn, index = test.index)

Затем мы преобразуем прогнозы (prcsn) в Series Pandas, сохраняя индекс из тестового набора данных.

precision_score(test["<TRGT>"], prcsn)

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

Результат:

Показатель точности

cmbnd = pd.concat([test["<TRGT>"], prcsn], axis = 1)

cmbnd.plot()

Мы объединяем фактические целевые значения и прогнозируемые значения модели в единый фрейм данных для более легкого анализа.

Результат:

Целевое и реальное значения

def predors(train, test, predictors, model):
    model.fit(train[predictors], train["<TRGT>"])
    prcsn = model.predict(test[predictors])
    prcsn = pd.Series(prcsn, index = test.index, name = "Predictions")
    cmbnd = pd.concat([test["<TRGT>"], prcsn], axis = 1)
    return cmbnd

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

def backtestor(data, model, predictors, start = 2500, step = 250):
    all_predictions = []

    for i in range(start, data.shape[0], step):
        train = data.iloc[0:i].copy()
        test = data.iloc[i:(i + step)].copy()
        predictions = predors(train, test, predictors, model)
        all_predictions.append(predictions)
    return pd.concat(all_predictions)

Функция выполняет повторяющееся тестирование на истории (rolling back-test) на наборе данных временного ряда с использованием модели машинного обучения. Тестирование на истории оценивает эффективность модели, имитируя прогнозы так, как если бы они были сделаны в реальной торговой среде, где данные раскрываются постепенно с течением времени.

predictions = backtestor(data, model, predictors)

Запускает функцию backtestor, используя указанный набор данных (data), модель машинного обучения (model) и переменные-предикторы (predictors). Выполняет повторяющееся тестирование на истории, и полученные прогнозы сохраняются в переменной predictions.

predictions["Predictions"].value_counts()

Мы подсчитываем количество вхождений каждого уникального значения в столбце Predictions фрейма данных 'prediction'.

Результат:

Predictions

precision_score(predictions["<TRGT>"], predictions["Predictions"])

Рассчитывает точность прогноза модели. Precision (точность) — это показатель, который измеряет точность положительных прогнозов.

Результат:

P_score

Уравнение точности

predictions["<TRGT>"].value_counts() / predictions.shape[0]

Вычисляет долю каждого уникального значения в столбце <TRGT> относительно общего числа прогнозов.

Результат:

Доля

horizons = [2, 5, 55, 125, 750]
new_predictors = []

# Ensure only numeric columns are used for rolling calculations
numeric_columns = data.select_dtypes(include=[float, int]).columns

for i in horizons:
    # Calculate rolling averages for numeric columns only
    rolling_averages = data[numeric_columns].rolling(i).mean()
    
    # Generate the ratio column
    ratio_column = f"Close_Ratio_{i}"
    data[ratio_column] = data["<CLOSE>"] / rolling_averages["<CLOSE>"]
    
    # Generate the trend column
    trend_column = f"Trend_{i}"
    data[trend_column] = data["<TRGT>"].shift(1).rolling(i).sum()
    
    new_predictors += [ratio_column, trend_column]
data

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

Результат:

Новые столбцы предиктора

data = data.dropna()

Мы удаляем все строки с отсутствующими значениями во фрейме данных.

def predict(train, test, predictors, model):
    model.fit(train[predictors], train["<TRGT>"])
    prcsn = model.predict_proba(test[predictors])[:1]
    prcsn[prcsn >= .6] = 1
    prcsn[prcsn < .6] = 0
    prcsn = pd.Series(prcsn, index = test.index, name = "Predictions")
    cmbnd = pd.concat([test["<TRGT>"], prcsn], axis = 1)
    return cmbnd

Модель обучается на обучающем наборе данных с использованием выбранных предикторов и целевой переменной. Для порогового значения и прогнозов мы применяем пользовательское пороговое значение 0,6. Если вероятность для класса 1 составляет 0,6 или выше, модель предсказывает 1. В противном случае - 0. Такая корректировка позволяет модели быть более консервативной и требует большей уверенности перед подачей сигнала о сделке.

predictions = backtestor(data, model, new_predictors)
predictions["Predictions"].value_counts()
precision_score(predictions["<TRGT>"], predictions["Predictions"])

Результат:

Второе значение точности

Наш показатель точности немного вырос — до 0,52, если округлить.


Обучение модели и ее экспорт в ONNX

import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.model_selection import train_test_split
import onnx
import skl2onnx
from skl2onnx import convert_sklearn
from skl2onnx.common.data_types import FloatTensorType

# Load and preprocess your data (example)
# Replace this with your actual data loading process
#data = pd.read_csv('your_data.csv')  # Replace with your actual data source
#data = data.dropna()

# Define predictors and target
predictors = ["<CLOSE>", "<TICKVOL>", "<OPEN>", "<HIGH>", "<LOW>"]
target = "<TRGT>"

# Split data into train and test sets
train, test = train_test_split(data, test_size=0.2, shuffle=False)

# Define and train the model
model = RandomForestClassifier(n_estimators=50, min_samples_split=50, random_state=1)
model.fit(train[predictors], train[target])

# Export the trained model to ONNX format
initial_type = [('float_input', FloatTensorType([None, len(predictors)]))]
onnx_model = convert_sklearn(model, initial_types=initial_type)

# Save the ONNX model to a file
with open("random_forest_model.onnx", "wb") as f:
    f.write(onnx_model.SerializeToString())

Мы обучаем нашу модель, затем она конвертируется, экспортируется и сохраняется в формате ONNX с помощью skl2onnx. Затем мы копируем нашу сохраненную модель в папку Files MQL5, где мы сможем получить к ней доступ.

Сохраненная модель



Собираем всё вместе в MQL5

Загрузим модель в Oninit().

#include <Trade/Trade.mqh>
#define   ModelName          "RandomForestClassifier"
#define   ONNXFilename       "random_forest_model.onnx"

// Single ONNX model resource
#resource "\\Files\\random_forest_model.onnx" as const uchar ExtModelDouble[];

input double lotsize = 0.1;     // Trade lot size
input double stoploss = 20;     // Stop loss in points
input double takeprofit = 50;   // Take profit in points

// Trading functions
CTrade m_trade;

Включаемые файлы и глобальные переменные в глобальной области. Мы также указываем, что модель ONNX встроена в MQL5 как двоичный ресурс. Для включения внешних файлов используется #resource.

//+------------------------------------------------------------------+
//| Run classification using double values                           |
//+------------------------------------------------------------------+
bool RunModel(long model, vector &input_vector, vector &output_vector)
{
    ulong batch_size = input_vector.Size() / 5; // Assuming 5 input features
    if (batch_size == 0)
        return (false);

    output_vector.Resize((int)batch_size);

    // Prepare input tensor
    double input_data[];
    ArrayResize(input_data, input_vector.Size());

    for (int k = 0; k < input_vector.Size(); k++)
        input_data[k] = input_vector[k];

    // Set input shape
    ulong input_shape[] = {batch_size, 5}; // 5 input features for each prediction
    OnnxSetInputShape(model, 0, input_shape);

    // Prepare output tensor
    double output_data[];
    ArrayResize(output_data, (int)batch_size);

    // Set output shape (binary classification)
    ulong output_shape[] = {batch_size, 2}; // Output shape for probability (0 or 1)
    OnnxSetOutputShape(model, 0, output_shape);

    // Run the model
    bool res = OnnxRun(model, ONNX_DEBUG_LOGS, input_data, output_data);

    if (res)
    {
        // Copy output to vector (only keeping the class with highest probability)
        for (int k = 0; k < batch_size; k++)
            output_vector[k] = (output_data[2 * k] < output_data[2 * k + 1]) ? 1.0 : 0.0;
    }

    return (res);
}

Функция RunModel представляет собой модель ONNX, которую мы обучили выполнять бинарную классификацию. Функция определяет прогнозируемый класс (0 или 1) на основе того, какой класс имеет более высокую вероятность, и сохраняет результаты в выходном векторе.

//+------------------------------------------------------------------+
//| Generate input data for prediction                               |
//+------------------------------------------------------------------+
vector input_data()
{
    vector input_vector;
    MqlRates rates[];

    // Get the last 5 bars of data
    if (CopyRates(Symbol(), PERIOD_H1, 5, 1, rates) > 0)
    {
        input_vector.Resize(5 * 5); // 5 input features for each bar

        for (int i = 0; i < 5; i++)
        {
            input_vector[i * 5] = rates[i].open;
            input_vector[i * 5 + 1] = rates[i].high;
            input_vector[i * 5 + 2] = rates[i].low;
            input_vector[i * 5 + 3] = rates[i].close;
            input_vector[i * 5 + 4] = rates[i].tick_volume;
        }
    }

    return (input_vector);
}

//+------------------------------------------------------------------+
//| Check if there is a new bar                                      |
//+------------------------------------------------------------------+
bool NewBar()
{
    static datetime last_time = 0;
    datetime current_time = iTime(Symbol(), Period(), 0);

    if (current_time != last_time)
    {
        last_time = current_time;
        return (true);
    }
    return (false);
}

//+------------------------------------------------------------------+
//| Check if a position of a certain type exists                     |
//+------------------------------------------------------------------+
bool PosExists(int type)
{
    for (int i = PositionsTotal() - 1; i >= 0; i--)
    {
        if (PositionGetInteger(POSITION_TYPE) == type && PositionGetString(POSITION_SYMBOL) == Symbol())
            return (true);
    }
    return (false);
}

//+------------------------------------------------------------------+
//| Script program initialization                                    |
//+------------------------------------------------------------------+
int OnInit()
{
    Print("Initializing ONNX model...");

    // Initialize the ONNX model
    long model = OnnxCreateFromBuffer(ExtModelDouble, ONNX_DEFAULT);
    if (model == INVALID_HANDLE)
    {
        Print("Error loading ONNX model: ", GetLastError());
        return INIT_FAILED;
    }

    // Store the model handle for further use
    GlobalVariableSet("model_handle", model);
    return (INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
    if (NewBar()) // Trade at the opening of a new candle
    {
        vector input_vector = input_data();
        vector output_vector;

        // Retrieve the model handle
        long model = GlobalVariableGet("model_handle");
        if (model == INVALID_HANDLE)
        {
            Print("Invalid model handle.");
            return;
        }

        bool prediction_success = RunModel(model, input_vector, output_vector);
        if (!prediction_success || output_vector.Size() == 0)
        {
            Print("Prediction failed.");
            return;
        }

        long signal = output_vector[0]; // The predicted class (0 or 1)

        MqlTick ticks;
        if (!SymbolInfoTick(Symbol(), ticks))
            return;

        if (signal == 1) // Bullish signal
        {
            if (!PosExists(POSITION_TYPE_BUY)) // No buy positions exist
            {
                if (!m_trade.Buy(lotsize, Symbol(), ticks.ask, ticks.bid - stoploss * Point(), ticks.ask + takeprofit * Point())) // Open a buy trade
                    Print("Failed to open a buy position, error = ", GetLastError());
            }
        }
        else if (signal == 0) // Bearish signal
        {
            if (!PosExists(POSITION_TYPE_SELL)) // No sell positions exist
            {
                if (!m_trade.Sell(lotsize, Symbol(), ticks.bid, ticks.ask + stoploss * Point(), ticks.bid - takeprofit * Point())) // Open a sell trade
                    Print("Failed to open a sell position, error = ", GetLastError());
            }
        }
    }
}

//+------------------------------------------------------------------+
//| Script program deinitialization                                  |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    // Release the ONNX model
    long model = GlobalVariableGet("model_handle");
    if (model != INVALID_HANDLE)
    {
        OnnxRelease(model);
    }
}
Во время инициализации модель загружается, а ее хэндл сохраняется для дальнейшего использования. В функции OnTick() скрипт запускает модель при обнаружении нового бара. Мы используем прогноз модели (0 для медвежьего тренда и 1 - для бычьего) и совершаем сделки соответствующим образом. Сделки на покупку размещаются, когда модель предсказывает бычий тренд, а сделки на продажу — при медвежьем тренде.



Заключение

Мы использовали пакет обработки данных (Jupyter Lab) для обработки исторических данных, разработали и обучили модель с использованием машинного обучения, чтобы иметь возможность делать прогнозы. Мы изучили важнейшие шаги, необходимые для бесперебойной интеграции и работы. Затем мы сосредоточились на загрузке и обработке модели в MQL5, встроив ее в качестве ресурса и обеспечив правильную инициализацию модели и ее доступность во время выполнения.

В заключение следует отметить, что мы интегрировали модель ONNX в торговую среду MQL5 для улучшения процесса принятия решений с использованием машинного обучения. Процесс начался с загрузки модели в среду MQL5. Затем мы настроили советник для сбора соответствующих рыночных данных, предварительной обработки их в векторы признаков и передачи их в модель для прогнозирования. Логика была разработана для совершения сделок на основе выходных данных модели. Позиции открываются только при обнаружении нового бара и отсутствии открытых противоположных сделок. Кроме того, система выполняет проверки позиций, управление ошибками и перераспределение ресурсов, обеспечивая надежное и эффективное торговое решение. Эта реализация демонстрирует гармоничное сочетание финансового анализа на основе искусственного интеллекта, что позволяет автоматизировать торговые стратегии, которые адаптируются к рыночным условиям в режиме реального времени.


Ссылки

Создание модели


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

Прикрепленные файлы |
prdctv_anlyss.ipynb (161.62 KB)
Последние комментарии | Перейти к обсуждению на форуме трейдеров (3)
Adam Karim
Adam Karim | 21 авг. 2024 в 01:57
Отличная статья! Я следовал вашему коду я получаю ошибку : 2024.08.21 02:57:11.290 adas (XAUUSD,H1) array out of range in 'adas.mq5' (74,41)

talebih06
talebih06 | 28 авг. 2024 в 20:35

Здравствуйте

Я также столкнулся с точно такой же ошибкой

amrhamed83
amrhamed83 | 25 окт. 2024 в 14:02
Привет ... я прочитал все ваши статьи и посмотрел на код..... есть ошибки во всех из них.... я надеюсь, что вы пересмотрите все коды, которые вы публикуете ...|
я не знаю, но по крайней мере, должны быть некоторые qc на окончательный код, представленный
Торговая стратегия SP500 на языке MQL5 для начинающих Торговая стратегия SP500 на языке MQL5 для начинающих
Узнайте, как использовать язык MQL5 для точного прогнозирования индекса S&P 500, добавляя классический технический анализ для обеспечения стабильности и объединяя алгоритмы с проверенными временем принципы для получения надежной информации о рынке.
Нейросети в трейдинге: Гибридные модели последовательностей графов (Окончание) Нейросети в трейдинге: Гибридные модели последовательностей графов (Окончание)
Продолжаем изучение гибридных моделей последовательностей графов (GSM++), которые интегрируют преимущества различных архитектур, обеспечивая высокую точность анализа и эффективное распределение вычислительных ресурсов. Эти модели эффективно выявляют скрытые закономерности, снижая влияние рыночного шума и повышая качество прогнозирования.
Разрабатываем мультивалютный советник (Часть 23): Приводим в порядок конвейер этапов автоматической оптимизации проектов (II) Разрабатываем мультивалютный советник (Часть 23): Приводим в порядок конвейер этапов автоматической оптимизации проектов (II)
Мы стремимся создать систему автоматической периодической оптимизации торговых стратегий, используемых в одном итоговом советнике. С развитием система становится всё более сложной, поэтому время от времени надо смотреть на неё в целом с целью выявления узких мест и неоптимальных решений.
Возможности Мастера MQL5, которые вам нужно знать (Часть 32): Регуляризация Возможности Мастера MQL5, которые вам нужно знать (Часть 32): Регуляризация
Регуляризация — это форма штрафования функции потерь пропорционально дискретному весу, применяемому ко всем слоям нейронной сети. Мы оценим значимость некоторых форм регуляризации, протестировав советник, собранный в Мастере.