Discusión sobre el artículo "Visión por computadora para el trading (Parte 1): Creamos una funcionalidad básica sencilla"

 

Artículo publicado Visión por computadora para el trading (Parte 1): Creamos una funcionalidad básica sencilla:

Sistema de previsión de EURUSD mediante visión por computadora y aprendizaje profundo. Descubra cómo las redes neuronales convolucionales pueden reconocer patrones de precios complejos en el mercado de divisas y predecir la evolución de los tipos con una precisión de hasta el 54%. El artículo revela la metodología de creación de un algoritmo que usa tecnologías de inteligencia artificial para analizar visualmente los gráficos en lugar de los indicadores técnicos tradicionales. El autor muestra el proceso de transformación de los datos de precios en "imágenes", su procesamiento por una red neuronal y una visión única de la "conciencia" de la IA a través de mapas de activación y mapas de calor de la atención. El práctico código Python que utiliza la biblioteca MetaTrader 5 permite a los lectores reproducir el sistema y aplicarlo a sus propias transacciones.

¿Se ha preguntado alguna vez qué siente una red neuronal al observar el mercado EURUSD? ¿Cómo percibe cada pico de volatilidad, cada cambio de tendencia, cada escurridiza formación de patrones?

Imagínese: una computadora que no se limita a aplicar sin pensar reglas preprogramadas, sino que realmente ve el mercado y capta los sutiles matices de los movimientos de los precios que son inaccesibles al ojo humano. Inteligencia artificial que mira el gráfico del EURUSD como un capitán experimentado mira el horizonte del mar, anticipando la llegada de una tormenta mucho antes de los primeros signos de mal tiempo.

Hoy les propongo un viaje a la vanguardia de la tecnología financiera, donde la visión por computadora se une al análisis bursátil. Así, crearemos un sistema que no se limite a analizar el mercado, sino que lo entienda visualmente, reconociendo patrones complejos de movimiento de precios con la misma naturalidad con la que se reconoce la cara de un amigo entre la multitud.

Esta función crea un verdadero mapa de la mente del modelo, mostrando a qué partes del gráfico le presta más atención a la hora de tomar una decisión. Las zonas rojas de mayor atención suelen coincidir con niveles clave y puntos pivote, lo cual confirma que nuestro modelo sí ha aprendido a destacar formaciones de precios significativas.


Autor: Yevgeniy Koshtenko

 
Hola, ¿cómo estás hombre?
Realmente aprecio este artículo que ha proporcionado para nosotros. Pero todavía tengo algo que decir para alguien como yo que ha creado sistemas de comercio(EA) con lenguaje MQL5 pero tienen muy poca idea cuando se trata de aprendizaje de máquina o incluso python generalmente.
Quiero integrar ML en mi sistema de comercio para actualizarlo de un programa común que como usted dijo "es sin sentido" para tomar mejores decisiones.
En tu artículo parece que faltan algunos pasos de principiante por lo que yo sé. Tu primer código no nos dice que IDE estaremos usando (¿es meta quotes IDE?) Me gustaría saber eso y los pasos para configurarlo para todo el trabajo que haremos después.
Salvo que quizás tu artículo no sea exactamente para enseñar a principiantes desde cero (no es introductorio).
 
import MetaTrader5 as mt5
import numpy as np
import pandas as pd
import matplotlib
matplotlib.use('Agg') 
import matplotlib.pyplot as plt
from sklearn.preprocessing import MinMaxScaler
from sklearn.model_selection import train_test_split
from tensorflow.keras.models import Model
from tensorflow.keras.layers import Dense, Conv1D, MaxPooling1D, Flatten, Dropout, BatchNormalization, Input
from tensorflow.keras.callbacks import EarlyStopping
from datetime import datetime

# --- CONFIGURACIÓN ---
SYMBOL = "EURUSD"
TIMEFRAME = mt5.TIMEFRAME_H1
DATA_LOAD = 6200      # Increased to ~1 year of H1 data
WINDOW_SIZE = 48      # Ventana de entrada (48 horas)
PRED_WINDOW = 24      # Horizonte de previsión (24 horas)
BACKTEST_ROWS = 20    # Número de barras recientes a verificar manualmente

def connect_to_mt5():
    if not mt5.initialize():
        print("Error initializing MetaTrader5")
        return False
    return True

def get_historical_data(num_bars):
    # Extrayendo el recuento específico de la posición actual
    rates = mt5.copy_rates_from_pos(SYMBOL, TIMEFRAME, 0, num_bars)
    if rates is None or len(rates) == 0:
        return None
    df = pd.DataFrame(rates)
    df['time'] = pd.to_datetime(df['time'], unit='s')
    df.set_index('time', inplace=True)
    return df[['open', 'high', 'low', 'close']]

