Оптимизация торговых стратегий с помощью генетических алгоритмов DEAP на Python

Оптимизация торговых стратегий с помощью генетических алгоритмов DEAP на Python Анализ данных и Бэктесты
Пошаговое руководство по оптимизации параметров торговых стратегий с использованием генетических алгоритмов библиотеки DEAP в Python для квант-разработчиков.
Суть: Оптимизация параметров торговой стратегии с помощью генетического алгоритма библиотеки DEAP позволяет эффективно находить глобальные экстремумы в многомерном пространстве решений (например, оптимальные периоды индикаторов), избегая вычислительного тупика полного перебора (Grid Search).

Исходный код

Для построения качественной торговой системы критически важно использовать быстрые методы расчета. Прежде чем переходить к оптимизации, ознакомьтесь с нашей статьей Интеграция Ta-Lib в Python: Быстрый расчет 100+ индикаторов на DataFrame, чтобы ускорить вычисление технических индикаторов. Также для выбора перспективных активов вам может пригодиться Тепловая карта correlation альткоинов на Python: seaborn и pandas, а для анализа рыночных настроений — Парсинг и Sentiment Analysis Reddit (r/CryptoCurrency) на Python.

Ниже представлен готовый скрипт оптимизации двух скользящих средних (Fast SMA и Slow SMA) с использованием эволюционного фреймворка DEAP.

import random
import numpy as np
import pandas as pd
from deap import base, creator, tools, algorithms

# Генерируем синтетические данные для бэктеста
np.random.seed(42)
dates = pd.date_range(start='2023-01-01', periods=500, freq='D')
prices = 100 + np.cumsum(np.random.normal(0.1, 1.0, size=500))
data = pd.DataFrame({'Close': prices}, index=dates)

def backtest(individual, df):
    fast_period, slow_period = individual
    # Ограничение: быстрый период должен быть строго меньше медленного
    if fast_period >= slow_period:
        return (-1000.0,)
    
    df = df.copy()
    df['Fast_SMA'] = df['Close'].rolling(window=fast_period).mean()
    df['Slow_SMA'] = df['Close'].rolling(window=slow_period).mean()
    
    df['Signal'] = 0.0
    df.loc[df['Fast_SMA'] > df['Slow_SMA'], 'Signal'] = 1.0
    df['Returns'] = df['Close'].pct_change()
    df['Strategy_Returns'] = df['Signal'].shift(1) * df['Returns']
    
    total_return = df['Strategy_Returns'].sum()
    return (total_return,)

# Настройка DEAP
creator.create('FitnessMax', base.Fitness, weights=(1.0,))
creator.create('Individual', list, fitness=creator.FitnessMax)

toolbox = base.Toolbox()
# Диапазоны: Fast SMA (от 5 до 50), Slow SMA (от 20 до 150)
toolbox.register('attr_fast', random.randint, 5, 50)
toolbox.register('attr_slow', random.randint, 20, 150)
toolbox.register('individual', tools.initCycle, creator.Individual, 
                 (toolbox.attr_fast, toolbox.attr_slow), n=1)
toolbox.register('population', tools.initRepeat, list, toolbox.individual)

toolbox.register('evaluate', backtest, df=data)
toolbox.register('mate', tools.cxTwoPoint)
toolbox.register('mutate', tools.mutUniformInt, low=[5, 20], up=[50, 150], indpb=0.2)
toolbox.register('select', tools.selTournament, tournsize=3)

if __name__ == '__main__':
    random.seed(42)
    pop = toolbox.population(n=50)
    hof = tools.HallOfFame(1)
    
    stats = tools.Statistics(lambda ind: ind.fitness.values)
    stats.register('avg', np.mean)
    stats.register('max', np.max)
    
    algorithms.eaSimple(pop, toolbox, cxpb=0.5, mutpb=0.2, ngen=20, 
                        stats=stats, halloffame=hof, verbose=False)
    
    best_ind = hof[0]
    print(f'Лучшие параметры (Fast SMA, Slow SMA): {best_ind}')
    print(f'Максимальная доходность: {best_ind.fitness.values[0]:.4f}')

Разбор параметров

  • creator.create('FitnessMax', base.Fitness, weights=(1.0,)): Создает класс целевой функции. Кортеж весов со значением 1.0 указывает алгоритму на необходимость максимизации метрики (например, доходности или коэффициента Шарпа).
  • toolbox.register('individual', ...): Определяет структуру хромосомы (особи), которая в данном случае состоит из двух целочисленных генов: периода быстрой и медленной скользящих средних.
  • tools.cxTwoPoint: Метод двухточечного скрещивания, позволяющий особям обмениваться участками хромосом для получения потенциально более успешного потомства.
  • tools.mutUniformInt: Оператор мутации, который с заданной вероятностью indpb изменяет значения генов в пределах указанных границ low и up, предотвращая застревание алгоритма в локальных экстремумах.
  • tools.selTournament: Турнирный отбор, при котором из случайной группы особей размером tournsize выбирается лучшая для перехода в следующее поколение.

Как запустить

Для запуска скрипта установите необходимые библиотеки с помощью команды pip install deap pandas numpy. Скопируйте код в файл optimize.py и выполните его в терминале. Алгоритм инициализирует популяцию из 50 случайных стратегий и в течение 20 поколений эволюционным путем найдет оптимальное сочетание периодов скользящих средних для максимизации доходности на исторических данных.

Оцените статью
FinFluct