データサイエンスと機械学習(第27回):MetaTrader 5取引ボットにおける畳み込みニューラルネットワーク(CNN)に価値はあるか?
畳み込みニューラルネットワークで使われているプーリング演算は大きな間違いであり、それがうまく機能していることが災いしている。
ジェフリー・ヒントン
内容
- 畳み込みニューラルネットワーク(CNN)とは?
- 畳み込み層
- 活性化関数
- プーリング層
- 全結合層
- ドロップアウト層 - なぜ畳み込みニューラルネットワーク(CNN)を金融分析や取引に使うのか?
- Pythonで畳み込みニューラルネットワーク(CNN)を作る
- 畳み込みニューラルネットワーク(CNN)ベースの取引ロボットの作成
- 結論
この記事の内容を完全に理解するためには、プログラミング言語、人工ニューラルネットワーク、機械学習、MQL5におけるONNXについての基本的な理解が必要です。
畳み込みニューラルネットワーク(CNN)とは?
畳み込みニューラルネットワーク(CNN)は、画像、音声スペクトログラム、時系列データなど、構造化されたグリッド状のデータを処理するために特別に設計された深層学習アルゴリズムのクラスです。入力データから特徴の空間階層を自動的かつ適応的に学習できるため、視覚データタスクに特に適しています。
CNNは人工ニューラルネットワーク(ANN)の拡張版です。これらは主にグリッド状の行列データセットから特徴を抽出するために使用されます。例えば、画像や動画のような視覚的データセットでは、データパターンが重要な役割を果たします。
畳み込みニューラルネットワークには、畳み込み層、活性化関数、プーリング層、全結合層、ドロップアウト層など、いくつかの重要な構成要素があります。CNNをより深く理解するために、各構成要素を分解して、その全体像を見てみましょう。
畳み込み層
これらはCNNの核となる構成要素で、計算の大部分がここでおこなわれます。畳み込み層は、画像のエッジなど、入力データの局所的なパターンを検出する役割を担っています。これは、特徴量マップを生成するために入力データ上をスライドするフィルタ(またはカーネル)を使用することで実現できます。
畳み込み層は、畳み込みニューラルネットワークのいくつかの畳み込みユニットを含む隠れ層であり、特徴量の抽出に使用されます。
from tensorflow.keras.layers import Conv1D
model = Sequential()
model.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(window_size, X_train.shape[2])))
フィルタ/カーネル
フィルタ(またはカーネル)とは、学習可能な小さな正方行列(通常は3x3、5x5などのサイズ)のことで、入力データ上をスライドして局所的なパターンを検出します。
どのように機能するのか?
入力データを横切って移動し、フィルタの値とフィルタの現在の受容野内の入力値との間で要素ごとの乗算をおこない、その結果を合計することで動作します。この操作が畳み込みと呼ばれるものです。
訓練中、ネットワークはフィルタの最適値を学習します。初期の層では、フィルタは通常、エッジやテクスチャのような単純な特徴量を検出するように学習します。一方、より深い層では、フィルタは形状やオブジェクトのような、より複雑なパターンを検出することができます。
単純な3x3フィルタと5x5の入力画像を考えてください。フィルタは画像上をスライドし、畳み込み演算をおこない、特徴量マップを生成します。
ストライド
これも畳み込み層に見られる特徴です。ストライドは、フィルタが入力データ上を移動する際のステップサイズです。これは、畳み込み処理中の各ステップでフィルタがどれだけシフトするかを決定します。
どのように機能するのか?
ストライドが1の場合、フィルタは一度に1ユニットずつ移動し、その結果、非常に重なり合った詳細な特徴量マップが得られます。これにより、より大きな特徴量マップが出力されます。
ストライドが2以上の場合、フィルタはユニットをスキップし、その結果、出力される特徴量マップはより詳細でなくなるが、より小さくなります。これにより、出力の空間次元が縮小され、事実上、入力がダウンサンプリングされます。
例えば、3x3のフィルタと5x5の入力画像があり、ストライドが1の場合、フィルタは一度に1ピクセルずつ移動し、3x3の出力特徴量マップを生成します。ストライドが2の場合、フィルタは一度に2つのピクセルを移動し、2x2の出力特徴量マップを生成します。
パディング
パディングは、入力データの境界の周りに余分なピクセル(通常はゼロ)を追加することです。これにより、フィルタが適切にフィットし、出力される特徴量マップの空間的な次元が制御されます。
パッドの種類
Kerasよると、パディングには3つのタイプがあります(大文字と小文字を区別する)。
- valid:パディングは適用されない
- same:strides=1のとき、出力サイズが入力サイズと一致するように入力をパッドする
- causal:時間ステップᵆでの出力が将来の入力に依存しないことを保証するために、時間データに使用される
パディングは、入力データの空間的な次元を保持するのに役立ちます。パディングをおこなわないと、畳み込み層ごとに出力特徴量マップが縮小し、重要なエッジ情報が失われる可能性があります。
パディングを追加することで、ネットワークはエッジ特徴量を効率的に学習し、入力の空間分解能を維持することができます。
3x3のフィルタと5x5の入力画像を考えます。有効なパディング(パディングなし)の場合、出力特徴量マップは3x3になります。同じパディングで、入力の周囲にゼロの境界を追加して7x7にすることもできます。出力特徴量マップは、入力次元を保持したまま5x5となります。
以下はPythonによる畳み込み層のコードです。
from tensorflow.keras.models import Sequential from tensorflow.keras.layers import Conv1D model = Sequential() model.add(Conv1D(filters=64, kernel_size=3, activation='relu', strides=2, padding='causal', input_shape=(window_size, X_train.shape[2]) ) )
活性化関数
ニューラルネットワークの謎を解くの記事で説明したように、活性化関数は入力を受けて出力を処理する数学的関数です。
活性化関数は、モデルに非線形性を導入するために要素ごとに適用されます。CNNでよく使われる活性化関数には、ReLU (Rectified Linear Unit)、Sigmoid、TanHなどがあります。
プーリング層
デサンプル層とも呼ばれるこれらの層は、最も重要な情報を保持しながら、入力データの幅と高さの空間次元を縮小する役割を担っているため、CNNにとって不可欠な部分です。
どのように機能するのか?
まず、入力データを重複する領域またはウィンドウに分割し、次に各ウィンドウに最大プーリングや平均プーリングのような集計関数を適用して単一の値を得ます。
最大プーリングは、フィルタ領域内の値の集合から最大値を取ります。データの空間的な次元を小さくすることで、計算負荷とパラメータの数を減らすことができます。
Python
from tensorflow.keras.layers import Conv1D, MaxPooling1D model = Sequential() model.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(window_size, X_train.shape[2]))) model.add(MaxPooling1D(pool_size=2))
平均プーリングは、フィルタ領域内の値の集合から平均値を取ります。最大プーリングよりも使用頻度は低くなります。
Python
from tensorflow.keras.layers import Conv1D, AveragePooling1D model = Sequential() model.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(window_size, X_train.shape[2]))) model.add(AveragePooling1D(pool_size=2))
なぜ1次元畳み込み層を使うのか?
CNNにはConv1D層、Conv2D層、Conv3D層があります。1次元畳み込み層は1次元データ用に設計されているため、この種の問題に適しており、逐次データや時系列データに適しています。Conv2DやConv3Dのような他の畳み込み層は、この種の問題には複雑すぎます。
全結合層
全結合層のニューロンは、前の層のすべての活性化に接続しています。これらの層は通常、畳み込み層とプーリング層によって抽出された特徴量に基づいて分類または回帰を実行するために、ネットワークの終盤で使用されます。
from tensorflow.keras.layers import Conv1D, MaxPooling1D, Flatten, Dense, Dropout
model = Sequential()
model.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(window_size, X_train.shape[2])))
model.add(MaxPooling1D(pool_size=2))
model.add(Flatten())
model.add(Dense(100, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(units=len(np.unique(y)), activation='sigmoid')) # For binary classification (e.g., buy/sell signal)
model.summary()
平坦化層は、1次元プールされた特徴量マップを1次元ベクトルに変換し、全結合層(密な層)に供給できるようにします。
蜜な層(Dense)は、畳み込み層とプーリング層によって抽出された特徴量に基づいて最終的な決定を下すために使用される全結合層です。密な層は基本的に、従来の人工ニューラルネットワーク(ANN)の中核的な構成要素です。
ドロップアウト層
ドロップアウト層はマスクの役割を果たし、他のすべてのニューロンの機能を維持したまま、一部のニューロンの後続層への寄与を排除します。ドロップアウト層を入力ベクトルに適用すると、その特徴の一部が除去されるが、隠れ層に適用すると、隠れニューロンの一部が除去されます。
学習データの過剰適合を避けるため、ドロップアウト層はCNNの学習において非常に重要です。もしそれらがない場合、最初の訓練サンプルセットは学習に過度に大きな影響を与えます。その結果、後のサンプルやバッチでしか見られない形質は学習されないことになります。
from tensorflow.keras.layers import Conv1D, MaxPooling1D, Flatten, Dense, Dropout
model = Sequential()
model.add(Conv1D(filters=64, kernel_size=3, activation='relu', input_shape=(window_size, X_train.shape[2])))
model.add(MaxPooling1D(pool_size=2))
model.add(Flatten())
model.add(Dense(100, activation='relu'))
model.add(Dropout(0.5))
model.add(Dense(units=len(np.unique(y)), activation='sigmoid')) # For binary classification (e.g., buy/sell signal)
model.summary()
なぜ畳み込みニューラルネットワーク(CNN)を金融分析や取引に使うのか?
CNNは画像やビデオの処理を目的として設計されているため、画像やビデオの処理アプリケーションで広く使用されています。上記の説明を見ていただければ、私が画像の分類などをおこなう際にCNNを使うことに言及していることにお気づきいただけるかもしれません。
金融分析のような表データに畳み込みニューラルネットワーク(CNN)を使用することは、順伝播型ニューラルネットワーク(FFNN: Feed Forward Neural Network)、回帰型ニューラルネットワーク(RNN: Recurrent Neural Network)、長・短期記憶(LSTM: Long Short-Term Memory)、ゲート付き回帰型ユニット(GRU: Gated Recurrent Unit)のような他のニューラルネットワークタイプを使用することに比べて、型破りに見えるかもしれません。しかし、この文脈でCNNを採用するには、いくつかの理由と潜在的な利点があります。
01:CNNは、データから局所的なパターンを自動的に抽出することに優れている
03:ノイズや冗長な特徴に強い
04:CNNは多変量時系列をうまく扱える
取引アプリケーションでCNNを使う正当な理由がわかったので、CNNを作り、訓練してみましょう。次に、Meta Trader 5のエキスパートアドバイザー(EA)でCNNを使用する方法を見ていきます。
Pythonで畳み込みニューラルネットワーク(CNN)を作る
これにはいくつかのステップがあります。
- データの収集
- CNNモデル用のデータ準備
- CNNモデルの訓練
- CNNモデルのONNX形式への保存
01:データの収集
前回の記事で使用した時系列予測のために作成したデータを使用します。
畳み込みニューラルネットワーク(CNN)が高次元データ内のパターンを検出するのに適していることがわかったので、モデルを複雑にすることなく、CNNモデルが検出できるパターンをたくさん持っていると思われる特徴量をいくつか選ぶことができます。
Pythonコード
open_price = df['TARGET_OPEN'] close_price = df['TARGET_CLOSE'] # making the target variable target_var = [] for i in range(len(open_price)): if close_price[i] > open_price[i]: # if the price closed above where it opened target_var.append(1) # bullish signal else: target_var.append(0) # bearish signal new_df = pd.DataFrame({ 'OPEN': df['OPEN'], 'HIGH': df['HIGH'], 'LOW': df['LOW'], 'CLOSE': df['CLOSE'], 'TARGET_VAR': target_var }) print(new_df.shape)
TARGET_OPENとTARGET_CLOSE(それぞれ始値と終値)に基づいて目標変数を準備した直後に、1バー先まで収集します。OPEN、HIGH、LOWの4つの独立変数と、TARGET_VARという1つの従属変数のみを持つ、new_dfというミニデータセットバージョンを作成しました。
02:CNNモデル用のデータ準備
まず、入力データを整形し、ウィンドウに整列させるという前処理をしなければなりません。CNNで表形式のデータを扱う場合、これは非常に重要です。
取引データは逐次的なものであるため、多くの場合、一時点ではなく、一連の時間ステップにわたってパターンが現れます。データのオーバーラップウィンドウを作ることで、時間的な依存関係をとらえ、CNNモデルにコンテキストを提供することができます。
また、CNNは入力データが特定の形をしていることを期待します。1次元畳み込み層の場合、入力形状は通常、(ウィンドウの数、ウィンドウのサイズ、特徴量の数)が必要です。 この形状は、前回の記事で紹介した回帰型ニューラルネットワーク(RNN)を使った時系列分析で使うものと似ています。これからおこなう前処理は、データがこの形式であることを保証し、CNNモデルの入力に適したものにします。
# Example data preprocessing function def preprocess_data(df, window_size): X, y = [], [] for i in range(len(df) - window_size): X.append(df.iloc[i:i+window_size, :-1].values) y.append(df.iloc[i+window_size, -1]) return np.array(X), np.array(y) window_size = 10 X, y = preprocess_data(new_df, window_size) print(f"x_shape = {X.shape}\ny_shape = {y.shape}")
出力
x_shape = (990, 10, 4) y_shape = (990,)
私たちのデータは1日単位で収集されているので、10というウィンドウサイズは、10日以内のパターンを理解するためにCNNモデルを訓練することを示しています。
次に、データを訓練用サンプルとテスト用サンプルに分ける必要があります。
# Split data into training and testing sets X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False) # Standardize the data scaler = StandardScaler() X_train = scaler.fit_transform(X_train.reshape(-1, X_train.shape[-1])).reshape(X_train.shape) X_test = scaler.transform(X_test.reshape(-1, X_test.shape[-1])).reshape(X_test.shape) print(f"x_train\n{X_train.shape}\nx_test\n{X_test.shape}\n\ny_train {y_train.shape} y_test {y_test.shape}")
出力
x_train (792, 10, 4) x_test (198, 10, 4) y_train (792,) y_test (198,)
最後に、この分類問題タスクの目標変数をワンホットエンコードしなければなりません。
from tensorflow.keras.utils import to_categorical
y_train_encoded = to_categorical(y_train)
y_test_encoded = to_categorical(y_test)
print(f"One hot encoded\n\ny_train {y_train_encoded.shape}\ny_test {y_test_encoded.shape}")
出力
One hot encoded y_train (792, 2) y_test (198, 2)
03:CNNモデルの訓練
ほとんどの仕事はここでおこなわれます。
# Defining the CNN model model = Sequential() model.add(Conv1D(filters=64, kernel_size=3, activation='relu', strides=2, padding='causal', input_shape=(window_size, X_train.shape[2]) ) ) model.add(MaxPooling1D(pool_size=2)) model.add(Flatten()) model.add(Dense(100, activation='relu')) model.add(Dropout(0.5)) model.add(Dense(units=len(np.unique(y)), activation='softmax')) # For binary classification (buy/sell signal) model.summary() # Compiling the model optimizer = Adam(learning_rate=0.001) model.compile(optimizer=optimizer, loss='categorical_crossentropy', metrics=['accuracy']) # Training the model early_stopping = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True) history = model.fit(X_train, y_train_encoded, epochs=100, batch_size=16, validation_split=0.2, callbacks=[early_stopping]) plt.figure(figsize=(7.5, 6)) plt.plot(history.history['loss'], label='Training Loss') plt.plot(history.history['val_loss'], label='Validation Loss') plt.xlabel('Epochs') plt.ylabel('Loss') plt.title('Training Loss Curve') plt.legend() plt.savefig("training loss cuver-cnn-clf.png") plt.show()
出力
Model: "sequential_2" ┏━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓ ┃ Layer (type) ┃ Output Shape ┃ Param # ┃ ┡━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩ │ conv1d_2 (Conv1D) │ (None, 5, 64) │ 832 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ max_pooling1d_2 (MaxPooling1D) │ (None, 2, 64) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ flatten_2 (Flatten) │ (None, 128) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense_4 (Dense) │ (None, 100) │ 12,900 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dropout_2 (Dropout) │ (None, 100) │ 0 │ ├─────────────────────────────────┼────────────────────────┼───────────────┤ │ dense_5 (Dense) │ (None, 2) │ 202 │ └─────────────────────────────────┴────────────────────────┴───────────────┘
訓練は34番目のエポックで停止しました。
40/40 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - accuracy: 0.5105 - loss: 0.6875 - val_accuracy: 0.4843 - val_loss: 0.6955 Epoch 32/100 40/40 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - accuracy: 0.5099 - loss: 0.6888 - val_accuracy: 0.5283 - val_loss: 0.6933 Epoch 33/100 40/40 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - accuracy: 0.4636 - loss: 0.6933 - val_accuracy: 0.5283 - val_loss: 0.6926 Epoch 34/100 40/40 ━━━━━━━━━━━━━━━━━━━━ 0s 3ms/step - accuracy: 0.5070 - loss: 0.6876 - val_accuracy: 0.5346 - val_loss: 0.6963
このモデルは、サンプル外予測で約57%の精度を示しました。
y_pred = model.predict(X_test) classes_in_y = np.unique(y) y_pred_binary = classes_in_y[np.argmax(y_pred, axis=1)] # Confusion Matrix cm = confusion_matrix(y_test, y_pred_binary) sns.heatmap(cm, annot=True, fmt='d', cmap='Blues') plt.xlabel("Predicted Label") plt.ylabel("True Label") plt.title("Confusion Matrix") plt.savefig("confusion-matrix CNN") # Display the heatmap print("Classification Report\n", classification_report(y_test, y_pred_binary))
出力
7/7 ━━━━━━━━━━━━━━━━━━━━ 0s 11ms/step Classification Report precision recall f1-score support 0 0.53 0.24 0.33 88 1 0.58 0.83 0.68 110 accuracy 0.57 198 macro avg 0.55 0.53 0.50 198 weighted avg 0.55 0.57 0.52 198
私たちのCNNモデルはEAとしては十分です。しかし、EAのコーディングを始める前に、訓練したCNNモデルをONNX形式で保存しておきましょう。
04:CNNモデルをONNX形式に保存する
CNNモデルを.onnx形式で保存し、スケーリング技術のパラメータをバイナリファイルで保存します。
import tf2onnx onnx_file_name = "cnn.EURUSD.D1.onnx" spec = (tf.TensorSpec((None, window_size, X_train.shape[2]), tf.float16, name="input"),) model.output_names = ['outputs'] onnx_model, _ = tf2onnx.convert.from_keras(model, input_signature=spec, opset=13) # Save the ONNX model to a file with open(onnx_file_name, "wb") as f: f.write(onnx_model.SerializeToString()) # Save the mean and scale parameters to binary files scaler.mean_.tofile(f"{onnx_file_name.replace('.onnx','')}.standard_scaler_mean.bin") scaler.scale_.tofile(f"{onnx_file_name.replace('.onnx','')}.standard_scaler_scale.bin")
畳み込みニューラルネットワーク(CNN)ベースの取引ロボットの作成
EAの内部では、最初にONNX形式のモデルと標準スケーラーのバイナリファイルをリソースとしてインクルードする必要があります。
MQL5 | ConvNet EA.mq5
#resource "\\Files\\cnn.EURUSD.D1.onnx" as uchar onnx_model[] #resource "\\Files\\cnn.EURUSD.D1.standard_scaler_scale.bin" as double scaler_stddev[] #resource "\\Files\\cnn.EURUSD.D1.standard_scaler_mean.bin" as double scaler_mean[]
スケーラーとonnxモデルの両方を初期化します。
#include <MALE5\Convolutioal Neural Networks(CNNs)\Convnet.mqh> #include <MALE5\preprocessing.mqh> CConvNet cnn; StandardizationScaler scaler; //+------------------------------------------------------------------+ //| | //+------------------------------------------------------------------+ input group "cnn"; input uint cnn_data_window = 10; //this value must be the same as the one used during training in a python script vector classes_in_y = {0,1}; //we have to assign the classes manually | it is essential that their order is preserved as they can be seen in python code, HINT: They are usually in ascending order //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- if (!cnn.Init(onnx_model)) //Initialize the ONNX model return INIT_FAILED; //--- Initializing the scaler with values loaded from binary files scaler = new StandardizationScaler(scaler_mean, scaler_stddev); //load the scaler return(INIT_SUCCEEDED); }
モデルを稼働させるにはこれで十分です。訓練時の独立変数の使い方と同じように、データを抽出する関数を作ってみましょう。時間枠が保存されなければならないウィンドウサイズである、直前のクローズバーから10本前のバーまでの4つの変数OHLC値を使用しました(日足時間枠)。
input group "cnn"; input uint cnn_data_window = 10; //this value must be the same as the one used during training in a python script input ENUM_TIMEFRAMES timeframe = PERIOD_D1; input int magic_number = 1945; input int slippage = 50;
matrix GetXVars(int bars, int start_bar=1) { vector open(bars), high(bars), low(bars), close(bars); //--- Getting OHLC values open.CopyRates(Symbol(), timeframe, COPY_RATES_OPEN, start_bar, bars); high.CopyRates(Symbol(), timeframe, COPY_RATES_HIGH, start_bar, bars); low.CopyRates(Symbol(), timeframe, COPY_RATES_LOW, start_bar, bars); close.CopyRates(Symbol(), timeframe, COPY_RATES_CLOSE, start_bar, bars); //--- matrix data(bars, 4); //we have 10 inputs from cnn | this value is fixed //--- adding the features into a data matrix data.Col(open, 0); data.Col(high, 1); data.Col(low, 2); data.Col(close, 3); return data; }
独立変数を収集する関数ができたので、取引戦略を確定できます。
void OnTick() { //--- if (NewBar()) //Trade at the opening of a new candle { matrix input_data_matrix = GetXVars(cnn_data_window); //get data for the past 10 days(default) input_data_matrix = scaler.transform(input_data_matrix); //applying StandardSCaler to the input data int signal = cnn.predict_bin(input_data_matrix, classes_in_y); //getting trade signal from the RNN model Comment("Signal==",signal); //--- MqlTick ticks; SymbolInfoTick(Symbol(), ticks); if (signal==1) //if the signal is bullish { if (!PosExists(POSITION_TYPE_BUY)) //There are no buy positions { if (!m_trade.Buy(lotsize, Symbol(), ticks.ask, 0, 0)) //Open a buy trade printf("Failed to open a buy position err=%d",GetLastError()); ClosePosition(POSITION_TYPE_SELL); //close opposite trade } } else if (signal==0) //Bearish signal { if (!PosExists(POSITION_TYPE_SELL)) //There are no Sell positions if (!m_trade.Sell(lotsize, Symbol(), ticks.bid, 0, 0)) //open a sell trade printf("Failed to open a sell position err=%d",GetLastError()); ClosePosition(POSITION_TYPE_BUY); } else //There was an error return; } }
戦略は単純です。特定のシグナル、例えば買いシグナルを受信したら、ストップロスや利益確定値を設定せずに買い取引を開始し、その後反対側のシグナルを決済し、売りシグナルの場合はその逆となります。
最後に、この戦略をEURUSDという訓練済みの銘柄で10年間テストしてみました。2014.01.01から2024.05.27まで4時間足チャートで各バーの始値を表示します。
ストラテジーテスターの結果は傑出していました。
EAは全体の58%の確率で正確な予測をおこない、その結果、CNNベースのEAは503ドルの純利益を上げました。
結論
畳み込みニューラルネットワーク(CNN)は、本来画像や映像の処理に特化して設計されたにもかかわらず、為替データのような表形式のデータに対しても効果的に採用されています。CNNはパターンを検出し、それを基に外国為替市場での予測が可能です。
ストラテジーテスターのレポートが示すように、CNNベースのEAは正確な予測をおこないました。CNNモデルが4つの独立変数(OHLC)のみを入力としていることを考慮すると、線形回帰、サポートベクターマシン、ナイーブベイズなどの従来の表データ向けモデルでは、この精度の予測は困難であったと考えられます。私の経験から言えば、少数の変数しかない場合に、これほど優れた性能を発揮するモデルは多くはありません。
ご精読ありがとうございました。
機械学習モデルの開発を追跡し、本連載で議論されている多くのことは、このレポに掲載されています。
添付ファイルの表
ファイル名 | ファイルタイプ | 説明と使用法 |
---|---|---|
ConvNet EA.mq5 | EA | ONNX形式でCNNモデルをロードし、MetaTrader 5で最終的な取引戦略をテストするための取引ロボット |
cnn.EURUSD.D1.onnx | ONNX | ONNX形式のCNNモデル |
cnn.EURUSD.D1.standard_scaler_mean.bin cnn.EURUSD.D1.standard_scaler_scale.bin | バイナリファイル | 標準化スケーラー用バイナリファイル |
preprocessing.mqh | インクルードファイル | 標準化スケーラーで構成されるライブラリ |
ConvNet.mqh | インクルードファイル | CNNモデルをONNX形式で読み込み、配置するためのライブラリ |
cnn-for-trading-applications-tutorial.ipynb | Pythonスクリプト/Jupyterノートブック | この記事で取り上げたすべてのpythonコードで構成される |
情報源と参考文献
- Convolutional Neural Network-based a novel Deep Trend Following Strategy for Stock Market Trading (https://ceur-ws.org/Vol-3052/paper2.pdf)
- What are Convolutional Neural Networks (CNNs)? (https://youtu.be/QzY57FaENXg)
- Converting tabular data into images for deep learning with convolutional neural networks (https://www.nature.com/articles/s41598-021-90923-y)
- Image kernels (https://setosa.io/ev/image-kernels/)
- Pooling Methods in Deep Neural Networks, a Review(https://arxiv.org/pdf/2009.07485)
MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/15259
- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索