def create_images(data, window_size=48, prediction_window=24):
    images, targets = [], []
    for i in range(len(data) - window_size - prediction_window):
        window = data.iloc[i:i+window_size]
        # La etiqueta se basa en el precio después de 24 horas
        target_val = 1 if data.iloc[i+window_size+prediction_window-1]['close'] > window['close'].iloc[-1] else 0
        
        scaler = MinMaxScaler()
        window_scaled = scaler.fit_transform(window)
        
        images.append(window_scaled)
        targets.append(target_val)
    return np.array(images), np.array(targets)

def train_cv_model(images, targets):
    X_train, X_val, y_train, y_val = train_test_split(images, targets, test_size=0.15, shuffle=True)
    inputs = Input(shape=(X_train.shape[1], X_train.shape[2]))
    
    # Arquitectura CNN según lógica CV_Model.py
    x = Conv1D(64, 3, padding='same', activation='relu')(inputs)
    x = BatchNormalization()(x)
    x = MaxPooling1D(2)(x)
    x = Conv1D(128, 3, padding='same', activation='relu')(x)
    x = BatchNormalization()(x)
    x = MaxPooling1D(2)(x)
    
    x = Flatten()(x)
    x = Dense(64, activation='relu')(x)
    x = Dropout(0.3)(x)
    outputs = Dense(1, activation='sigmoid')(x)
    
    model = Model(inputs, outputs)
    model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
    model.fit(X_train, y_train, epochs=40, batch_size=64, validation_data=(X_val, y_val), 
              callbacks=[EarlyStopping(patience=10, restore_best_weights=True)], verbose=0)
    return model

def run_author_backtest(model, full_data, num_checks=20):
    """
    Backtests the last 20 hours to see if a 24-hour prediction 
    made at that time would have been correct.
    """
    print(f"\n--- BACKTEST TABLE (Last {num_checks} Prediction Points) ---")
    print(f"{'Time (UTC)':<20} | {'Pred (24h)':<10} | {'Actual (24h)':<12} | {'Result'}")
    print("-" * 75)
    
    wins = 0
    # Retrocedemos para asegurarnos de que la ventana de 24 horas ha terminado realmente para el backtest
    for i in range(num_checks + PRED_WINDOW, PRED_WINDOW, -1):
        idx = len(full_data) - i
        
        # 1. Obtenga la ventana de 48h disponible EN ESE MOMENTO
        window = full_data.iloc[idx - WINDOW_SIZE : idx]
        timestamp = full_data.index[idx-1]
        
        # 2. Obtenga el resultado REAL exactamente 24 horas después
        actual_price_then = window['close'].iloc[-1]
        actual_price_future = full_data.iloc[idx + PRED_WINDOW - 1]['close']
        actual_dir = "ARRIBA ▲" if actual_price_future > actual_price_then else "ABAJO ▼"
        
        # 3. Modelo de predicción basado en la ventana
        scaler = MinMaxScaler()
        window_scaled = scaler.fit_transform(window)
        pred_val = model.predict(np.array([window_scaled]), verbose=0)[0][0]
        pred_dir = "ARRIBA ▲" if pred_val > 0.5 else "ABAJO ▼"
        
        # 4. Resultado
        res = "✅ WIN" if pred_dir == actual_dir else "❌ PÉRDIDA"
        if res == "✅ WIN": wins += 1
        
        print(f"{str(timestamp):<20} | {pred_dir:<10} | {actual_dir:<12} | {res}")

    print("-" * 75)
    print(f"TOTAL BACKTEST ACCURACY: {(wins/num_checks)*100:.2 f}% ({wins}/{num_checks})")

def main():
    if not connect_to_mt5(): return
    
    print(f"Loading {DATA_LOAD} bars for EURUSD...")
    data = get_historical_data(DATA_LOAD)
    if data is None: 
        mt5.shutdown()
        return

    # Entrena sólo con datos que no formen parte de nuestra ventana de backtest
    train_data = data.iloc[:-(BACKTEST_ROWS + PRED_WINDOW)]
    images, targets = create_images(train_data, WINDOW_SIZE, PRED_WINDOW)
    
    print("Training model on ~1 year of data...")
    model = train_cv_model(images, targets)
    
    # Ejecutar el backtest exactamente como se especifica
    run_author_backtest(model, data, BACKTEST_ROWS)
    
    # Previsión en directo para AHORA MISMO (las próximas 24 horas)
    last_window = data.iloc[-WINDOW_SIZE:]
    scaler = MinMaxScaler()
    live_pred = model.predict(np.array([scaler.fit_transform(last_window)]), verbose=0)[0][0]
    live_dir = "ARRIBA ▲" if live_pred > 0.5 else "ABAJO ▼"
    
    print(f"\nLIVE FORECAST FOR NEXT 24 HOURS: {live_dir}")
    print(f"Confidence: {live_pred*100 if live_pred > 0.5 else (1-live_pred)*100:.2 f}%")
    input("Process complete. Press Enter to close this window...")
    
    mt5.shutdown()

if __name__ == "__main__":
    main()
Hecho pequeño cambio a las predicciones backtest hecho.