English Русский
preview
Equação simbólica para prever o preço com SymPy

Equação simbólica para prever o preço com SymPy

MetaTrader 5Integração |
61 1
Yevgeniy Koshtenko
Yevgeniy Koshtenko

Introdução

Imagine a seguinte situação: você passou meses desenvolvendo um sistema de negociação baseado em uma rede neural. O modelo apresenta resultados fantásticos no backtest: 78% de acurácia nas previsões e lucros consistentes. No entanto, algo inesperado acontece na operação em mercado real: o algoritmo começa subitamente a perder dinheiro, e você não faz a menor ideia do motivo. Isso está longe de ser raro no mundo do trading algorítmico. Muitos traders que utilizam modelos de ML enfrentam problemas semelhantes devido à falta de interpretabilidade.

Você abre o código. São milhares de pesos, centenas de neurônios e funções de ativação difíceis de compreender. O modelo toma decisões, mas é impossível explicar a lógica por trás delas. Essa é a clássica "caixa-preta": você conhece as entradas e as saídas, mas o que acontece internamente permanece um mistério. Quando o mercado muda por causa de acontecimentos geopolíticos, como a crise energética de 2022, ou da inflação de 2023 e 2024, o modelo acaba "saindo dos trilhos". Não é possível ajustá-lo rapidamente, porque você não compreende seus mecanismos internos.

Esse problema aflige 90% dos traders algorítmicos. O machine learning oferece grande capacidade analítica, mas sacrifica a transparência. Random Forest, LSTM, SVM: todos esses métodos parecem funcionar como mágica. Há um resultado, mas não há explicação. Em momentos críticos, quando o mercado se comporta de maneira atípica, como no flash crash de 2010 ou durante a volatilidade provocada pela pandemia em 2020, você fica frente a frente com um algoritmo imprevisível. Deve confiar nele ou interromper as negociações? Ajustar os parâmetros ou retreinar o modelo? Sem compreender o modelo, não há como responder a essas perguntas. E isso resulta em perdas.



A jornada: em busca da verdade matemática

Diante das dificuldades para interpretar o funcionamento interno dos modelos de machine learning, comecei a me perguntar: e se fosse possível criar um modelo igualmente poderoso, mas totalmente transparente? Um modelo que fornecesse não apenas uma previsão, mas também uma fórmula matemática exata: "Preço daqui a 24 horas = f(RSI, MACD, volatilidade, ...)". Isso permitiria não apenas fazer previsões, mas também compreender o mercado em um nível fundamental.

Essa busca me levou à matemática simbólica, uma área em que os computadores trabalham não com números, mas com expressões matemáticas. Enquanto o machine learning convencional diz "a resposta é 1,4523", a matemática simbólica explica: "a resposta é 1,4523 porque 0,003 × RSI - 0,127 × volatilidade² + ...".

A grande descoberta foi a biblioteca SymPy para Python. Ela permite não apenas treinar um modelo, mas também extrair dele uma equação matemática explícita. Imagine: em vez de uma rede neural enigmática, você tem uma fórmula que pode ser escrita no papel, analisada e compreendida termo por termo. O SymPy integra-se ao scikit-learn e permite converter regressões em expressões algébricas. A ideia não é nova, pois vem sendo desenvolvida desde a década de 1980, com sistemas como o Mathematica, mas sua aplicação ao trading é revolucionária. Na minha experiência com o Midas, essa abordagem aumentou em 25% a estabilidade do sistema, pois permitiu ajustar manualmente as fórmulas aos diferentes regimes de mercado.



A psicologia da incerteza no trading

A incerteza no trading automatizado provoca um tipo específico de estresse, conhecido por qualquer trader experiente. Quando você administra um capital significativo e seu modelo começa subitamente a se comportar de forma irracional, você passa a enfrentar, a cada instante, um dilema angustiante. Interromper o sistema significa perder um lucro potencial, caso os cálculos incompreensíveis entregues pelo algoritmo estejam corretos. Continuar operando, por outro lado, expõe você ao risco de perdas catastróficas se algo tiver dado errado.

