Русский Português
preview
Computación cuántica y trading: Una nueva mirada a las previsiones de precios

Computación cuántica y trading: Una nueva mirada a las previsiones de precios

MetaTrader 5Sistemas comerciales |
90 0
Yevgeniy Koshtenko
Yevgeniy Koshtenko

Introducción a la computación cuántica para el trading: conceptos básicos y ventajas

Imaginemos un mundo en el que cada transacción de mercado se analiza a través de la lente de las posibilidades que existen simultáneamente, como el famoso gato de Schrödinger, que está a la vez vivo y muerto hasta que abramos la caja. Así funciona el trading cuántico: considera simultáneamente todos los estados potenciales del mercado, abriendo nuevos horizontes al análisis financiero.

Mientras que las computadoras clásicas procesan la información secuencialmente, bit a bit, los sistemas cuánticos usan las asombrosas propiedades del microcosmos -superposición y entrelazamiento- para analizar múltiples escenarios en paralelo. Es como si un tráder experimentado tuviera en la cabeza decenas de gráficos, noticias e indicadores al mismo tiempo, pero escalados hasta límites impensables.

Vivimos en una época en la que el trading algorítmico ya es la norma, pero ahora nos encontramos en la cúspide de la próxima revolución. La computación cuántica promete algo más que acelerar el análisis de datos: ofrece un enfoque esencialmente nuevo para entender los procesos del mercado. Imaginemos que, en lugar de predecir linealmente el precio de un activo, podemos explorar todo un árbol de escenarios probabilísticos en los que cada rama considera sutiles correlaciones de mercado.

En este artículo nos sumergiremos en el mundo del trading cuántico: desde los principios básicos de la computación cuántica hasta la aplicación práctica de los sistemas comerciales. Asimismo, veremos cómo los algoritmos cuánticos pueden encontrar patrones donde los métodos clásicos fallan, y cómo dicha ventaja puede aplicarse a las decisiones comerciales en tiempo real.

Nuestro viaje comenzará con los fundamentos de la computación cuántica y nos conducirá gradualmente a un sistema operativo de previsión de mercados. A lo largo del camino, desglosaremos conceptos complejos usando ejemplos sencillos y veremos cómo los beneficios teóricos de la computación cuántica se traducen en herramientas comerciales prácticas.


La superposición y el entrelazamiento cuánticos en el contexto del análisis de series temporales financieras

A la hora de analizar los mercados financieros, nos enfrentamos a un problema fundamental: un número infinito de factores que se influyen mutuamente. Cada movimiento de los precios es el resultado de la compleja interacción de miles de variables, desde los indicadores macroeconómicos hasta los sentimientos de los tráders individuales. Y aquí es donde la informática cuántica ofrece una solución única gracias a sus propiedades fundamentales de superposición y entrelazamiento.

Analicemos la superposición. En una computadora clásica, un bit puede ser un 0 o un 1. Un cúbit, en cambio, existe en todos los estados posibles simultáneamente hasta que realizamos una medición. Matemáticamente, esto se describe como estado |ψ⟩ = α|0⟩ + β|1⟩, donde α y β suponen amplitudes de probabilidad complejas. Aplicada al análisis de series temporales, esta propiedad permite a los algoritmos cuánticos explorar eficazmente el espacio de decisión en problemas de gestión de portafolios y gestión de riesgos analizando en paralelo muchos escenarios potenciales.

El entrelazamiento cuántico añade otra capa de posibilidades. Cuando los cúbits están entrelazados, sus estados se vuelven inseparables, lo cual se describe, por ejemplo, mediante el estado |ψ⟩ = (|00⟩ + |11⟩)/√2. En el contexto del análisis financiero, esta propiedad se usa en algoritmos cuánticos para modelizar correlaciones complejas entre distintos indicadores del mercado. Por ejemplo, podemos crear sistemas en los que se consideren las relaciones entre el precio de los activos, el volumen comercial y la volatilidad del mercado.

Estas propiedades cuánticas resultan especialmente útiles en el trading de alta frecuencia, donde la velocidad de procesamiento de datos multidimensionales resulta fundamental. La superposición permite analizar múltiples escenarios comerciales en paralelo, mientras que el entrelazamiento ayuda a tener en cuenta las complejas correlaciones entre mercados en tiempo real. Las ventajas cuánticas resultan más claras en problemas específicos de optimización y búsqueda en los que los algoritmos clásicos se enfrentan a un crecimiento exponencial de la complejidad computacional.


Desarrollo de un algoritmo de predicción cuántica usando QPE (Quantum Phase Estimation)

En el corazón de nuestro sistema se encontrará una elegante combinación de computación cuántica y análisis técnico clásico. Imagine una orquesta cuántica de ocho cúbits, donde cada cúbit es un músico que interpreta su papel en una compleja sinfonía de movimientos de mercado.

