文章 "计算机视觉在MQL5中的集成(第一部分):构建基础函数"

 

新文章 计算机视觉在MQL5中的集成(第一部分):构建基础函数已发布:

基于计算机视觉与深度学习的欧元兑美元(EURUSD)汇率预测系统。探索卷积神经网络(CNN)如何识别外汇市场中的复杂价格形态,并实现最高达54%的汇率波动预测准确率。本文将分享一种突破传统技术指标的算法设计方法 —— 通过人工智能(AI)技术对K线图进行可视化分析。作者演示了将价格数据转换为“图像”的过程、神经网络的处理流程,以及通过激活热力图和注意力热图窥视AI“思维”的独特机会。通过基于MetaTrader 5库的Python实践代码,读者可完整复现系统并将其应用于自身的交易中。

您是否想过,当神经网络“审视”EURUSD市场时,它究竟“观察”到了什么?它如何解读每一次波动率的飙升、每一轮趋势的反转、每一个转瞬即逝的形态构建?

想象一台计算机,它不再机械地执行预设规则,而是真正地观察市场 —— 捕捉价格波动中那些人类肉眼无法察觉的微妙细节。正如经验丰富的船长能在风暴来临前察觉海平线气流的异动,这套AI系统也能以类似的方式解读EURUSD图表。

现在,我邀您共赴金融科技的最前沿,见证计算机视觉与市场分析的深度融合。我们将构建一个超越传统分析的系统 —— 它通过视觉理解市场,能像在人群中辨认挚友面容般自然地识别复杂价格形态。

该功能绘制出模型“思维”的实时图谱,揭示K线图中哪些区域对预测结果影响最大。高关注度红色区域往往精准覆盖关键价位与反转点,印证了模型已学会自主识别重要价格形态。


作者:Yevgeniy Koshtenko

 
嗨,你好吗?
我非常欣赏你为我们提供的这篇文章。不过,对于像我这样用 MQL5 语言创建了交易系统(EA),但对机器学习或一般 Python 语言知之甚少的人,我还有一些话要说。
我想将 ML 集成到我的交易系统中,将它从一个像你说的 "无意识 "的普通程序升级到能做出更好的决策。
据我所知,你的文章似乎缺少一些初级步骤。你的第一段代码并没有告诉我们将使用什么 IDE(是元报价 IDE 吗?
也许您的文章并不是从头开始教初学者(不是入门)。
 
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

# --- 配置 ---
SYMBOL = "EURUSD"
TIMEFRAME = mt5.TIMEFRAME_H1
DATA_LOAD = 6200      # 增加到 ~1 年的上半年数据
WINDOW_SIZE = 48      # 输入窗口(48 小时)
PRED_WINDOW = 24      # 预测范围(24 小时)
BACKTEST_ROWS = 20    # 需要手动验证的最近条数

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

def get_historical_data(num_bars):
    # 从当前位置提取特定计数
    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]
        # 标签基于 24 小时后的价格
        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 架构与 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
    # 我们后退一步,以确保 24 小时窗口实际完成回溯测试
    for i in range(num_checks + PRED_WINDOW, PRED_WINDOW, -1):
        idx = len(full_data) - i
        
        # 1.获取当时可用的 48 小时窗口
        window = full_data.iloc[idx - WINDOW_SIZE : idx]
        timestamp = full_data.index[idx-1]
        
        # 2.准确获取 24 小时后的实际结果
        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.基于窗口的模型预测
        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.结果
        res = "✅赢" if pred_dir == actual_dir else "❌损失"
        if res == "✅赢": 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

    # 只对不属于我们回溯测试窗口的数据进行训练
    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_author_backtest(model, data, BACKTEST_ROWS)
    
    # 现在(未来 24 小时)的实时预报
    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:.2 f}%")
    input("Process complete. Press Enter to close this window...")
    
    mt5.shutdown()

if __name__ == "__main__":
    main()
对所做的回溯测试 预测进行了小修改。