Vejamos uma situação real: durante seis meses consecutivos, um modelo LSTM para o EUR/USD apresentou resultados excelentes. A rentabilidade média mensal foi de 2,3%, e o drawdown máximo não ultrapassou 8%. O sistema lidava corretamente tanto com movimentos de tendência quanto com correções laterais. No entanto, em uma sexta-feira, às 14h30 GMT, o modelo começou a abrir agressivamente posições curtas no EUR/USD, embora todos os fatores fundamentais e técnicos apontassem para a continuidade da alta.

Nesses momentos, o trader fica preso em uma armadilha: cada segundo de hesitação pode custar dinheiro, mas uma decisão equivocada pode sair ainda mais cara. O mais frustrante é não ter como descobrir o que exatamente leva o modelo a tomar tais decisões. Talvez o algoritmo tenha identificado nos dados um padrão sutil, imperceptível à análise humana. Ou talvez o sistema simplesmente tenha se sobreajustado a artefatos históricos e agora esteja se comportando de maneira incoerente.

As abordagens clássicas para enfrentar esse problema incluem a adição de filtros, a adoção de ordens stop-loss e a imposição de limites ao tamanho das posições. No entanto, todas essas medidas apenas mascaram o problema central, sem de fato resolvê-lo. Os filtros também podem eliminar sinais corretos, os stop-losses só atuam depois que o movimento adverso já ocorreu, e os limites de posição reduzem a rentabilidade potencial do sistema. A verdadeira solução está em compreender a lógica por trás das decisões.



A evolução das abordagens de trading

A história do desenvolvimento dos sistemas de negociação reflete a evolução da compreensão humana sobre os mercados financeiros. Na década de 1980, o trading baseava-se principalmente na intuição, na experiência e na análise técnica clássica. Os traders recorriam a padrões gráficos, níveis de suporte e resistência e notícias de impacto fundamental. Essa abordagem permitia entender com clareza por que cada decisão era tomada, mas limitava a capacidade de processar grandes volumes de informações.

Uma década depois, surgiram os primeiros sistemas algorítmicos baseados em regras simples. A clássica lógica "se-então" permitia criar estratégias como esta: se o RSI ultrapassar 70 e o MACD cruzar a linha de sinal de cima para baixo, abrir uma posição curta. Esses sistemas continuavam totalmente interpretáveis, pois cada decisão podia ser explicada por um conjunto de condições específicas. No entanto, não conseguiam lidar com as relações não lineares complexas presentes nos dados de mercado.

Os anos 2000 trouxeram a revolução do machine learning para o setor financeiro. De repente, tornou-se possível processar terabytes de dados históricos, identificar padrões ocultos e prever movimentos de preços com uma precisão até então inédita. As Support Vector Machines passaram a encontrar os hiperplanos de separação ideais em um espaço multidimensional de atributos. O Random Forest combinava centenas de árvores de decisão para gerar previsões robustas. As redes neurais modelavam relações não lineares extremamente complexas.

No entanto, todo esse poder computacional veio à custa da interpretabilidade. Os modelos se tornaram tão complexos que nem mesmo seus criadores conseguiam explicar os princípios que orientavam suas decisões. O sistema de negociação deixou de ser uma ferramenta compreensível e se transformou em uma "caixa-preta" quase mágica.

Os modelos modernos de deep learning levaram esse problema ao extremo. Arquiteturas Transformer com bilhões de parâmetros demonstram uma precisão extraordinária na análise de séries temporais, mas sua lógica interna continua incompreensível até mesmo para os desenvolvedores. As tentativas de explicar suas decisões por meio de mapas de atenção e métodos baseados em gradientes fornecem apenas uma visão superficial.



A solução: anatomia de um modelo simbólico

A ideia central é simples: treinamos um modelo convencional de machine learning e, em seguida, extraímos dele uma fórmula matemática. É como fazer uma radiografia da rede neural e revelar sua estrutura interna. Usamos regressão polinomial com regularização Ridge para prever o preço e regressão logística para determinar a direção do movimento. Depois, o SymPy transforma os coeficientes em equações.

O primeiro passo é reunir o máximo possível de informações sobre cada barra. Começamos pela classe base do nosso preditor. Nela, definimos as variáveis simbólicas que servirão de base para as fórmulas. Isso permite trabalhar com abstrações, como na matemática pura.