Todo comenzará con la preparación de los datos. Nuestro predictor cuántico recibirá datos del mercado a través de la integración de MetaTrader 5, como las neuronas que recogen información de los sentidos. Estos datos pasarán por un proceso de normalización: imagínese que afináramos todos los instrumentos de una orquesta al mismo tono.

La parte más interesante comenzará al crear los circuitos cuánticos. Primero sumergiremos cada cúbit en un estado de superposición utilizando las puertas de Hadamard (H-gates o puertas H). En ese momento, cada cúbit existirá simultáneamente en todos los estados posibles, como si cada músico tocara al mismo tiempo todas las notas posibles de su parte.

A continuación, codificaremos los datos del mercado en estados cuánticos a través de puertas ry, donde el ángulo de rotación vendrá determinado por el valor de los parámetros del mercado. Es algo similar a cómo un director de orquesta establece el tempo y el carácter de la interpretación para cada músico. Se prestará especial atención al precio actual: este recibirá su propio giro cuántico, que afectará a todo el sistema como un solista a una orquesta.

La verdadera magia se producirá cuando se cree el entrelazamiento cuántico. Utilizando puertas cx (CNOTs), enlazaremos cúbits vecinos, creando correlaciones cuánticas irrompibles. Es como el momento en que las partes individuales de los músicos se funden en un único sonido armonioso.

Tras las transformaciones cuánticas, realizaremos mediciones, como si estuviéramos grabando un concierto. Pero aquí hay una peculiaridad: repetiremos este proceso 2000 veces (shots), obteniendo una distribución estadística de los resultados. Cada dimensión nos dará una cadena de bits, donde el número de unidades determinará la dirección de la predicción.

El acorde final será la interpretación de los resultados. El sistema, eso sí, será muy conservador en sus previsiones, limitando la variación máxima de los precios al 0,1%. Sería como un director experimentado que no deja que la orquesta toque ni muy alto ni muy bajo, manteniendo el sonido equilibrado.

Los resultados de las pruebas hablan por sí mismos. La precisión de los pronósticos supera a las conjeturas aleatorias, alcanzando el 54% en el marco temporal de horas de EUR/USD. Al mismo tiempo, el sistema demuestra un alto nivel de confianza en sus predicciones, lo cual se reflejará en la métrica de confianza.

En esta aplicación, la computación cuántica no solo complementará el análisis técnico clásico, sino que creará una nueva dimensión en el análisis de los mercados donde se exploran simultáneamente múltiples escenarios posibles en superposición cuántica. Como decía Richard Feynman: "La naturaleza a nivel cuántico se comporta de forma muy diferente a lo que estamos acostumbrados a pensar". Y parece que los mercados financieros también poseen una naturaleza cuántica que apenas estamos empezando a reconocer.

import numpy as np
import MetaTrader5 as mt5
import pandas as pd
from datetime import datetime, timedelta
from qiskit import QuantumCircuit, transpile, QuantumRegister, ClassicalRegister
from qiskit_aer import AerSimulator
from sklearn.preprocessing import MinMaxScaler
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
import warnings
warnings.filterwarnings('ignore')

class MT5DataLoader:
    def __init__(self, symbol="EURUSD", timeframe=mt5.TIMEFRAME_H1):
        if not mt5.initialize():
            raise Exception("MetaTrader5 initialization failed")
        
        self.symbol = symbol
        self.timeframe = timeframe
    
    def get_historical_data(self, lookback_bars=1000):
        current_time = datetime.now()
        rates = mt5.copy_rates_from(self.symbol, self.timeframe, current_time, lookback_bars)
        
        if rates is None:
            raise Exception(f"Failed to get data for {self.symbol}")
            
        df = pd.DataFrame(rates)
        df['time'] = pd.to_datetime(df['time'], unit='s')
        return df

