preview
Разработка робота на Python и MQL5 (Часть 2): Выбор модели, создание и обучение, кастомный тестер Python

Разработка робота на Python и MQL5 (Часть 2): Выбор модели, создание и обучение, кастомный тестер Python

MetaTrader 5Тестер | 29 мая 2024, 13:26
1 060 14
Yevgeniy Koshtenko
Yevgeniy Koshtenko

Краткое содержание предыдущей статьи

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

Наша конечная цель — создать рабочую и по максимуму прибыльную модель для прогнозирования цен и торговли. Весь код будет на Python, с включениями библиотеки MQL5. 


Версия Python и необходимые модули

Для работы использовался Python версии 3.10.10.

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

  • Функцию для кластеризации признаков с помощью Gaussian Mixture Model (GMM) от библиотеки sklearn
  • Функцию для выделения признаков с помощью Recursive Feature Elimination with Cross-Validation (RFECV) от библиотеки sklearn
  • Функцию для обучения классификатора XGBoost

Для запуска этого кода необходимо установить следующие модули Python:

  • pandas
  • numpy
  • sklearn
  • xgboost
  • matplotlib
  • seaborn
  • MetaTrader5
  • tqdm

Вы можете установить их с помощью pip, утилиты установки пакетов Python. Вот пример команды для установки всех необходимых модулей:

pip install pandas numpy sklearn xgboost matplotlib seaborn tqdm MetaTrader5

Поехали!


Классификация или регрессия?

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

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

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

Осталось определиться с самой моделью.


Выбор модели классификации

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

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

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


Создание кода модели классификации

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

Функция train_xgboost_classifier получает данные и число раундов бустинга. Разделяет данные на фичи X и метки y, создает модель XGBClassifier с настройкой гиперпараметров, обучает ее методом fit().

Данные делятся на трейн/тест, модель обучается на трейне с помощью функции. Тестируется на остатке данных, высчитывается accuracy предсказаний.

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

Для использования вам потребуется также установить OpenMP runtime библиотеку. Для установки библиотеки XGBoost нужно также поставить OpenMP runtime. Для Windows надо скачать Microsoft Visual C++ Redistributable, соответствующий вашей версии Python.

Переходим к самому коду. В начале кода мы импортируем библиотеку xgboost вот таким образом:

import xgboost as xgb

Остальная часть кода:

import xgboost as xgb

def train_xgboost_classifier(data, num_boost_rounds=500):
    # Check if data is not empty
    if data.empty:
        raise ValueError("Data should not be empty")
    
    # Check if all required columns are present in the data
    required_columns = ['label', 'labels']
    if not all(column in data.columns for column in required_columns):
        raise ValueError(f"Data is missing required columns: {required_columns}")
    
    # Remove the 'label' column as it is not a feature
    X = data.drop(['label', 'labels'], axis=1)
    y = data['labels']
    
    # Check if all features have numeric data type
    if not all(pd.api.types.is_numeric_dtype(X[column]) for column in X.columns):
        raise ValueError("All features should have numeric data type")
    
    # Create an XGBoostClassifier model
    clf = xgb.XGBClassifier(objective='binary:logistic', max_depth=10, learning_rate=0.3, n_estimators=num_boost_rounds, random_state=1)
    
    # Train the model on the data
    clf.fit(X, y)
    
    # Return the trained model
    return clf

labeled_data_engineered = feature_engineering(labeled_data_clustered, n_features_to_select=20)

# Get all data
raw_data = labeled_data_engineered

# Test the model on all data
train_data = raw_data[raw_data.index <= FORWARD]

# Test the model on all data
test_data = raw_data[raw_data.index >= FORWARD]

# Train the XGBoost model on the filtered data
xgb_clf = train_xgboost_classifier(train_data, num_boost_rounds=100)

# Test the model on all data
test_data = raw_data[raw_data.index >= FORWARD]
X_test = test_data.drop(['label', 'labels'], axis=1)
y_test = test_data['labels']
predicted_labels = xgb_clf.predict(X_test)

# Calculate prediction accuracy
accuracy = (predicted_labels == y_test).mean()
print(f"Prediction accuracy: {accuracy:.2f}")

Обучим модель, и рассмотрим точность Accuracy в 52%.

