English Русский Español Deutsch Português
preview
MQL5における取引へのコンピュータビジョンの統合(第1回):基本関数の作成

MQL5における取引へのコンピュータビジョンの統合(第1回):基本関数の作成

MetaTrader 5トレーディングシステム |
21 0
Yevgeniy Koshtenko
Yevgeniy Koshtenko

はじめに

ローソク足チャートが金融の流れの曲がりくねった軌跡を描くモニターの静かな光の中で、取引の新時代が生まれつつあります。ニューラルネットワークがEURUSD市場を見つめるとき、それは何を感じているのでしょうか。ボラティリティの急騰、トレンドの反転、そして捉えどころのないパターン形成の一つひとつを、どのように認識しているのでしょうか。

あらかじめ定められたルールを機械的に適用するのではなく、市場を真に見るコンピュータを想像してみてください。それは人間の目には見えない価格変動の微細なニュアンスを捉えます。まるでベテラン船長が水平線を見つめ、最初の兆候が現れるはるか前に嵐の接近を察知するかのように、人工知能はEURUSDチャートを読み取ります。

本記事では、コンピュータビジョンと市場分析が融合する金融テクノロジーの最前線を紹介します。私たちは単に市場を分析するのではなく、視覚的に理解するシステムを構築します。それは、群衆の中から友人の顔を自然に見分けるように、複雑な価格パターンを認識するのです。

ミリ秒が何百万人もの運命を左右する世界において、本記事の畳み込みニューラルネットワークに基づくモデルは、テクニカル分析の新たな次元への扉を開きます。このモデルは標準的なインジケーターを使用せず、生のOHLCデータから直接シグナルを見つけ出し、解釈することを学習します。そして最も驚くべき点は、その「意識」の内側を可視化し、意思決定の前にどの特定のチャートスニペットに注目しているのかを確認できることです。


コンピュータビジョンモデルの歴史と応用

コンピュータビジョンは1960年代にマサチューセッツ工科大学(MIT)で誕生しました。当時、研究者たちは機械に視覚情報を解釈させることを初めて試みました。初期の開発は緩やかで、最初のシステムは単純な図形や輪郭しか認識できませんでした。

真のブレークスルーは2012年に到来しました。畳み込みニューラルネットワーク(CNN)の登場により、業界は大きく変革されました。AlexNetアーキテクチャはImageNetコンペティションで前例のない画像認識精度を示し、ディープラーニング時代の幕開けを告げました。

今日、コンピュータビジョン(CV)は多くの業界に変革をもたらしています。医療分野では、アルゴリズムがX線やMRI画像を熟練した放射線科医に匹敵する精度で解析します。自動車産業では、運転支援システムや自動運転技術が道路上の物体認識にCVを活用します。スマートフォンでは、写真の高画質化や顔認証によるロック解除に利用されています。セキュリティ分野では、顔認識技術がアクセス制御に活用されています。

金融分析におけるコンピュータビジョンの応用は、新しく有望な分野です。CVアルゴリズムは、従来のテクニカル指標では捉えきれない複雑なチャートパターンやフォーメーションを認識できます。これにより、アルゴリズム取引に新たな可能性が広がります。


技術基盤:市場データへの接続

私たちの旅は、市場との「生きた接続」を確立することから始まります。金融市場の流れの鼓動へと伸びる神経の末端のように、コードはMetaTrader 5ターミナルへ接続します。これは長年トレーダーに利用されてきた定番ツールであり、今では人工知能へのポータルとして機能します。

import MetaTrader5 as mt5
import matplotlib
matplotlib.use('Agg')  # Using Agg backend for running without GUI
import matplotlib.pyplot as plt
from tensorflow.keras.models import Sequential, Model
from tensorflow.keras.layers import Dense, Conv1D, MaxPooling1D, Flatten, Dropout, BatchNormalization, Input

# Connecting to MetaTrader5 terminal
def connect_to_mt5():
    if not mt5.initialize():
        print("Error initializing MetaTrader5")
        mt5.shutdown()
        return False
    return True