class EnhancedQuantumPredictor:
    def __init__(self, num_qubits=8):  # Уменьшаем число кубитов для стабильности
        self.num_qubits = num_qubits
        self.simulator = AerSimulator()
        self.scaler = MinMaxScaler()
        
    def create_qpe_circuit(self, market_data, current_price):
        """Создание упрощенной квантовой схемы"""
        qr = QuantumRegister(self.num_qubits, 'qr')
        cr = ClassicalRegister(self.num_qubits, 'cr')
        qc = QuantumCircuit(qr, cr)
        
        # Нормализуем данные
        scaled_data = self.scaler.fit_transform(market_data.reshape(-1, 1)).flatten()
        
        # Создаем суперпозицию
        for i in range(self.num_qubits):
            qc.h(qr[i])
        
        # Применяем рыночные данные как фазы
        for i in range(min(len(scaled_data), self.num_qubits)):
            angle = float(scaled_data[i] * np.pi)  # Преобразуем в float
            qc.ry(angle, qr[i])
        
        # Создаем запутанность
        for i in range(self.num_qubits - 1):
            qc.cx(qr[i], qr[i + 1])
        
        # Применяем текущую цену
        price_angle = float((current_price % 0.01) * 100 * np.pi)  # Используем только последние 2 знака
        qc.ry(price_angle, qr[0])
        
        # Измеряем все кубиты
        qc.measure(qr, cr)
        
        return qc
    
    def predict(self, market_data, current_price, features=None, shots=2000):
        """Упрощенное предсказание"""
        # Обрезаем входные данные
        if market_data.shape[0] > self.num_qubits:
            market_data = market_data[-self.num_qubits:]
        
        # Создаем и выполняем схему
        qc = self.create_qpe_circuit(market_data, current_price)
        compiled_circuit = transpile(qc, self.simulator, optimization_level=3)
        job = self.simulator.run(compiled_circuit, shots=shots)
        result = job.result()
        counts = result.get_counts()
        
        # Анализируем результаты
        predictions = []
        total_shots = sum(counts.values())
        
        for bitstring, count in counts.items():
            # Используем количество единиц в битстроке для определения направления
            ones = bitstring.count('1')
            direction = ones / self.num_qubits  # Нормализованное направление
            
            # Предсказываем изменение не более чем на 0.1%
            price_change = (direction - 0.5) * 0.001
            predicted_price = current_price * (1 + price_change)
            predictions.extend([predicted_price] * count)
        
        predicted_price = np.mean(predictions)
        up_probability = sum(1 for p in predictions if p > current_price) / len(predictions)
        
        confidence = 1 - np.std(predictions) / current_price
        

        
        return {
            'predicted_price': predicted_price,
            'up_probability': up_probability,
            'down_probability': 1 - up_probability,
            'confidence': confidence
        }

class MarketPredictor:
    def __init__(self, symbol="EURUSD", timeframe=mt5.TIMEFRAME_H1, window_size=14):
        self.symbol = symbol
        self.timeframe = timeframe
        self.window_size = window_size
        self.quantum_predictor = EnhancedQuantumPredictor()
        self.data_loader = MT5DataLoader(symbol, timeframe)
    
    def prepare_features(self, df):
        """Подготовка технических индикаторов"""
        df['sma'] = df['close'].rolling(window=self.window_size).mean()
        df['ema'] = df['close'].ewm(span=self.window_size).mean()
        df['std'] = df['close'].rolling(window=self.window_size).std()
        df['upper_band'] = df['sma'] + (df['std'] * 2)
        df['lower_band'] = df['sma'] - (df['std'] * 2)
        df['rsi'] = self.calculate_rsi(df['close'])
        df['momentum'] = df['close'] - df['close'].shift(self.window_size)
        df['rate_of_change'] = (df['close'] / df['close'].shift(1) - 1) * 100
        
        features = df[['sma', 'ema', 'std', 'upper_band', 'lower_band', 
                      'rsi', 'momentum', 'rate_of_change']].dropna()
        return features
    
    def calculate_rsi(self, prices, period=14):
        delta = prices.diff()
        gain = (delta.where(delta > 0, 0)).ewm(alpha=1/period).mean()
        loss = (-delta.where(delta < 0, 0)).ewm(alpha=1/period).mean()
        rs = gain / loss
        return 100 - (100 / (1 + rs))
    
    def predict(self):
        # Получаем данные
        df = self.data_loader.get_historical_data(self.window_size + 50)
        features = self.prepare_features(df)
        
        if len(features) < self.window_size:
            raise ValueError("Недостаточно данных")
        
        # Получаем последние данные для прогноза
        latest_features = features.iloc[-self.window_size:].values
        current_price = df['close'].iloc[-1]
        
        # Делаем прогноз, теперь передаем features как DataFrame
        prediction = self.quantum_predictor.predict(
            market_data=latest_features,
            current_price=current_price,
            features=features.iloc[-self.window_size:]  # Передаем последние записи
        )
        
        prediction.update({
            'timestamp': datetime.now(),
            'current_price': current_price,
            'rsi': features['rsi'].iloc[-1],
            'sma': features['sma'].iloc[-1],
            'ema': features['ema'].iloc[-1]
        })
        
        return prediction