Итак, наша точность классификации сейчас составляет 53% прибыльных меток. Прошу заметить, что тут речь идет о прогнозировании ситуаций, когда цена изменилась более чем на величину тейка (200 пипсов), и не задела хвостом стоп (100 пипсов). На практике у нас выйдет профит-фактор примерно в троечку, что вполне достаточно для прибыльной торговли. Следующим шагом я вижу написание самописного тестера в Python, для анализа доходности моделей, доходности именно в долларах, а не пунктах. Нужно понять, зарабатывает ли модель с учетом маркапа, или же сливает капитал в трубу.


Написание функции самописного тестера Python

def test_model(model, X_test, y_test, markup, initial_balance=10000.0, point_cost=0.00001):
    balance = initial_balance
    trades = 0
    profits = []

    # Test the model on the test data
    predicted_labels = model.predict(X_test)
    for i in range(len(predicted_labels) - 48):
        if predicted_labels[i] == 1:
            # Open a long position
            entry_price = X_test.iloc[i]['close']
            exit_price = X_test.iloc[i+48]['close']
            if exit_price > entry_price + markup:
                # Close the long position with profit
                profit = (exit_price - entry_price - markup) / point_cost
                balance += profit
                trades += 1
                profits.append(profit)
            else:
                # Close the long position with loss
                loss = (entry_price - exit_price + markup) / point_cost
                balance -= loss
                trades += 1
                profits.append(-loss)
        elif predicted_labels[i] == 0:
            # Open a short position
            entry_price = X_test.iloc[i]['close']
            exit_price = X_test.iloc[i+48]['close']
            if exit_price < entry_price - markup:
                # Close the short position with profit
                profit = (entry_price - exit_price - markup) / point_cost
                balance += profit
                trades += 1
                profits.append(profit)
            else:
                # Close the short position with loss
                loss = (exit_price - entry_price + markup) / point_cost
                balance -= loss
                trades += 1
                profits.append(-loss)

    # Calculate the cumulative profit or loss
    total_profit = balance - initial_balance

    # Plot the balance change over the number of trades
    plt.plot(range(trades), [balance + sum(profits[:i]) for i in range(trades)])
    plt.title('Balance Change')
    plt.xlabel('Trades')
    plt.ylabel('Balance ($)')
    plt.xticks(range(0, len(X_test), int(len(X_test)/10)), X_test.index[::int(len(X_test)/10)].strftime('%Y-%m-%d'))  # Add dates to the x-axis
    plt.axvline(FORWARD, color='r', linestyle='--')  # Add a vertical line for the FORWARD date
    plt.show()

    # Print the results
    print(f"Cumulative profit or loss: {total_profit:.2f} $")
    print(f"Number of trades: {trades}")

# Get test data
test_data = raw_data[raw_data.index >= FORWARD]
X_test = test_data.drop(['label', 'labels'], axis=1)
y_test = test_data['labels']

# Test the model with markup and target labels
initial_balance = 10000.0
markup = 0.00001
test_model(xgb_clf, X_test, y_test, markup, initial_balance)

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

Функция получает модель, тест-данные, маркап и начальный баланс. Используя предсказания модели, имитируется торговля: лонг при 1, шорт при 0. Если прибыль превысила маркап, позиция закрывается, а прибыль добавляется к балансу.

Ведется учет сделок и прибыли/убытка от каждой. Строится график баланса. Вычисляется накопленный итог прибыли/убытка.

В конце получаются тест-данные, удаляются ненужные столбцы. Обученная модель xgb_clf тестируется с заданным маркапом и начальным балансом. Протестируем же ее!


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


Внедрение кросс-валидации в модель

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

В нашем случае мы будем использовать 5-кратную кросс-валидацию для оценки модели XGBoost. Для этого воспользуемся функцией cross_val_score из библиотеки sklearn.

Изменим код функции train_xgboost_classifier следующим образом:

def train_xgboost_classifier(data, num_boost_rounds=500):
    # Check that data is not empty
    if data.empty:
        raise ValueError("Data should not be empty")

    # Check that all required columns are present in the data
    required_columns = ['label', 'labels']
    if not all(column in data.columns for column in required_columns):
        raise ValueError(f"Data is missing required columns: {required_columns}")

    # Drop the 'label' column since it is not a feature
    X = data.drop(['label', 'labels'], axis=1)
    y = data['labels']

    # Check that all features have numeric data type
    if not all(pd.api.types.is_numeric_dtype(X[column]) for column in X.columns):
        raise ValueError("All features should have numeric data type")

    # Create XGBoostClassifier model
    clf = xgb.XGBClassifier(objective='binary:logistic', max_depth=10, learning_rate=0.3, n_estimators=num_boost_rounds, random_state=1)

    # Train the model on the data using cross-validation
    scores = cross_val_score(clf, X, y, cv=5)

    # Calculate the mean accuracy of the predictions
    accuracy = scores.mean()

    print(f"Mean prediction accuracy on cross-validation: {accuracy:.2f}")

    # Train the model on the data without cross-validation
    clf.fit(X, y)

    # Return the trained model
    return clf

labeled_data_engineered = feature_engineering(labeled_data_clustered, n_features_to_select=20)

# Get all data
raw_data = labeled_data_engineered

# Train data
train_data = raw_data[raw_data.index <= FORWARD]

# Train the XGBoost model on the filtered data
xgb_clf = train_xgboost_classifier(train_data, num_boost_rounds=100)

# Test data
test_data = raw_data[raw_data.index >= FORWARD]
X_test = test_data.drop(['label', 'labels'], axis=1)
y_test = test_data['labels']
predicted_labels = xgb_clf.predict(X_test)

# Calculate the accuracy of the predictions
accuracy = (predicted_labels == y_test).mean()
print(f"Accuracy: {accuracy:.2f}")

При обучении модели функция train_xgboost_classifier будет выполнять 5-кратную кросс-валидацию и выводить среднюю точность прогноза. В обучении по-прежнему будет участвовать выборка до даты FORWARD.

Кросс-валидация используется только для оценки модели, но не для ее обучения. Обучение выполняется на всех данных до даты FORWARD без кросс-валидации.

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


Протестировав XGBoost с кросс-валидацией на данных 1990-2024 гг., получена точность 56% на тесте после 2010 г. Модель показала неплохую робастность на новых данных с первой попытки. Точность также неплохо выросла, это не может не радовать.


Оптимизация гиперпараметров модели по сетке

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

Рассмотрим оптимизацию гиперпараметров XGBoost по сетке с использованием Scikit-learn.

Используем GridSearchCV из Scikit-learn для кросс-валидации модели по всем наборам гиперпараметров из сетки. Выберется набор с максимальной средней точностью на кросс-валидации.

Код для оптимизации:

from sklearn.model_selection import GridSearchCV

# Define the grid of hyperparameters
param_grid = {
    'max_depth': [3, 5, 7, 10],
    'learning_rate': [0.1, 0.3, 0.5],
    'n_estimators': [100, 500, 1000]
}

# Create XGBoost model
clf = xgb.XGBClassifier(objective='binary:logistic', random_state=1)

# Perform grid search to find the best hyperparameters
grid_search = GridSearchCV(clf, param_grid, cv=5, scoring='accuracy')
grid_search.fit(X_train, y_train)

# Print the best hyperparameters
print("Best hyperparameters:", grid_search.best_params_)

# Print the mean accuracy of the predictions on cross-validation for the best hyperparameters
print("Mean prediction accuracy on cross-validation:", grid_search.best_score_)

Здесь мы определяем сетку гиперпараметров param_grid, создаем модель XGBoost clf и выполняем поиск оптимальных гиперпараметров по сетке с помощью метода GridSearchCV. Затем мы выводим лучшие гиперпараметры grid_search.best_params_ и среднюю точность прогноза на кросс-валидации grid_search.best_score_ .

Обратите внимание, что в этом коде мы используем кросс-валидацию для оптимизации гиперпараметров. Это позволяет нам получить более надежную и объективную оценку качества модели.

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

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