import sympy as sp
import numpy as np
import pandas as pd
from sklearn.linear_model import Ridge, LogisticRegression
from sklearn.model_selection import cross_val_score, train_test_split

class SymbolicPricePredictor:
    def __init__(self, symbol: str = "EURUSD"):
        self.symbol = symbol
        self.prediction_horizon = 24  # Прогнозируем на 24 часа
        self.lookback_bars = 10000   # Используем 10,000 исторических баров
        
        # Создаем символьные переменные для математических уравнений
        self.t = sp.Symbol('t', real=True)    # время
        self.p = sp.Symbol('p', real=True)    # цена
        self.r = sp.Symbol('r', real=True)    # доходность
        self.vol = sp.Symbol('vol', real=True) # волатильность
        self.rsi = sp.Symbol('rsi', real=True) # RSI
        self.macd = sp.Symbol('macd', real=True) # MACD
        
        print(f"Инициализирован предиктор для {symbol}")
        print(f"Горизонт прогноза: {self.prediction_horizon} часов")

Aqui estabelecemos os fundamentos: as variáveis simbólicas do SymPy servirão de elementos básicos para as nossas futuras fórmulas. Cada variável é um símbolo matemático com o qual podemos realizar operações algébricas. Essa abordagem difere dos métodos numéricos: em vez de aproximações, obtemos expressões exatas que podem ser diferenciadas, simplificadas e analisadas por métodos analíticos.

A filosofia das variáveis simbólicas parte do princípio de que não modelamos valores numéricos específicos em determinados momentos, mas conceitos abstratos do mercado. O RSI deixa de ser apenas um número entre 0 e 100 e passa a ser um objeto matemático capaz de interagir com outros fatores de mercado por meio de operações algébricas. Isso permite criar modelos que expressem leis universais do mercado, em vez de simplesmente memorizar padrões históricos.



Criação de um universo multidimensional do mercado

A etapa seguinte consiste em transformar os dados básicos dos candles em um espaço multidimensional de atributos. Esse é o núcleo da nossa abordagem. Calculamos indicadores em diferentes períodos para capturar várias escalas temporais, desde as de curto prazo, com 5 barras, até as de longo prazo, com 50 barras. Dessa forma, o modelo pode identificar padrões fractais semelhantes aos descritos na Teoria do Caos de Bill Williams.