def evaluate_model(symbol="EURUSD", timeframe=mt5.TIMEFRAME_H1, test_periods=100):
    """Оценка точности модели"""
    predictor = MarketPredictor(symbol, timeframe)
    predictions = []
    actual_movements = []
    
    # Получаем исторические данные
    df = predictor.data_loader.get_historical_data(test_periods + 50)
    
    for i in range(test_periods):
        try:
            temp_df = df.iloc[:-(test_periods-i)]
            predictor_temp = MarketPredictor(symbol, timeframe)
            features_temp = predictor_temp.prepare_features(temp_df)
            
            # Получаем данные для прогноза
            latest_features = features_temp.iloc[-predictor_temp.window_size:].values
            current_price = temp_df['close'].iloc[-1]
            
            # Делаем прогноз с передачей всех необходимых параметров
            prediction = predictor_temp.quantum_predictor.predict(
                market_data=latest_features,
                current_price=current_price,
                features=features_temp.iloc[-predictor_temp.window_size:]
            )
            
            predicted_movement = 1 if prediction['up_probability'] > 0.5 else 0
            predictions.append(predicted_movement)
            
            actual_price_next = df['close'].iloc[-(test_periods-i)]
            actual_price_current = df['close'].iloc[-(test_periods-i)-1]
            actual_movement = 1 if actual_price_next > actual_price_current else 0
            actual_movements.append(actual_movement)
            
        except Exception as e:
            print(f"Error in evaluation: {e}")
            continue
    
    if len(predictions) > 0:
        metrics = {
            'accuracy': accuracy_score(actual_movements, predictions),
            'precision': precision_score(actual_movements, predictions),
            'recall': recall_score(actual_movements, predictions),
            'f1': f1_score(actual_movements, predictions)
        }
    else:
        metrics = {
            'accuracy': 0,
            'precision': 0,
            'recall': 0,
            'f1': 0
        }
    
    return metrics

if __name__ == "__main__":
    if not mt5.initialize():
        print("MetaTrader5 initialization failed")
        mt5.shutdown()
    else:
        try:
            symbol = "EURUSD"
            timeframe = mt5.TIMEFRAME_H1
            
            print("\nТестирование модели...")
            metrics = evaluate_model(symbol, timeframe, test_periods=100)
            
            print("\nМетрики качества модели:")
            print(f"Точность (Accuracy): {metrics['accuracy']:.2%}")
            print(f"Точность прогнозов (Precision): {metrics['precision']:.2%}")
            print(f"Полнота (Recall): {metrics['recall']:.2%}")
            print(f"F1-мера: {metrics['f1']:.2%}")
            
            print("\nТекущий прогноз:")
            predictor = MarketPredictor(symbol, timeframe)
            df = predictor.data_loader.get_historical_data(predictor.window_size + 50)
            features = predictor.prepare_features(df)
            latest_features = features.iloc[-predictor.window_size:].values
            current_price = df['close'].iloc[-1]
            
            prediction = predictor.predict()  # Теперь этот метод правильно передает все параметры
            
            print(f"Предсказанная цена: {prediction['predicted_price']:.5f}")
            print(f"Вероятность роста: {prediction['up_probability']:.2%}")
            print(f"Вероятность падения: {prediction['down_probability']:.2%}")
            print(f"Уверенность в прогнозе: {prediction['confidence']:.2%}")
            print(f"Текущая цена: {prediction['current_price']:.5f}")
            print(f"RSI: {prediction['rsi']:.2f}")
            print(f"SMA: {prediction['sma']:.5f}")
            print(f"EMA: {prediction['ema']:.5f}")
            
        finally:
            mt5.shutdown()


Pruebas y validación del sistema de trading cuántico: metodología y resultados



Métricas clave de rendimiento

  • Precisión global (Accuracy): 55,00% - Supera moderadamente las conjeturas aleatorias para el volátil mercado EURUSD.
  • Precisión de las previsiones (Precision): 63,64% - Muestra una buena fiabilidad de las señales generadas por el sistema: casi dos tercios de las previsiones resultan correctas.
  • Integridad (Recall): 14,58% - Una puntuación de exhaustividad baja indica que el sistema es selectivo y genera señales solo cuando hay mucha confianza en la previsión. Así se evitarán las señales falsas.
  • Puntuación F1: 23,73% - El valor de la puntuación F1 refleja el equilibrio entre precisión y exhaustividad, lo que confirma la estrategia conservadora del sistema.

Previsión de mercado actual

  • Cotización actual del euro-dólar EURUSD: 1.02903
  • Precio previsto: 1.02905
  • Distribución de probabilidad:
    • Probabilidad de crecimiento: 38.95%
    • Probabilidad de caída: 61.05%
  • Confianza en la previsión: 99.98%

El sistema predice un movimiento alcista moderado con una alta confianza a pesar de la probabilidad predominante de un movimiento bajista. Y esto puede indicar un periodo de corrección a corto plazo dentro de la tendencia bajista general.

Indicadores técnicos

  • RSI: 49,13 (cerca de la zona neutra, indica que no existen sobrecompra ni sobreventa evidentes)
  • SMA: 1.02904
  • EMA: 1.02909
  • Tendencia: neutra (el precio actual está cerca de los niveles de las medias móviles)

Conclusiones

El sistema presenta las siguientes características clave a considerar:

  1. Precisión estable por encima de las suposiciones aleatorias
  2. Alta selectividad de la generación de señales (63,64% de precisión en las previsiones)
  3. Capacidad de cuantificar la confianza y las probabilidades de distintos escenarios.
  4. Análisis exhaustivo de la situación del mercado, considerando tanto los indicadores técnicos como las pautas más complejas.

Este enfoque conservador, que prioriza la calidad de las señales sobre su cantidad, hace del sistema una herramienta potencialmente eficaz para el trading real.