def train_xgboost_classifier(data, num_boost_rounds=1000):
    # Check that data is not empty
    if data.empty:
        raise ValueError("Data should not be empty")

    # Check that all required columns are present in the data
    required_columns = ['label', 'labels']
    if not all(column in data.columns for column in required_columns):
        raise ValueError(f"Data is missing required columns: {required_columns}")

    # Drop the 'label' column since it is not a feature
    X = data.drop(['label', 'labels'], axis=1)
    y = data['labels']

    # Check that all features have numeric data type
    if not all(pd.api.types.is_numeric_dtype(X[column]) for column in X.columns):
        raise ValueError("All features should have numeric data type")

    # Create XGBoostClassifier model
    clf = xgb.XGBClassifier(objective='binary:logistic', random_state=1)

    # Define hyperparameters for grid search
    param_grid = {
        'max_depth': [3, 5, 7, 10],
        'learning_rate': [0.05, 0.1, 0.2, 0.3, 0.5],
        'n_estimators': [50, 100, 600, 1200, 2000]
    }

    # Train the model on the data using cross-validation and grid search
    grid_search = GridSearchCV(clf, param_grid, cv=5, scoring='accuracy')
    grid_search.fit(X, y)

    # Calculate the mean accuracy of the predictions
    accuracy = grid_search.best_score_

    print(f"Mean prediction accuracy on cross-validation: {accuracy:.2f}")

    # Return the trained model with the best hyperparameters
    return grid_search.best_estimator_


Ансамблирование моделей

Пришло время сделать нашу модель еще круче и лучше! Ансамблирование моделей - мощный подход в машинном обучении, объединяющий несколько моделей для повышения точности прогнозов. Популярные методы: баггинг (создание моделей на разных подвыборках данных) и бустинг (последовательное обучение моделей для исправления ошибок предыдущих).

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

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

Итоговая функция обучения модели использует кросс-валидацию, ансамблирование, подбор гиперпараметров баггинга по сетке.

def train_xgboost_classifier(data, num_boost_rounds=1000):
    # Check that data is not empty
    if data.empty:
        raise ValueError("Data should not be empty")

    # Check that all required columns are present in the data
    required_columns = ['label', 'labels']
    if not all(column in data.columns for column in required_columns):
        raise ValueError(f"Missing required columns in data: {required_columns}")

    # Remove the 'label' column as it is not a feature
    X = data.drop(['label', 'labels'], axis=1)
    y = data['labels']

    # Check that all features have numeric data type
    if not all(pd.api.types.is_numeric_dtype(X[column]) for column in X.columns):
        raise ValueError("All features should have numeric data type")

    # Create XGBoostClassifier model
    clf = xgb.XGBClassifier(objective='binary:logistic', random_state=1)

    # Define hyperparameters for grid search
    param_grid = {
        'max_depth': [3, 7, 12],
        'learning_rate': [0.1, 0.3, 0.5],
        'n_estimators': [100, 600, 1200]
    }

    # Train the model on the data using cross-validation and hyperparameter tuning
    grid_search = GridSearchCV(clf, param_grid, cv=5, scoring='accuracy')
    grid_search.fit(X, y)

    # Calculate the mean accuracy of the predictions
    accuracy = grid_search.best_score_

    print(f"Mean accuracy on cross-validation: {accuracy:.2f}")

    # Return the trained model
    return grid_search.best_estimator_

labeled_data_engineered = feature_engineering(labeled_data_clustered, n_features_to_select=20)

# Get all data
raw_data = labeled_data_engineered

# Train data
train_data = raw_data[raw_data.index <= FORWARD]

# Test data
test_data = raw_data[raw_data.index <= EXAMWARD]

# Train the XGBoost model on the filtered data
xgb_clf = train_xgboost_classifier(train_data, num_boost_rounds=100)

# Test the model on all data
test_data = raw_data[raw_data.index >= FORWARD]
X_test = test_data.drop(['label', 'labels'], axis=1)
y_test = test_data['labels']
predicted_labels = xgb_clf.predict(X_test)

# Calculate the accuracy of the predictions
accuracy = (predicted_labels == y_test).mean()
print(f"Prediction accuracy: {accuracy:.2f}")

Внедряем ансамблирование моделей через бэггинг, тестируем, получаем следующий результат нашего тестирования:


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

 

Внедряем экзаменационную выборку и проверяем робастность модели

Теперь я использую для теста данные после EXAMWARD даты. Это позволяет мне проверить работу модели на совершенно новых данных, которые не использовались при обучении и тестировании модели. Так я могу объективно оценить, как модель будет работать в реальных условиях.

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

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

Провел обучение на данных 2000-2010 гг, тест на 2010-2019 гг, экзамен - с 2019 г. Экзамен имитирует торговлю в неизвестном будущем.