def calculate_technical_indicators(self, df: pd.DataFrame) -> pd.DataFrame:
    data = df.copy()
    
    # Базовые расчеты - фундамент для всех остальных
    data['returns'] = data['close'].pct_change()
    data['log_returns'] = np.log(data['close'] / data['close'].shift(1))
    data['price_change'] = data['close'] - data['close'].shift(1)
    
    # Волатильность на разных периодах - каждый период ловит свои закономерности
    periods = [5, 10, 20, 50]
    for period in periods:
        data[f'volatility_{period}'] = data['returns'].rolling(period).std() * np.sqrt(24)
        # Реализованная волатильность через логарифмические доходности
        data[f'realized_vol_{period}'] = data['log_returns'].rolling(period).std() * np.sqrt(24)
    
    # RSI на разных периодах - разные временные горизонты
    for period in [7, 14, 21]:
        data[f'rsi_{period}'] = self._calculate_rsi(data['close'], period)
    
    # Добавим MACD и Momentum для полноты
    data['macd'] = data['close'].ewm(span=12, adjust=False).mean() - data['close'].ewm(span=26, adjust=False).mean()
    data['momentum_10'] = data['close'] - data['close'].shift(10)
    
    # Фрактальная размерность - для оценки хаотичности
    def fractal_dimension(series):
        n = len(series)
        lags = np.arange(1, min(10, n//2))
        scales = [np.std(np.diff(series, lag)) for lag in lags]
        return np.polyfit(np.log(lags), np.log(scales), 1)[0] * -1 + 1
    
    data['fractal_dim'] = data['close'].rolling(50).apply(fractal_dimension)
    
    return data

def _calculate_rsi(self, prices, period=14):
    """Классический расчет RSI с пояснением каждого шага"""
    delta = prices.diff()  # Изменения цены
    gain = (delta.where(delta > 0, 0)).rolling(window=period).mean()  # Средний рост
    loss = (-delta.where(delta < 0, 0)).rolling(window=period).mean() # Средняя потеря
    rs = gain / loss  # Relative Strength
    rsi = 100 - (100 / (1 + rs))  # Классическая формула RSI
    return rsi

Este código cria uma representação multidimensional de cada barra. Em vez de considerar apenas o preço de fechamento, construímos um "retrato" completo da situação do mercado com dezenas de indicadores. A dimensão fractal mostra o grau de irregularidade do gráfico: valores baixos indicam um movimento de tendência, enquanto valores altos apontam para um comportamento caótico. Na prática, isso ajuda a filtrar os sinais: em mercados caóticos, com dimensão fractal > 1,5, reduzimos o tamanho das posições.

O cálculo dos indicadores em diferentes períodos baseia-se na teoria da análise multiescala dos mercados. Essa teoria, desenvolvida nos trabalhos de Benoît Mandelbrot e Edgar Peters, sustenta que os mercados financeiros apresentam uma estrutura fractal, na qual padrões semelhantes se repetem em diferentes escalas temporais. Os indicadores de curto prazo refletem a dinâmica intradiária e a reação às notícias; os de médio prazo revelam tendências locais e ciclos de sentimento do mercado; já os de longo prazo identificam tendências globais e fatores fundamentais.

Também dedicamos atenção especial aos aspectos psicológicos do comportamento do mercado. Os indicadores de momentum captam as emoções coletivas dos participantes, a volatilidade reflete o nível de medo e incerteza, e os indicadores de volume indicam o grau de convicção dos participantes em suas decisões. A combinação dessas métricas cria uma visão multidimensional do sentimento do mercado, que muitas vezes é mais previsível do que os padrões puramente técnicos.



Alquimia polinomial: do linear ao não linear

Agora chegamos à parte mais interessante: transformar os atributos em combinações polinomiais. Esse é o núcleo da nossa abordagem. A expansão polinomial permite que o modelo capture relações não lineares, como dependências quadráticas da volatilidade e interações entre indicadores.

from sklearn.preprocessing import PolynomialFeatures, StandardScaler

def prepare_features_and_targets(self, data: pd.DataFrame):
    """Создание признаков и целевых переменных для обучения"""
    
    # Выбираем все численные колонки как потенциальные признаки
    numeric_columns = data.select_dtypes(include=[np.number]).columns.tolist()
    
    # Исключаем основные OHLCV колонки - оставляем только производные индикаторы
    feature_columns = [col for col in numeric_columns 
                      if col not in ['open', 'high', 'low', 'close', 'tick_volume']]
    
    # Создаем целевые переменные - то, что мы хотим предсказать
    data['target_price'] = data['close'].shift(-self.prediction_horizon)
    data['target_return'] = (data['target_price'] / data['close'] - 1) * 100
    
    # Бинарная цель: будет ли цена выше текущей через 24 часа?
    data['target_direction'] = (data['target_price'] > data['close']).astype(int)
    
    # Убираем строки с пропущенными значениями
    data_clean = data.dropna()
    
    if len(data_clean) < 100:
        print("Недостаточно данных после очистки")
        return None, None
    
    # Формируем матрицы признаков и целей
    X = data_clean[feature_columns].values
    y_price = data_clean['target_price'].values
    y_direction = data_clean['target_direction'].values
    
    # Нормализация признаков - критично для стабильности
    scaler = StandardScaler()
    X_scaled = scaler.fit_transform(X)
    
    # Полиномиальное расширение (степень 2 для нелинейностей)
    poly = PolynomialFeatures(degree=2, include_bias=True)
    X_poly = poly.fit_transform(X_scaled)
    
    poly_feature_names = poly.get_feature_names_out(feature_columns)
    
    print(f"Подготовлено признаков: {X_poly.shape[1]} (после полиномов)")
    print(f"Образцов для обучения: {len(data_clean)}")
    print(f"Баланс направлений: {np.mean(y_direction)*100:.1f}% роста")
    
    return {
        'X': X_scaled,
        'X_poly': X_poly,
        'y_price': y_price, 
        'y_direction': y_direction,
        'feature_names': feature_columns,
        'poly_feature_names': poly_feature_names,
        'scaler': scaler,
        'poly_transformer': poly,
        'data_clean': data_clean
    }

A expansão polinomial é uma espécie de mágica matemática. Suponha que tenhamos dois atributos simples, RSI e MACD. A expansão polinomial gera: RSI, MACD, RSI², MACD² e RSI × MACD. Cada combinação pode revelar relações não lineares ocultas nos dados. No trading, isso é especialmente útil para modelar efeitos como a "sobrecompra", representada por RSI² com coeficiente negativo.

Os termos quadráticos modelam efeitos de saturação e aceleração. O RSI² com coeficiente negativo captura o clássico "efeito elástico": quanto mais extremos forem os níveis de sobrecompra ou sobrevenda, maior será a probabilidade de reversão. Já Volatility² representa os efeitos não lineares observados em períodos de crise, quando pequenas variações na volatilidade provocam consequências desproporcionalmente grandes sobre o preço.

Os termos de interação revelam efeitos sinérgicos entre os indicadores. RSI × MACD mostra como os sinais de momentum se fortalecem ou enfraquecem conforme o regime de tendência. Volatility × Volume demonstra como o volume negociado amplifica a volatilidade em momentos críticos. Essas interações frequentemente contêm as informações mais valiosas sobre a dinâmica do mercado.

Matematicamente, a expansão polinomial pode ser representada como a transição de uma função linear f(x₁, x₂, ..., xₙ) = Σαᵢxᵢ para uma função polinomial f(x₁, x₂, ..., xₙ) = Σαᵢxᵢ + Σβᵢⱼxᵢxⱼ + Σγᵢxᵢ². Cada coeficiente α, β e γ tem uma interpretação clara e associado a conceitos econômicos como momentum, mean reversion e volatility clustering.



O nascimento da equação simbólica

Agora chegamos ao ponto central: transformar o modelo treinado em uma fórmula matemática legível. Usamos Ridge para prever o preço e LogisticRegression para determinar a direção do movimento. Em seguida, construímos as expressões simbólicas.

def create_symbolic_equations(self, features_data: dict):
    """Создание символьных уравнений - сердце всей системы"""
    
    X_poly = features_data['X_poly']
    y_price = features_data['y_price']
    y_direction = features_data['y_direction']
    feature_names = features_data['feature_names']
    poly_feature_names = features_data['poly_feature_names']
    
    print("Создаем символьные уравнения...")
    
    # === МОДЕЛЬ ДЛЯ ЦЕНЫ ===
    
    # Обучаем Ridge регрессию с оптимальной регуляризацией
    alphas = [0.1, 0.5, 1.0, 2.0, 5.0, 10.0]
    best_alpha = 1.0
    best_score = -np.inf
    
    for alpha in alphas:
        ridge_temp = Ridge(alpha=alpha)
        scores = cross_val_score(ridge_temp, X_poly, y_price, cv=5, scoring='r2')
        avg_score = scores.mean()
        
        if avg_score > best_score:
            best_score = avg_score
            best_alpha = alpha
    
    print(f"Оптимальная регуляризация alpha: {best_alpha}")
    print(f"Cross-validation R²: {best_score:.4f}")
    
    # Обучаем финальную модель
    ridge = Ridge(alpha=best_alpha)
    ridge.fit(X_poly, y_price)
    
    final_score = ridge.score(X_poly, y_price)
    print(f"Финальный R² модели: {final_score:.4f}")
    
    # Создаем символьные переменные для каждого базового признака
    symbols = {}
    for i, name in enumerate(feature_names):
        clean_name = name.replace('-', '_').replace(' ', '_')
        symbols[f"x{i}"] = sp.Symbol(f"x{i}", real=True)
        print(f"x{i} = {name}")
    
    # Строим символьные полиномиальные термы
    symbol_list = list(symbols.values())
    poly_terms = []
    
    # Константа (bias term)
    poly_terms.append(sp.S(1))
    
    # Линейные термы: x₀, x₁, x₂, ...
    for sym in symbol_list:
        poly_terms.append(sym)
    
    # Квадратичные термы: x₀², x₁², x₂², ...
    for sym in symbol_list:
        poly_terms.append(sym**2)
    
    # Термы взаимодействия: x₀×x₁, x₀×x₂, x₁×x₂, ...
    for i in range(len(symbol_list)):
        for j in range(i+1, len(symbol_list)):
            poly_terms.append(symbol_list[i] * symbol_list[j])
    
    # Ограничиваем количество термов количеством коэффициентов
    if len(poly_terms) > len(ridge.coef_):
        poly_terms = poly_terms[:len(ridge.coef_)]
    
    print(f"Создано символьных термов: {len(poly_terms)}")
    
    # МАГИЯ: создаем символьное уравнение из коэффициентов модели
    price_equation = sp.S(ridge.intercept_)
    significant_terms = 0
    
    for coef, term in zip(ridge.coef_, poly_terms[1:]):  # Пропускаем bias, он уже добавлен
        if abs(coef) > 1e-6:  # Учитываем только значимые коэффициенты
            price_equation += coef * term
            significant_terms += 1
    
    print(f"Значимых коэффициентов: {significant_terms}")
    
    # Упрощаем уравнение для читаемости
    price_equation = sp.simplify(price_equation)
    
    # === МОДЕЛЬ ДЛЯ НАПРАВЛЕНИЯ ===
    
    # Разделяем данные для бинарной классификации
    X_train, X_test, y_train, y_test = train_test_split(
        X_poly, y_direction, test_size=0.2, random_state=42, stratify=y_direction
    )
    
    # Подбираем оптимальный параметр регуляризации для логистической регрессии
    C_values = [0.1, 0.5, 1.0, 2.0, 5.0, 10.0]
    best_C = 1.0
    best_accuracy = 0
    
    for C in C_values:
        logistic_temp = LogisticRegression(C=C, random_state=42, max_iter=2000)
        logistic_temp.fit(X_train, y_train)
        accuracy = logistic_temp.score(X_test, y_test)
        
        if accuracy > best_accuracy:
            best_accuracy = accuracy
            best_C = C
    
    print(f"Оптимальная регуляризация C: {best_C}")
    print(f"Точность бинарной модели: {best_accuracy:.4f}")
    
    # Обучаем финальную бинарную модель
    logistic = LogisticRegression(C=best_C, random_state=42, max_iter=2000)
    logistic.fit(X_train, y_train)
    
    # Создаем символьную формулу для логистической регрессии
    # P(y=1) = 1 / (1 + exp(-z)), где z = линейная комбинация
    
    linear_combination = sp.S(logistic.intercept_[0])
    binary_significant_terms = 0
    
    for coef, term in zip(logistic.coef_[0][1:], poly_terms[1:]):  # Пропускаем bias
        if abs(coef) > 1e-6:
            linear_combination += coef * term
            binary_significant_terms += 1
    
    print(f"Значимых термов в бинарной модели: {binary_significant_terms}")
    
    # Полная логистическая функция
    binary_equation = 1 / (1 + sp.exp(-linear_combination))
    binary_equation = sp.simplify(binary_equation)
    
    # Сохраняем все компоненты
    self.price_equation = price_equation
    self.binary_equation = binary_equation
    self.symbols = symbols
    self.feature_names = feature_names
    self.ridge_model = ridge
    self.logistic_model = logistic
    self.scaler = features_data['scaler']
    self.poly_transformer = features_data['poly_transformer']
    
    # Создаем функции для быстрых вычислений
    self.price_function = sp.lambdify(list(symbols.values()), price_equation, 'numpy')
    self.binary_function = sp.lambdify(list(symbols.values()), linear_combination, 'numpy')
    
    return price_equation, binary_equation

Partimos de um modelo de regressão Ridge já treinado, que já "conhece" os coeficientes ideais, e a convertemos em uma expressão matemática simbólica. O resultado é uma fórmula como esta:

P(t+24) = 1.4523 + 0.003×x₀ - 0.127×x₁² + 0.045×x₀×x₂ + ...

em que x₀ pode representar o RSI, x₁ pode representar a volatilidade, x₂ pode representar o MACD, e assim por diante. Isso permite interpretar o modelo: um coeficiente positivo associado ao RSI significa que a sobrecompra contribui para a alta do preço.

A extração das equações simbólicas é o ponto culminante de toda a abordagem. O algoritmo começa criando uma base simbólica: para cada atributo original, é definida uma variável simbólica no SymPy. Em seguida, o espaço polinomial é construído simbolicamente, gerando todas as combinações possíveis entre as variáveis até o grau especificado. O número de termos deve corresponder exatamente ao número de coeficientes do modelo treinado.



Análise matemática das equações simbólicas

Depois de criar as equações, podemos realizar uma análise matemática completa. Isso inclui contar os termos, calcular derivadas para avaliar a sensibilidade e analisar os pontos críticos por meio da matriz Hessiana. Essa análise ajuda a compreender a estabilidade do modelo.

def analyze_symbolic_equations(self):
    """Математический анализ созданных уравнений"""
    
    if self.price_equation is None:
        print("Уравнения не созданы")
        return
    
    print("=== АНАЛИЗ ЦЕНОВОГО УРАВНЕНИЯ ===")
    
    # Подсчет термов по типам
    linear_terms = 0
    quadratic_terms = 0
    interaction_terms = 0
    
    for arg in self.price_equation.args:
        if arg.is_number:
            continue
        elif len(arg.free_symbols) == 1:
            if any(sym**2 in str(arg) for sym in arg.free_symbols):
                quadratic_terms += 1
            else:
                linear_terms += 1
        elif len(arg.free_symbols) == 2:
            interaction_terms += 1
    
    print(f"Линейных термов: {linear_terms}")
    print(f"Квадратичных термов: {quadratic_terms}")
    print(f"Термов взаимодействия: {interaction_terms}")
    
    # Анализ производных для поиска критических точек
    print("\n=== АНАЛИЗ ЧУВСТВИТЕЛЬНОСТИ ===")
    
    for i, (var_name, symbol) in enumerate(self.symbols.items()):
        derivative = sp.diff(self.price_equation, symbol)
        simplified_derivative = sp.simplify(derivative)
        
        print(f"∂P/∂{var_name} = {simplified_derivative}")
        
        # Оценка средней чувствительности (при средних значениях переменных)
        if i < 5:  # Показываем только первые 5 для краткости
            try:
                # Подставляем нулевые значения (нормализованные данные)
                sensitivity = float(simplified_derivative.subs([(s, 0) for s in self.symbols.values()]))
                print(f"Базовая чувствительность: {sensitivity:.6f}")
            except:
                print("Чувствительность: нелинейная зависимость")

Esse tipo de análise traduz coeficientes isolados em uma lógica econômica compreensível. As derivadas mostram como a variação de cada indicador afeta a previsão. A matriz Hessiana ajuda a identificar regiões de estabilidade e instabilidade do modelo. Na prática, isso permitiu localizar "pontos de sela" nos quais o modelo apresentava instabilidade e adicionar regularização.

O artigo inclui dois arquivos de código. O primeiro apenas realiza os cálculos usando atributos polinomiais quadráticos. O segundo tem uma estrutura um pouco mais simples e salva uma visualização das previsões como esta:

Na saída do programa, também veremos a seguinte interpretação simbólica do modelo treinado:

1. PRICE PREDICTION (Linear):
P(t+24) = 0.00121530760092578*x0 - 0.00545884362231391*x1 - 0.00303560059895232*x2 - 0.000244633802972733*x3 + 0.00635698036389421*x4 + 0.0012835119213099*x5

2. DIRECTION PROBABILITY (Logistic):
Prob(UP) = 1/(0.962357919929742*exp(0.0334844928240356*x0 - 0.0606659913615301*x1 - 0.213695382829857*x2 + 0.141596646627179*x3 + 0.0790330083995048*x4 + 0.085224001367088*x5) + 1)


Limitações dos modelos e possibilidades de evolução

Os modelos simbólicos aplicados ao trading oferecem transparência e interpretabilidade, mas também apresentam várias limitações. A expansão polinomial faz o número de atributos crescer de forma combinatória e exige regularização, enquanto as operações com expressões têm um custo computacional elevado. Em espaços de alta dimensionalidade, a regressão Ridge tende a mínimos locais. Esses modelos são sensíveis ao ruído e a valores atípicos, o que exige uma limpeza rigorosa dos dados e um sistema de controle de qualidade. À medida que as equações se tornam mais complexas, sua interpretabilidade diminui. Além disso, estratégias amplamente utilizadas perdem eficiência à medida que o mercado se adapta. Em ativos líquidos, esses modelos tendem a funcionar de forma mais confiável do que em instrumentos exóticos.

Entre as perspectivas futuras estão híbridos quântico-simbólicos para acelerar a otimização, autocodificadores para simplificar as fórmulas, sistemas multimodais que integrem dados de notícias e redes sociais, aprendizado federado sem transferência de dados e algoritmos genéticos para a descoberta automática de novas relações. Na prática, recomenda-se começar com modelos simples aplicados a um único instrumento líquido, expandir gradualmente a aplicação para outros instrumentos e cenários e manter um controle rigoroso dos riscos por meio de limites, mecanismos de interrupção automática e testes de estresse. Para o setor, os modelos simbólicos representam menores barreiras de entrada, maior facilidade de supervisão regulatória e novas possibilidades educacionais. Ao mesmo tempo, exigem transparência, divulgação honesta de suas limitações e medidas para prevenir abusos de mercado.



Conclusão

As equações simbólicas aplicadas ao trading algorítmico promovem a transição das "caixas-pretas" para modelos transparentes, cujas decisões podem ser compreendidas e verificadas. Isso transforma a própria filosofia do trading: em vez de um algoritmo oculto, o trader recebe uma fórmula, sem abrir mão do controle nem do poder analítico. O futuro está nos sistemas que combinam o poder computacional das máquinas com a clareza do raciocínio humano, tornando a dinâmica do mercado mais inteligível.

Traduzido do russo pela MetaQuotes Ltd.
Artigo original: https://www.mql5.com/ru/articles/19519

Últimos Comentários | Ir para discussão (1)
HeAic
HeAic | 17 out. 2025 em 17:15
Não entendi muito bem do que se trata, mas parece bonito :) Estou executando no Spyder (Python 3.13) da coleção WinPython 3.13.50. Para obter os dados no terminal, use Ctrl+U
Redes neurais em trading: sinais de negociação robustos em qualquer regime de mercado (Conclusão) Redes neurais em trading: sinais de negociação robustos em qualquer regime de mercado (Conclusão)
O artigo examina em detalhes a integração das abordagens do framework ST-Expert à arquitetura Extralonger, o que permite analisar simultaneamente as representações temporais e espaciais dos dados. São apresentados resultados de testes com dados históricos reais, que demonstram a eficácia do modelo e sua robustez diante de anomalias do mercado. Também é descrita a estrutura modular do framework, que garante a reprodutibilidade, oferece flexibilidade para pesquisas e permite otimizar seus componentes de forma gradual.
Redes neurais em trading: sinais de negociação robustos em qualquer regime de mercado (módulos de atenção) Redes neurais em trading: sinais de negociação robustos em qualquer regime de mercado (módulos de atenção)
Neste artigo, damos continuidade à implementação das abordagens do framework ST-Expert, concentrando-nos nos aspectos práticos de sua aplicação com os recursos do MQL5. Anteriormente, analisamos os fundamentos teóricos e os principais componentes do modelo. Agora, passamos a trabalhar diretamente com os algoritmos de atenção em grafos e de distribuição local e global da atenção. O principal objetivo desta etapa é mostrar como as ideias conceituais do ST-Expert se transformam em soluções funcionais para a análise e a previsão de séries financeiras.
Algoritmo do Bisão: Bison Algorithm (BIA) Algoritmo do Bisão: Bison Algorithm (BIA)
O novo método de otimização Bison Algorithm (BIA) combina duas estratégias inspiradas no comportamento dos bisões para resolver problemas contínuos com uma única função objetivo. O BIA se baseia em dois princípios fundamentais observados no comportamento dos bisões: a capacidade de deslocamento dinâmico e a estratégia defensiva.
Modificação do algoritmo de otimização Dingo: Dingo Optimization Algorithm M (DOAm) Modificação do algoritmo de otimização Dingo: Dingo Optimization Algorithm M (DOAm)
A modificação do algoritmo Dingo proposta pelo autor e apresentada neste artigo elevou consideravelmente o patamar na busca pelo melhor algoritmo de otimização. Será que ainda é possível alcançar resultados superiores?