Integración de métricas de aprendizaje automático y algoritmos cuánticos: reflexiones y primeros intentos

La combinación de computación cuántica y aprendizaje automático descubre nuevos horizontes. En nuestro experimento, utilizaremos MinMaxScaler de sklearn para normalizar los datos antes de codificarlos cuánticamente, pasando los datos de mercado a ángulos cuánticos.

El sistema combina métricas de aprendizaje automático (accuracy, precision, recall, F1-score) con mediciones cuánticas. Con una precisión del 60%, capta patrones que no están al alcance de los algoritmos clásicos, demostrando cautela y selectividad como un tráder experimentado.

El futuro de estos sistemas pasa por integrar sofisticadas técnicas de preprocesamiento, como autocodificadores y transformadores, destinados a profundizar en el análisis de los datos. Los algoritmos cuánticos pueden convertirse en un filtro para los modelos clásicos o viceversa, adaptándose a las condiciones del mercado.

Nuestro experimento muestra que la sinergia entre métodos cuánticos y clásicos no es una elección, sino un camino hacia el próximo gran avance en el trading algorítmico.


Cómo empecé a escribir mi primera red neuronal cuántica - un clasificador

Cuando empecé a experimentar con la computación cuántica en el trading, decidí ir más allá de los simples esquemas cuánticos y crear un sistema híbrido que combinara la informática cuántica con métodos clásicos de aprendizaje automático. La idea parecía prometedora: usar los estados cuánticos para codificar la información de mercado y, a continuación, entrenar un clasificador clásico con estos datos.

El sistema resultó bastante complejo. Se basa en un circuito cuántico de 8 cúbits que convierte los datos del mercado en estados cuánticos usando una serie de puertas cuánticas. Cada fragmento de la historia de precios se codifica en ángulos de puertas ry, mientras que el entrelazamiento entre cúbits se crea utilizando puertas cx. Esto permite al sistema captar relaciones no lineales complejas en los datos.

Para mejorar la capacidad de predicción, añadí un grupo de indicadores binarios clásicos: dirección del precio, impulso, volúmenes, convergencia/divergencia de medias móviles, volatilidad, RSI y líneas de Bollinger. Cada indicador genera señales binarias, que luego se combinan con características cuánticas.

import numpy as np
import MetaTrader5 as mt5
import pandas as pd
from datetime import datetime, timedelta
from qiskit import QuantumCircuit, transpile, QuantumRegister, ClassicalRegister
from qiskit_aer import AerSimulator
from sklearn.preprocessing import MinMaxScaler, StandardScaler
from sklearn.metrics import accuracy_score, precision_score, recall_score, f1_score
from sklearn.model_selection import train_test_split
from catboost import CatBoostClassifier
import warnings
warnings.filterwarnings('ignore')

class MT5DataLoader:
    def __init__(self, symbol="EURUSD", timeframe=mt5.TIMEFRAME_H1):
        if not mt5.initialize():
            raise Exception("MetaTrader5 initialization failed")
        
        self.symbol = symbol
        self.timeframe = timeframe
    
    def get_historical_data(self, lookback_bars=1000):
        current_time = datetime.now()
        rates = mt5.copy_rates_from(self.symbol, self.timeframe, current_time, lookback_bars)
        
        if rates is None:
            raise Exception(f"Failed to get data for {self.symbol}")
            
        df = pd.DataFrame(rates)
        df['time'] = pd.to_datetime(df['time'], unit='s')
        return df

class BinaryPatternGenerator:
    def __init__(self, df, lookback=10):
        self.df = df
        self.lookback = lookback
        
    def direction_encoding(self):
        return (self.df['close'] > self.df['close'].shift(1)).astype(int)
        
    def momentum_encoding(self, threshold=0.0001):
        returns = self.df['close'].pct_change()
        return (returns.abs() > threshold).astype(int)
        
    def volume_encoding(self):
        return (self.df['tick_volume'] > self.df['tick_volume'].rolling(self.lookback).mean()).astype(int)
        
    def convergence_encoding(self):
        ma_fast = self.df['close'].rolling(5).mean()
        ma_slow = self.df['close'].rolling(20).mean()
        return (ma_fast > ma_slow).astype(int)
        
    def volatility_encoding(self):
        volatility = self.df['high'] - self.df['low']
        avg_volatility = volatility.rolling(20).mean()
        return (volatility > avg_volatility).astype(int)
        
    def rsi_encoding(self, period=14, threshold=50):
        delta = self.df['close'].diff()
        gain = (delta.where(delta > 0, 0)).ewm(alpha=1/period).mean()
        loss = (-delta.where(delta < 0, 0)).ewm(alpha=1/period).mean()
        rs = gain / loss
        rsi = 100 - (100 / (1 + rs))
        return (rsi > threshold).astype(int)
        
    def bollinger_encoding(self, window=20):
        ma = self.df['close'].rolling(window=window).mean()
        std = self.df['close'].rolling(window=window).std()
        upper = ma + (std * 2)
        lower = ma - (std * 2)
        return ((self.df['close'] - lower)/(upper - lower) > 0.5).astype(int)
        
    def get_all_patterns(self):
        patterns = {
            'direction': self.direction_encoding(),
            'momentum': self.momentum_encoding(),
            'volume': self.volume_encoding(),
            'convergence': self.convergence_encoding(),
            'volatility': self.volatility_encoding(),
            'rsi': self.rsi_encoding(),
            'bollinger': self.bollinger_encoding()
        }
        return patterns