В целом, все выглядит неплохо. Точность на экзамене упала до 60%, но главное - модель прибыльная и довольно робастная, без сильных просадок. Радует, что модель учится понятию риск/прибыль - прогнозирует ситуации с малым риском и большой потенциальной прибылью (используем 1:8 risk-reward).


Заключение

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


Планы на будущее

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

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

Также хотелось бы реализовать версию, которая будет учиться на исторических данных стакана цен, на реальной бирже, Чикагской или же Московской. Это тоже перспективное направление.

Прикрепленные файлы |
Последние комментарии | Перейти к обсуждению на форуме трейдеров (14)
Ivan Butko
Ivan Butko | 31 мая 2024 в 13:46
Хорошая мотивация, когда есть результаты! 
Причём, как я понял, не на неделю вперёд, и не на месяц, а нормально так, год работает
Maxim Dmitrievsky
Maxim Dmitrievsky | 2 июн. 2024 в 11:53

Все-таки row цены оказываются лучшими фичами.

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

Так из незнания рождается знание, а из знания - незнание :)

Yevgeniy Koshtenko
Yevgeniy Koshtenko | 2 июн. 2024 в 21:49
Ivan Butko #:
Хорошая мотивация, когда есть результаты! 
Причём, как я понял, не на неделю вперёд, и не на месяц, а нормально так, год работает

Спасибо большое! Да, меня такое очень мотивирует! Буду продолжать исследования) Вновь ночь, со мной чашка кофе и идеи по коду)))

Yevgeniy Koshtenko
Yevgeniy Koshtenko | 2 июн. 2024 в 21:49
Maxim Dmitrievsky #:

Все-таки row цены оказываются лучшими фичами.

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

Так из незнания рождается знание, а из знания - незнание :)

 Вот типа такого пытался, у меня теща трейдер с опытом 15+ лет, она все говорит надо на объемах делать фичи)) https://www.mql5.com/ru/code/50133

Maxim Dmitrievsky
Maxim Dmitrievsky | 2 июн. 2024 в 23:05
Yevgeniy Koshtenko #:

 Вот типа такого пытался, у меня теща трейдер с опытом 15+ лет, она все говорит надо на объемах делать фичи)) https://www.mql5.com/ru/code/50133

Да, чаще правда волатильность добавляют (например индикатор std), но не сильно много дает. Или приращения, деленные на волатильность.

Визуализации сделок на графике (Часть 1): Выбор периода для анализа Визуализации сделок на графике (Часть 1): Выбор периода для анализа
Пишем с нуля скрипт, который сделает удобным выгрузку принт-скринов сделок для анализа торговых входов. На одном графике будет удобно отображаться вся необходимая информация по отдельной сделке с возможностью прорисовывания разных таймфреймов.
Возможности Мастера MQL5, которые вам нужно знать (Часть 11): Числовые стены Возможности Мастера MQL5, которые вам нужно знать (Часть 11): Числовые стены
Числовые стены (Number Walls) — это вариант регистра сдвига с линейной обратной связью (Linear Shift Back Registers), который предварительно оценивает последовательности на предмет предсказуемости путем проверки на сходимость. Мы посмотрим, как эти идеи могут быть использованы в MQL5.
Нейросети — это просто (Часть 92): Адаптивное прогнозирование в частотной и временной областях Нейросети — это просто (Часть 92): Адаптивное прогнозирование в частотной и временной областях
Авторы метода FreDF экспериментально подтвердили преимущество комбинированного прогнозирования в частотной и временной областях. Однако применение весового гиперпараметра не является оптимальным для нестационарных временных рядов. В данной статье я предлагаю познакомиться с методом адаптивного сочетания прогнозов в частотной и временной областях.
Разрабатываем мультивалютный советник (Часть 12): Риск-менеджер как для проп-трейдинговых компаний Разрабатываем мультивалютный советник (Часть 12): Риск-менеджер как для проп-трейдинговых компаний
В разрабатываемом советнике у нас уже заложен определённый механизм контроля просадки. Но он имеет вероятностную природу, так как основывается на результатах тестирования на исторических ценовых данных. Поэтому просадка, хотя и с небольшой вероятностью, может иногда превышать максимальные ожидаемые значения. Попробуем добавить механизм, обеспечивающий гарантированное соблюдение заданного уровня просадки.