最初の数行のコードは、アルゴリズムの世界と金融の世界を結ぶハンドシェイクです。単なる関数呼び出しのように見えますが、その背後では世界中の何百万ものトレーダーの意思決定が交差して形成される相場データが流れ込むチャネルが構築されています。

本記事のシステムでは、GUIなしで可視化をおこなうためにAggバックエンドを使用します。これは小さな実装上の選択に見えますが、重要な意味を持ちます。リモートサーバー上でバックグラウンド実行を可能にし、市場の監視を一瞬たりとも中断することなく継続できます。


履歴データへのダイブ:データ収集と前処理

あらゆる人工知能はデータから始まります。このシステムにおいては、それは何千本ものEURUSDの1時間足です。それらは過去の価格攻防の静かな証人であり、私たちが解き明かそうとするパターンを内包しています。

def get_historical_data(symbol="EURUSD", timeframe=mt5.TIMEFRAME_H1, num_bars=1000):
    now = datetime.now()
    from_date = now - timedelta(days=num_bars/24)  # Approximate for hourly bars
    
    rates = mt5.copy_rates_range(symbol, timeframe, from_date, now)
    if rates is None or len(rates) == 0:
        print("Error loading historical quotes")
        return None
    
    # Convert to pandas DataFrame
    rates_frame = pd.DataFrame(rates)
    rates_frame['time'] = pd.to_datetime(rates_frame['time'], unit='s')
    rates_frame.set_index('time', inplace=True)
    
    return rates_frame

この関数では最初の魔法が起こります。生のバイト列は、整然としたデータストリームへと変換されます。すべてのローソク足、すべての価格変動が、多次元空間上の一点となり、ニューラルネットワークが探索する対象になります。ここでは2,000本の履歴データを読み込みます。これは、穏やかなトレンド相場から高ボラティリティの混沌とした局面まで、多様な市場環境をモデルが捉えるのに十分な量です。

しかし、コンピュータビジョンが必要とするのは数値だけではなく画像です。次のステップでは、時系列データを畳み込みネットワークが解析可能な画像へと変換します。

def create_images(data, window_size=48, prediction_window=24):
    images = []
    targets = []
    
    # Using OHLC data to create images
    for i in range(len(data) - window_size - prediction_window):
        window_data = data.iloc[i:i+window_size]
        target_data = data.iloc[i+window_size:i+window_size+prediction_window]
        
        # Normalize data in the window
        scaler = MinMaxScaler(feature_range=(0, 1))
        window_scaled = scaler.fit_transform(window_data[['open', 'high', 'low', 'close']])
        
        # Predict price direction (up/down) for the forecast period
        price_direction = 1 if target_data['close'].iloc[-1] > window_data['close'].iloc[-1] else 0
        
        images.append(window_scaled)
        targets.append(price_direction)
    
    return np.array(images), np.array(targets)

これは純粋なデータ錬金術です。連続する48本のバーを1つのウィンドウとして取得し、その値を0から1の範囲に正規化します。そしてOHLCそれぞれをチャネルとするマルチチャネル画像へと変換します。さらに、それぞれの市場履歴「フレーム」に対して、24本先の価格変動の方向というターゲット値を決定します。

スライディングウィンドウはデータセット全体を順次移動し、学習用の数千件のサンプルを生成します。これは、熟練トレーダーが過去チャートをスクロールしながら市場パターンを吸収し、大きな値動きの前兆となる状況を学習していくプロセスに似ています。


ニューラル「眼」の設計:モデルアーキテクチャ

次に、適切なニューラルネットワークの作成に進みます。これは市場データの混沌の中に潜む秩序を探し出す人工の「眼」です。このアーキテクチャは近年のコンピュータビジョンの進展に着想を得ていますが、金融時系列データの特性に適応させています。