class QuantumFeatureGenerator:
    def __init__(self, num_qubits=8):
        self.num_qubits = num_qubits
        self.simulator = AerSimulator()
        self.scaler = MinMaxScaler()
        
    def create_quantum_circuit(self, market_data, current_price):
        qr = QuantumRegister(self.num_qubits, 'qr')
        cr = ClassicalRegister(self.num_qubits, 'cr')
        qc = QuantumCircuit(qr, cr)
        
        # Нормализуем данные
        scaled_data = self.scaler.fit_transform(market_data.reshape(-1, 1)).flatten()
        
        # Создаем суперпозицию
        for i in range(self.num_qubits):
            qc.h(qr[i])
        
        # Применяем рыночные данные как фазы
        for i in range(min(len(scaled_data), self.num_qubits)):
            angle = float(scaled_data[i] * np.pi)
            qc.ry(angle, qr[i])
        
        # Создаем запутанность
        for i in range(self.num_qubits - 1):
            qc.cx(qr[i], qr[i + 1])
        
        # Добавляем текущую цену
        price_angle = float((current_price % 0.01) * 100 * np.pi)
        qc.ry(price_angle, qr[0])
        
        qc.measure(qr, cr)
        return qc
        
    def get_quantum_features(self, market_data, current_price):
        qc = self.create_quantum_circuit(market_data, current_price)
        compiled_circuit = transpile(qc, self.simulator, optimization_level=3)
        job = self.simulator.run(compiled_circuit, shots=2000)
        result = job.result()
        counts = result.get_counts()
        
        # Создаем вектор квантовых признаков
        feature_vector = np.zeros(2**self.num_qubits)
        total_shots = sum(counts.values())
        
        for bitstring, count in counts.items():
            index = int(bitstring, 2)
            feature_vector[index] = count / total_shots
            
        return feature_vector


class HybridQuantumBinaryPredictor:
    def __init__(self, num_qubits=8, lookback=10, forecast_window=5):
        self.num_qubits = num_qubits
        self.lookback = lookback
        self.forecast_window = forecast_window
        self.quantum_generator = QuantumFeatureGenerator(num_qubits)
        self.model = CatBoostClassifier(
            iterations=500,
            learning_rate=0.03,
            depth=6,
            loss_function='Logloss',
            verbose=False
        )
        
    def prepare_features(self, df):
        """Подготовка гибридных признаков"""
        pattern_generator = BinaryPatternGenerator(df, self.lookback)
        binary_patterns = pattern_generator.get_all_patterns()
        
        features = []
        labels = []
        
        # Заполняем NaN в бинарных паттернах
        for key in binary_patterns:
            binary_patterns[key] = binary_patterns[key].fillna(0)
        
        for i in range(self.lookback, len(df) - self.forecast_window):
            try:
                # Квантовые признаки
                market_data = df['close'].iloc[i-self.lookback:i].values
                current_price = df['close'].iloc[i]
                quantum_features = self.quantum_generator.get_quantum_features(market_data, current_price)
                
                # Бинарные признаки
                binary_vector = []
                for key in binary_patterns:
                    window = binary_patterns[key].iloc[i-self.lookback:i].values
                    binary_vector.extend([
                        sum(window),  # Общее количество сигналов
                        window[-1],   # Последний сигнал
                        sum(window[-3:])  # Последние 3 сигнала
                    ])
                
                # Технические индикаторы
                rsi = binary_patterns['rsi'].iloc[i]
                bollinger = binary_patterns['bollinger'].iloc[i]
                momentum = binary_patterns['momentum'].iloc[i]
                
                # Объединяем все признаки
                feature_vector = np.concatenate([
                    quantum_features,
                    binary_vector,
                    [rsi, bollinger, momentum]
                ])
                
                # Метка: направление движения цены
                future_price = df['close'].iloc[i + self.forecast_window]
                current_price = df['close'].iloc[i]
                label = 1 if future_price > current_price else 0
                
                features.append(feature_vector)
                labels.append(label)
                
            except Exception as e:
                print(f"Error at index {i}: {str(e)}")
                continue
        
        return np.array(features), np.array(labels)
    
    def train(self, df):
        """Обучение гибридной модели"""
        print("Preparing features...")
        X, y = self.prepare_features(df)
        
        # Разделение на обучающую и тестовую выборки
        split_point = int(len(X) * 0.8)
        X_train, X_test = X[:split_point], X[split_point:]
        y_train, y_test = y[:split_point], y[split_point:]
        
        print("Training model...")
        self.model.fit(X_train, y_train, eval_set=(X_test, y_test))
        
        # Оценка модели
        predictions = self.model.predict(X_test)
        probas = self.model.predict_proba(X_test)
        
        # Расчет метрик
        metrics = {
            'accuracy': accuracy_score(y_test, predictions),
            'precision': precision_score(y_test, predictions),
            'recall': recall_score(y_test, predictions),
            'f1': f1_score(y_test, predictions)
        }
        
        # Анализ важности признаков
        feature_importance = self.model.feature_importances_
        quantum_importance = np.mean(feature_importance[:2**self.num_qubits])
        binary_importance = np.mean(feature_importance[2**self.num_qubits:])
        
        metrics.update({
            'quantum_importance': quantum_importance,
            'binary_importance': binary_importance,
            'test_predictions': predictions,
            'test_probas': probas,
            'test_actual': y_test
        })
        
        return metrics
    
    def predict_next(self, df):
        """Прогноз следующего движения"""
        X, _ = self.prepare_features(df)
        if len(X) > 0:
            last_features = X[-1].reshape(1, -1)
            prediction_proba = self.model.predict_proba(last_features)[0]
            prediction = self.model.predict(last_features)[0]
            
            return {
                'direction': 'UP' if prediction == 1 else 'DOWN',
                'probability_up': prediction_proba[1],
                'probability_down': prediction_proba[0],
                'confidence': max(prediction_proba)
            }
        return None

