Discussing the article: "Integrating Computer Vision into Trading (Part 1): Creating Basic Functions"

 

Check out the new article: Integrating Computer Vision into Trading (Part 1): Creating Basic Functions.

The EURUSD forecasting system with the use of computer vision and deep learning. Learn how convolutional neural networks can recognize complex price patterns in the foreign exchange market and predict exchange rate movements with up to 54% accuracy. The article shares the methodology for creating an algorithm that uses artificial intelligence technologies for visual analysis of charts instead of traditional technical indicators. The author demonstrates the process of transforming price data into "images”, their processing by a neural network, and a unique opportunity to peer into the "consciousness" of AI through activation maps and attention heatmaps. Practical Python code using the MetaTrader 5 library allows readers to reproduce the system and apply it in their own trading.

Have you ever wondered what a neural network feels when it looks at the EURUSD market? How does it perceive every spike in volatility, every trend reversal, every elusive pattern formation?

Imagine a computer that does not just mindlessly apply pre-programmed rules, but truely sees the market — capturing subtle nuances of price movements that are invisible to the human eye. Artificial intelligence that looks at the EURUSD chart the way an experienced captain looks at the ocean horizon, sensing an approaching storm long before the first signs of bad weather occur.

Today, I invite you on a journey to the cutting edge of financial technology, where computer vision meets stock market analytics. We shall create a system that does not simply analyze the market — it understands it visually, recognizing complex price patterns as naturally as you recognize a friend's face in a crowd.

This feature creates a real map of the model's consciousness, showing which areas of the chart it pays most attention to when making a decision. Red zones of increased attention often coincide with key levels and reversal points, confirming that our model has indeed learned to identify significant price formations.


Author: Yevgeniy Koshtenko

 
Hi, how are you doing man? 
I really appreciate this article you have provided for us. But I still have some thing to say for someone like me who has created trading systems(EA) with MQL5 language but have very little idea when it comes to machine learning or even python generally.
I want to integrate ML into my trading system to upgrade it from a common program that like you said "is mindless" to making better decisions.
Your article seems to be missing some beginner steps as far as I know. Your first code doesn't tell us what IDE we will be using (is it meta quotes IDE?) I would like to know that and steps to set it up for all the work we will do later on.
Except maybe your article is not exactly teaching beginners from scratch (not introductory).
 
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

# --- CONFIGURATION ---
SYMBOL = "EURUSD"
TIMEFRAME = mt5.TIMEFRAME_H1
DATA_LOAD = 6200      # Increased to ~1 year of H1 data
WINDOW_SIZE = 48      # Input window (48 hours)
PRED_WINDOW = 24      # Forecast horizon (24 hours)
BACKTEST_ROWS = 20    # Number of recent bars to verify manually

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

def get_historical_data(num_bars):
    # Pulling specific count from the current position
    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]
        # Label is based on price after 24 hours
        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]))
    
    # CNN Architecture as per CV_Model.py logic
    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
    # We step back to ensure the 24-hour window has actually finished for the backtest
    for i in range(num_checks + PRED_WINDOW, PRED_WINDOW, -1):
        idx = len(full_data) - i
        
        # 1. Get the 48h window available AT THAT TIME
        window = full_data.iloc[idx - WINDOW_SIZE : idx]
        timestamp = full_data.index[idx-1]
        
        # 2. Get the ACTUAL result exactly 24 hours later
        actual_price_then = window['close'].iloc[-1]
        actual_price_future = full_data.iloc[idx + PRED_WINDOW - 1]['close']
        actual_dir = "UP ▲" if actual_price_future > actual_price_then else "DOWN ▼"
        
        # 3. Model Prediction based on window
        scaler = MinMaxScaler()
        window_scaled = scaler.fit_transform(window)
        pred_val = model.predict(np.array([window_scaled]), verbose=0)[0][0]
        pred_dir = "UP ▲" if pred_val > 0.5 else "DOWN ▼"
        
        # 4. Result
        res = "✅ WIN" if pred_dir == actual_dir else "❌ LOSS"
        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:.2f}% ({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

    # Train only on data that isn't part of our backtest window
    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)
    
    # Run the backtest exactly as specified
    run_author_backtest(model, data, BACKTEST_ROWS)
    
    # Live forecast for RIGHT NOW (the next 24 hours)
    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 = "UP ▲" if live_pred > 0.5 else "DOWN ▼"
    
    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:.2f}%")
    input("Process complete. Press Enter to close this window...")
    
    mt5.shutdown()

if __name__ == "__main__":
    main()
Done small change to backtest predictions made.