def train_cv_model(images, targets):
    # Split data into training and validation sets
    X_train, X_val, y_train, y_val = train_test_split(images, targets, test_size=0.2, shuffle=True, random_state=42)
    
    # Create model with improved architecture
    inputs = Input(shape=X_train.shape[1:])
    
    # First convolutional block
    x = Conv1D(filters=64, kernel_size=3, padding='same', activation='relu')(inputs)
    x = BatchNormalization()(x)
    x = Conv1D(filters=64, kernel_size=3, padding='same', activation='relu')(x)
    x = BatchNormalization()(x)
    x = MaxPooling1D(pool_size=2)(x)
    x = Dropout(0.2)(x)
    
    # Second convolutional block
    x = Conv1D(filters=128, kernel_size=3, padding='same', activation='relu')(x)
    x = BatchNormalization()(x)
    x = Conv1D(filters=128, kernel_size=3, padding='same', activation='relu')(x)
    x = BatchNormalization()(x)
    x = MaxPooling1D(pool_size=2)(x)
    feature_maps = x  # Store feature maps for visualization
    x = Dropout(0.2)(x)
    
    # Output block
    x = Flatten()(x)
    x = Dense(128, activation='relu')(x)
    x = BatchNormalization()(x)
    x = Dropout(0.3)(x)
    x = Dense(64, activation='relu')(x)
    x = BatchNormalization()(x)
    x = Dropout(0.3)(x)
    outputs = Dense(1, activation='sigmoid')(x)
    
    # Create the full model
    model = Model(inputs=inputs, outputs=outputs)
    
    # Create a feature extraction model for visualization
    feature_model = Model(inputs=model.input, outputs=feature_maps)

実装では、シーケンシャルモデルではなくKerasのFunctional APIを使用します。これにより、可視化のために中間表現を抽出する追加モデルを柔軟に構築できます。これは本アプローチの重要な要素です。私たちは単なる予測システムを構築するのではなく、人工知能の「意識」をのぞき込むためのツールも同時に作ります。

アーキテクチャは2つの畳み込みブロックで構成され、それぞれにバッチ正規化を伴う2層の畳み込み層を含みます。最初のブロックは64フィルタ、2番目のブロックは128フィルタを使用し、より複雑なパターンを段階的に抽出します。特徴量抽出後、データは複数の全結合層に渡され、得られた情報を統合して最終予測を生成します。

モデルの学習は単なる損失関数の最小化ではありません。それはパラメータ空間を探索するプロセスであり、各イテレーションが目標へと私たちを近づけます。

# Early stopping to prevent overfitting
early_stopping = EarlyStopping(
    monitor='val_loss',
    patience=10,
    restore_best_weights=True,
    verbose=1
)

# Train model
history = model.fit(
    X_train, y_train,
    epochs=50,
    batch_size=32,
    validation_data=(X_val, y_val),
    callbacks=[early_stopping],
    verbose=1
)

過学習を防ぐために早期停止を使用します。検証データに対する性能改善が止まった時点で学習を終了します。これにより、未学習(学習不足)と過学習の間にある最適なバランス、すなわち最大の汎化性能を持つポイントを見つけます。


人工知能の意識を覗く

本アプローチの独自性は、モデルが市場を「どのように見ているか」を可視化できる点にあります。私たちはニューラルネットワークの内部を覗くために、2つの特別な機能を開発しました。

def visualize_model_perception(feature_model, last_window_scaled, window_size=48):
    # Get feature maps for the last window
    feature_maps = feature_model.predict(np.array([last_window_scaled]))[0]
    
    # Plot feature maps
    plt.figure(figsize=(7, 10))
    
    # Plot original data
    plt.subplot(5, 1, 1)
    plt.title("Original Price Data (Normalized)")
    plt.plot(np.arange(window_size), last_window_scaled[:, 0], label='Open', alpha=0.7)
    plt.plot(np.arange(window_size), last_window_scaled[:, 1], label='High', alpha=0.7)
    plt.plot(np.arange(window_size), last_window_scaled[:, 2], label='Low', alpha=0.7)
    plt.plot(np.arange(window_size), last_window_scaled[:, 3], label='Close', color='black', linewidth=2)
    
    # Plot candlestick representation
    plt.subplot(5, 1, 2)
    plt.title("Candlestick Representation")
    
    # Width of the candles
    width = 0.6
    
    for i in range(len(last_window_scaled)):
        # Candle color
        if last_window_scaled[i, 3] >= last_window_scaled[i, 0]:  # close >= open
            color = 'green'
            body_bottom = last_window_scaled[i, 0]  # open
            body_height = last_window_scaled[i, 3] - last_window_scaled[i, 0]  # close - open
        else:
            color = 'red'
            body_bottom = last_window_scaled[i, 3]  # close
            body_height = last_window_scaled[i, 0] - last_window_scaled[i, 3]  # open - close
        
        # Candle body
        plt.bar(i, body_height, bottom=body_bottom, color=color, width=width, alpha=0.5)
        
        # Candle wicks
        plt.plot([i, i], [last_window_scaled[i, 2], last_window_scaled[i, 1]], color='black', linewidth=1)
    
    # Plot feature maps visualization (first 3 channels)
    plt.subplot(5, 1, 3)
    plt.title("Feature Map Channel 1 - Pattern Recognition")
    plt.plot(time_indices, feature_maps[:, 0], color='blue')
    
    plt.subplot(5, 1, 4)
    plt.title("Feature Map Channel 2 - Trend Detection")
    plt.plot(time_indices, feature_maps[:, 1], color='orange')
    
    plt.subplot(5, 1, 5)
    plt.title("Feature Map Channel 3 - Volatility Detection")
    plt.plot(time_indices, feature_maps[:, 2], color='green')