def test_hybrid_model(symbol="EURUSD", timeframe=mt5.TIMEFRAME_H1, periods=1000):
    """Полное тестирование гибридной модели"""
    try:
        # Инициализация MT5
        if not mt5.initialize():
            raise Exception("Failed to initialize MT5")
        
        # Загрузка данных
        print(f"Loading {periods} periods of {symbol} {timeframe} data...")
        loader = MT5DataLoader(symbol, timeframe)
        df = loader.get_historical_data(periods)
        
        # Создание и обучение модели
        print("Creating hybrid model...")
        model = HybridQuantumBinaryPredictor()
        
        # Обучение и оценка
        print("Training and evaluating model...")
        metrics = model.train(df)
        
        # Вывод результатов
        print("\nModel Performance Metrics:")
        print(f"Accuracy: {metrics['accuracy']:.2%}")
        print(f"Precision: {metrics['precision']:.2%}")
        print(f"Recall: {metrics['recall']:.2%}")
        print(f"F1 Score: {metrics['f1']:.2%}")
        
        print("\nFeature Importance Analysis:")
        print(f"Quantum Features: {metrics['quantum_importance']:.2%}")
        print(f"Binary Features: {metrics['binary_importance']:.2%}")
        
        # Текущий прогноз
        print("\nCurrent Market Prediction:")
        prediction = model.predict_next(df)
        if prediction:
            print(f"Predicted Direction: {prediction['direction']}")
            print(f"Up Probability: {prediction['probability_up']:.2%}")
            print(f"Down Probability: {prediction['probability_down']:.2%}")
            print(f"Confidence: {prediction['confidence']:.2%}")
        
        return model, metrics
        
    finally:
        mt5.shutdown()

if __name__ == "__main__":
    print("Starting Quantum-Binary Hybrid Trading System...")
    model, metrics = test_hybrid_model()
    print("\nSystem test completed.")

Los primeros resultados resultaron aleccionadores. En el marco temporal de horas de EURUSD, la precisión del sistema fue solo del 42,13%, lo que resulta incluso peor que adivinar al azar. La precisión del 39,71% y la recuperación del 27% indican que el modelo se equivoca mucho en sus predicciones. La puntuación F1 del 32,14% confirma la debilidad general de las predicciones.

El análisis de la importancia de las características resultó especialmente interesante. Los rasgos cuánticos contribuyeron solo en un 27,63% al poder predictivo global del modelo, mientras que los rasgos binarios mostraron una significación del 121,95%. Esto sugiere que, o bien la parte cuántica del sistema no está captando patrones importantes en los datos, o bien el propio método de codificación cuántica necesita una seria mejora.

Pero estos resultados no son desalentadores, sino que, por el contrario, nos indican áreas específicas de mejora. Puede que merezca la pena cambiar el esquema de codificación cuántica, aumentar o disminuir el número de cúbits, o experimentar con otras puertas cuánticas. O quizá el problema sea cómo se integran entre sí las características cuánticas y las clásicas.

El experimento ha demostrado que crear un sistema híbrido cuántico-clásico eficiente no es simplemente cuestión de combinar los dos enfoques. Se requiere un profundo conocimiento tanto de la computación cuántica como de las particularidades de los mercados financieros. Este es solo el primer paso de un largo viaje de investigación y optimizaciones.

En las próximas iteraciones, planeo reelaborar sustancialmente la parte cuántica del sistema, quizá añadiendo transformaciones cuánticas más complejas y mejorando la forma de codificar la información de mercado en estados cuánticos. También vale la pena experimentar con distintas formas de combinar características cuánticas y clásicas para encontrar el mejor equilibrio entre ellas.




Conclusión

De inicio, pensé que combinar la computación cuántica con el análisis técnico era una gran idea. Ya sabe, como en las películas: cogemos una tecnología genial, añadimos algo de magia de aprendizaje automático y ya está: ¡la imprenta de dinero está lista! Y en realidad, no es así.

Mi "ingenioso" clasificador cuántico apenas ha alcanzado el 42% de precisión. ¡Es aún peor que lanzar una moneda al aire! ¿Y sabe qué es lo gracioso? Todas esas extravagancias cuánticas en las que he estado trabajando durante semanas solo han sido útiles en un 27%. Y los viejos indicadores técnicos, que añadí "por si acaso", se dispararon un 122%.

Me entusiasmé especialmente cuando comencé a estudiar la codificación cuántica de datos. Imagínese, ¡tomamos los movimientos ordinarios de los precios y los convertimos en estados cuánticos! Parece ciencia ficción, pero la verdad es que funciona, aunque no en la forma que nos gustaría.

Hasta ahora, mi clasificador cuántico se parece más a una calculadora estropeada que a un sistema comercial del futuro. Pero no voy a rendirme, porque en algún lugar de este extraño mundo de estados cuánticos y patrones de mercado se esconde algo que realmente merece la pena. Y tengo la intención de encontrarlo, aunque tenga que reescribir el código completo desde cero.

Pero, mientras tanto... Mientras tanto, volveremos a nuestros cúbits. Y es que el circuito "cuántico" convencional ha mostrado algunos resultados. Mejor que adivinar sin más... Tengo un par de ideas sobre cómo hacer que esto funcione. Y puede estar seguro de que se las contaré.


Programas usados en el artículo

 Archivo Contenido del archivo
Quant_Predict_p_1.py 
Predicción cuántica clásica con intento de detectar precursores
Quant_Neural_Link.py 
Versión preliminar de la red neuronal cuántica
Quant_ML_Model.py 
Versión preliminar de un modelo cuántico de aprendizaje automático




Traducción del ruso hecha por MetaQuotes Ltd.
Artículo original: https://www.mql5.com/ru/articles/16879

Archivos adjuntos |
Quant_ML_Model.py (12.51 KB)
Del básico al intermedio: Estructuras (IV) Del básico al intermedio: Estructuras (IV)
En este artículo, veremos cómo producir el llamado código estructural, en el que se coloca todo el contexto y las formas de manipular variables e información dentro de una estructura, con el fin de generar un contexto adecuado para la implementación de cualquier código. Veremos la necesidad de utilizar la cláusula private para separar lo que es público de lo que no, espetando así la regla de encapsulamiento y manteniendo el contexto para el que se creó una estructura de datos.
De Python a MQL5: Un viaje hacia los sistemas de trading inspirados en la cuántica De Python a MQL5: Un viaje hacia los sistemas de trading inspirados en la cuántica
El artículo analiza el desarrollo de un sistema de negociación inspirado en la cuántica, pasando de un prototipo en Python a una implementación en MQL5 para la negociación en el mundo real. El sistema utiliza principios de computación cuántica, como la superposición y el entrelazamiento, para analizar los estados del mercado, aunque funciona en ordenadores clásicos utilizando simuladores cuánticos. Las características principales incluyen un sistema de tres qubits para analizar ocho estados del mercado simultáneamente, períodos de revisión de 24 horas y siete indicadores técnicos para el análisis del mercado. Aunque los índices de precisión puedan parecer modestos, proporcionan una ventaja significativa cuando se combinan con estrategias adecuadas de gestión de riesgos.
Características del Wizard MQL5 que debe conocer (Parte 48): Bill Williams Alligator Características del Wizard MQL5 que debe conocer (Parte 48): Bill Williams Alligator
El indicador Alligator, creado por Bill Williams, es un indicador versátil para identificar tendencias que proporciona señales claras y que a menudo se combina con otros indicadores. Las clases y el ensamblador del asistente MQL5 nos permiten probar una variedad de señales basadas en patrones, por lo que también tenemos en cuenta este indicador.
Del básico al intermedio: Struct (III) Del básico al intermedio: Struct (III)
En este artículo, veremos qué es un código estructurado. Muchas personas confunden el código estructurado con el código organizado. Sin embargo, existe una diferencia entre ambos conceptos. Esto se explicará en este artículo. A pesar de la aparente complejidad que se notará en el primer contacto con este tipo de codificación, he intentado abordar el tema de la mejor manera posible. Pero este artículo es solo el primer paso hacia algo más grande.