この関数では、マルチパネルの可視化を作成します。パネルには、元データ、ローソク足表現、そして畳み込みフィルタの最初の3チャネルの活性化が表示されます。それぞれのチャネルは市場の異なる側面に特化しています。1つは繰り返し出現するパターンを捉え、別のチャネルはトレンドを検出し、さらに別のチャネルはボラティリティに反応します。まるで熟練トレーダーの脳の異なる領域の専門性を明らかにするかのようです。

さらに興味深い結果を提供するのがアテンションヒートマップです。

def visualize_attention_heatmap(feature_model, last_window_scaled, window_size=48):
    # Get feature maps for the last window
    feature_maps = feature_model.predict(np.array([last_window_scaled]))[0]
    
    # Average activation across all channels to get a measure of "attention"
    avg_activation = np.mean(np.abs(feature_maps), axis=1)
    
    # Normalize to [0, 1] for visualization
    attention = (avg_activation - np.min(avg_activation)) / (np.max(avg_activation) - np.min(avg_activation))
    
    # Upsample attention to match original window size
    upsampled_attention = np.zeros(window_size)
    ratio = window_size / len(attention)
    
    for i in range(len(attention)):
        start_idx = int(i * ratio)
        end_idx = int((i+1) * ratio)
        upsampled_attention[start_idx:end_idx] = attention[i]
    
    # Plot the heatmap
    plt.figure(figsize=(7, 6))
    
    # Price plot with attention heatmap
    plt.subplot(2, 1, 1)
    plt.title("Model Attention Heatmap")
    
    # Plot close prices
    time_indices = np.arange(window_size)
    plt.plot(time_indices, last_window_scaled[:, 3], color='black', linewidth=2, label='Close Price')
    
    # Add shading based on attention
    plt.fill_between(time_indices, last_window_scaled[:, 3].min(), last_window_scaled[:, 3].max(), 
                     alpha=upsampled_attention * 0.5, color='red')
                     
    # Highlight points with high attention
    high_attention_threshold = 0.7
    high_attention_indices = np.where(upsampled_attention > high_attention_threshold)[0]
    plt.scatter(high_attention_indices, last_window_scaled[high_attention_indices, 3], 
               color='red', s=50, zorder=5, label='High Attention Points')

この機能は、モデルが意思決定時にチャートのどの領域に最も注意を払っているかを可視化する、人工知能の「意識」の実際のマップを生成します。注意が高い赤いゾーンは、しばしば重要な価格レベルや反転ポイントと一致し、モデルが重要な価格形成を正しく学習していることを確認できます。


予測から利益へ:実践的応用

システムの最終パートは、予測を可視化し、トレーダーに理解可能な形で提示することです。

def plot_prediction(data, window_size=48, prediction_window=24, direction="UP ▲"):
    plt.figure(figsize=(7, 4.2))
    
    # Get the last window of data for visualization
    last_window = data.iloc[-window_size:]
    
    # Create time index for prediction
    last_date = last_window.index[-1]
    future_dates = pd.date_range(start=last_date, periods=prediction_window+1, freq=data.index.to_series().diff().mode()[0])[1:]
    
    # Plot closing prices
    plt.plot(last_window.index, last_window['close'], label='Historical Data')
    
    # Add marker for current price
    current_price = last_window['close'].iloc[-1]
    plt.scatter(last_window.index[-1], current_price, color='blue', s=100, zorder=5)
    plt.annotate(f'Current price: {current_price:.5f}', 
                 xy=(last_window.index[-1], current_price),
                 xytext=(10, -30),
                 textcoords='offset points',
                 fontsize=10,
                 arrowprops=dict(arrowstyle='->', color='black'))
    
    # Visualize the predicted direction
    arrow_start = (last_window.index[-1], current_price)
    
    # Calculate range for the arrow (approximately 10% of price range)
    price_range = last_window['high'].max() - last_window['low'].min()
    arrow_length = price_range * 0.1
    
    # Up or down prediction
    if direction == "UP ▲":
        arrow_end = (future_dates[-1], current_price + arrow_length)
        arrow_color = 'green'
    else:
        arrow_end = (future_dates[-1], current_price - arrow_length)
        arrow_color = 'red'
    
    # Direction arrow
    plt.annotate('', 
                 xy=arrow_end,
                 xytext=arrow_start,
                 arrowprops=dict(arrowstyle='->', lw=2, color=arrow_color))
    
    plt.title(f'EURUSD - Forecast for {prediction_window} periods: {direction}')

この可視化により、抽象的な予測が明確な売買シグナルへと変換されます。緑の矢印は価格の上昇予想を示し、赤の矢印は下降を示します。トレーダーは瞬時に現状を把握し、人工知能による分析を根拠に意思決定をおこなうことができます。

しかし、本システムは単に価格の方向を予測するだけではありません。予測確率の定量的評価も提供します。

# Predict on the last available window
def make_prediction(model, data, window_size=48):
    # Get the last window of data
    last_window = data.iloc[-window_size:][['open', 'high', 'low', 'close']]
    
    # Normalize data
    scaler = MinMaxScaler(feature_range=(0, 1))
    last_window_scaled = scaler.fit_transform(last_window)
    
    # Prepare data for the model
    last_window_reshaped = np.array([last_window_scaled])
    
    # Get prediction
    prediction = model.predict(last_window_reshaped)[0][0]
    
    # Interpret result
    direction = "UP ▲" if prediction > 0.5 else "DOWN ▼"
    confidence = prediction if prediction > 0.5 else 1 - prediction
    
    return direction, confidence * 100, last_window_scaled

ニューラルネットワークの出力値は単なる二値の答えとして解釈されるのではなく、上昇の確率として理解されます。これにより、トレーダーは方向だけでなく、システムの予測に対する信頼度を考慮して意思決定することができます。例えば、信頼度95%の予測は、信頼度55%の予測よりも積極的なポジションを取る根拠となります。


プロセスのオーケストレーション:メイン関数

すべてのシステム要素は、データ接続から結果の可視化までの全工程を統括するメイン関数に統合されます。

def main():
    print("Starting EURUSD prediction system with computer vision")
    
    # Connect to MT5
    if not connect_to_mt5():
        return
    
    print("Successfully connected to MetaTrader5")
    
    # Load historical data
    bars_to_load = 2000  # Load more than needed for training
    data = get_historical_data(num_bars=bars_to_load)
    if data is None:
        mt5.shutdown()
        return
    
    print(f"Loaded {len(data)} bars of EURUSD history")
    
    # Convert data to image format
    print("Converting data for computer vision processing...")
    images, targets = create_images(data)
    print(f"Created {len(images)} images for training")
    
    # Train model
    print("Training computer vision model...")
    model, history, feature_model = train_cv_model(images, targets)
    
    # Visualize training process
    plot_learning_history(history)
    
    # Prediction
    direction, confidence, last_window_scaled = make_prediction(model, data)
    print(f"Forecast for the next 24 periods: {direction} (confidence: {confidence:.2f}%)")
    
    # Visualize prediction
    plot_prediction(data, direction=direction)
    
    # Visualize how the model "sees" the market
    visualize_model_perception(feature_model, last_window_scaled)
    
    # Visualize attention heatmap
    visualize_attention_heatmap(feature_model, last_window_scaled)
    
    # Disconnect from MT5
    mt5.shutdown()
    print("Work completed")

この関数は、データとアルゴリズムの複雑なシンフォニーを指揮する指揮者のような役割を果たします。ターミナルへの最初の接続から、人工知能の内部世界を明らかにする最終的な可視化まで、プロセス全体をステップごとに案内します。


結論:アルゴリズム取引の新時代

私たちは、単なる新しいテクニカル指標や取引システム以上のものを作り上げました。このコンピュータビジョンモデルは市場を認識する新しい方法であり、人間の視覚を超えて価格変動のノイズの中に隠れたパターンを発見するためのツールです。

これは未知の信号を出すブラックボックスではありません。可視化機能により、モデルが市場をどのように認識しているか、どの価格変動の特徴に注目しているか、そして予測がどのように形成されるかを確認できます。これにより、トレーダーとアルゴリズムの間に新たな信頼と理解が生まれます。

1秒間に何百万もの取引を行う高頻度アルゴリズムの時代において、本システムは異なる、より深いアプローチを提供します。速度に依存するのではなく、コンピュータビジョンを通じて市場ダイナミクスを深く理解することに基づくアルゴリズム取引です。

コードは公開されており、技術も利用可能であり、結果も印象的です。取引におけるコンピュータビジョンの世界への旅は今まさに始まったばかりです。そしてもしかすると、このアルゴリズム的なニューラルネットワークの視点こそ、従来見えなかったものを捉え、絶えず変化する通貨市場の動きを理解する鍵を与えてくれるかもしれません。

未来の取引セッションを想像してください。画面には従来のローソク足チャートやインジケーターラインだけでなく、人工知能が現在の市場状況をどのように認識しているか、どのパターンに注目しているか、どの価格水準に特別な注意を払っているかがリアルタイムで可視化されています。これはSFではなく、今日利用可能な技術です。あとは、新しいアルゴリズム取引の時代に一歩を踏み出すだけです。

MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/17981

添付されたファイル |
CV_Model.py (15.71 KB)
MQL5 MVCパラダイムにおけるテーブルのビューおよびコントローラーコンポーネント:コンテナ MQL5 MVCパラダイムにおけるテーブルのビューおよびコントローラーコンポーネント:コンテナ
この記事では、コンテンツのスクロールに対応したContainer(コンテナ)コントロールの作成について解説します。その過程で、既存のグラフィックライブラリのコントロールクラスを改良していきます。
初級から中級まで:インジケーター(II) 初級から中級まで:インジケーター(II)
本記事では、移動平均の計算をどのように実装するか、またその計算をおこなう際にどのような点に注意すべきかを確認します。さらに、OnCalculate関数のオーバーロードについても取り上げ、どのバージョンをいつ、どのように扱うべきかを理解していきます。
FXにおけるスワップ差裁定:合成ポートフォリオの構築と一貫したスワップフローの生成 FXにおけるスワップ差裁定:合成ポートフォリオの構築と一貫したスワップフローの生成
金利差を活用して利益を得る方法をご存じでしょうか。本記事では、FXにおけるスワップ差裁定(スワップアービトラージ)を活用し、毎晩安定した利益を生み出し、市場の変動に強いポートフォリオを構築する方法について解説します。
市場シミュレーション(第10回):ソケット(V) 市場シミュレーション(第10回):ソケット(V)
これからExcelとMetaTrader 5の接続の実装を始めますが、その前にいくつか押さえておくべき重要なポイントがあります。これを理解しておくことで、なぜ動くのか、なぜ動かないのかで悩む必要がなくなります。そして、PythonとExcelを組み合わせることに尻込みする前に、xlwingsを使ってExcelからMetaTrader 5をある程度操作できる方法を見てみましょう。ここで紹介する内容は主に教育目的ですが、もちろん、ここで取り上げることだけに制限されるわけではありません。