English Русский 中文 Español Deutsch Português
preview
PythonとMetaTrader5 Pythonパッケージを使用した深層学習による予測と注文とONNXモデルファイル

PythonとMetaTrader5 Pythonパッケージを使用した深層学習による予測と注文とONNXモデルファイル

MetaTrader 5トレーディングシステム | 29 4月 2024, 11:09
986 0
Javier Santiago Gaston De Iriarte Cabrera
Javier Santiago Gaston De Iriarte Cabrera

はじめに

深層学習は、人間の脳の構造と機能にヒントを得た人工ニューラルネットワークに焦点を当てた機械学習のサブ分野です。これは、明示的なプログラミングなしに、データからパターンや表現を学習することによって、タスクを実行するモデルを訓練することを含みます。深層学習は、階層的な特徴や表現を自動的に学習することができるため、画像認識や音声認識、自然言語処理など様々な領域で効果を発揮し、大きな注目を集めています。

深層学習の主要概念

  • ニューラルネットワーク:深層学習の基本単位で、相互に接続されたノードまたはニューロンで構成され、層に編成されています。
  • ディープニューラルネットワーク(DNN):複数の層を持つニューラルネットワークは、複雑なパターンを学習することができます。
  • 訓練:ラベル付けされたデータを用いてモデルのパラメータを調整し、予測結果と実際の結果の差を最小化するプロセス。
  • 活性化関数:ニューロンの出力に関数を適用して非線形性を導入し、モデルがより複雑な関係を学習できるようにします。
  • 誤差逆伝播法:予測誤差に基づいてモデルの重みを更新する最適化アルゴリズム。

Python:Pythonは、読みやすさと使いやすさで知られる高水準の汎用プログラミング言語です。Pythonは、Web開発、データサイエンス、人工知能など、さまざまなアプリケーションに適したライブラリやフレームワークの膨大なエコシステムを備えています。

Pythonの主な特徴は、以下の通りです。

  • 読みやすさ:Pythonの構文は読みやすく、すっきりしたデザインになっているため、開発者は少ないコード行数で簡単に概念を表現できます。
  • 豊富なライブラリ:Pythonには、データ操作のためのNumPyやpandas、深層学習のためのTensorFlowやPyTorch、Web開発のためのDjangoやFlaskなど、多様なアプリケーションのための豊富なライブラリやフレームワークがあります。
  • コミュニティサポート:Pythonには大規模で活発な開発者コミュニティがあり、継続的な改良に貢献し、学習のための多くのリソースが利用可能です。

深層学習におけるPythonの使用:Pythonは、その豊富なライブラリとフレームワークにより、深層学習に人気のある言語です。深層学習にPythonを使用するための2つの主要なライブラリは、TensorFlowとPyTorchです。これらのライブラリは、ニューラルネットワークの構築と訓練のための高いレベルの抽象化を提供し、初心者にも経験豊富な実務者にも利用しやすくなっています。

要約すると、深層学習は機械学習という広い分野の中で強力なアプローチであり、Pythonは深層学習モデルとソリューションを実装するための優れたプログラミング言語として機能します。Pythonと深層学習の組み合わせは、様々な分野での進歩をもたらし、複雑なタスクをより身近で自動化できるようになりました。


PythonとMQL5パッケージでの注文:PythonとMQL5パッケージを組み合わせて取引注文を処理することに興味があるようです。MQL5は、MetaTrader 5 (MT5)プラットフォームでのアルゴリズム取引用に設計された専用言語です。ここでは、PythonとMQL5を統合して取引をおこなう方法の一般的な概要を説明します。

  • 深層学習のためのPythonスクリプト:深層学習ライブラリ(TensorFlow、PyTorchなど)を使用してPythonスクリプトを開発し、特定の取引戦略のモデルを作成訓練します。このスクリプトは、深層学習モデルに基づく分析と意思決定を処理します。

  • PythonとMQL5間の通信:PythonスクリプトとMetaTrader 5プラットフォーム間の通信の橋渡しをします。これは、ソケット、RESTAPI、その他の通信プロトコルなど、さまざまな方法を用いておこなうことができます。目標は、PythonスクリプトがMetaTrader端末に取引シグナルまたは注文を送信できるようにすることです。

  • MQL5における注文の実行:MQL5スクリプトまたはEAで、Pythonスクリプトからシグナルを受信し、MetaTrader 5プラットフォームで対応する買い/売り注文を実行するロジックを実装します。これには、MQL5言語が提供する取引関数を利用することが含まれます。


ONNX

ONNX (Open Neural Network Exchange)は、様々なフレームワーク間での人工知能(AI)モデルの相互運用性を促進するために設計されたオープンソースの形式です。マイクロソフトとフェイスブックによって開発され、サポートされているONNXは、ユーザーがあるフレームワークを使用してモデルを訓練し、別のフレームワークを使用してそれをデプロイすることを可能にします。

ONNXの主な利点は、TensorFlowやPyTorchなどの異なる深層学習フレームワーク間の仲介形式として機能する能力です。この互換性により、機械学習モデルをさまざまなアプリケーション、環境、プラットフォームに統合するプロセスが簡素化されます。

MQL5 (MetaQuotes Language 5)の文脈では、ONNXモデルの統合には、学習済みの機械学習モデルをONNX形式に変換することが含まれます。ONNX形式に変換されたモデルは、MQL5スクリプトまたはEAに読み込むことができるので、MetaTrader 5プラットフォーム内のアルゴリズム取引戦略に高度な機械学習機能を利用することができます。


今後の内容の簡単な紹介

次回の記事では、自動売買に応用された深層学習の魅力的な世界を掘り下げていきます。焦点となるのは、高度な深層学習技術を活用した自動売買のためのプログラムです。平均絶対誤差(MAE)、平均二乗誤差(MSE)、R二乗(R2)などの主要な測定基準を使用して、モデルのパフォーマンスをテストする複雑さを探求します。この調査は、アルゴリズム取引の文脈における深層学習モデルの有効性に関する洞察を提供し、その予測精度と全体的な頑健性に光を当てることを目的としています。一緒に、深層学習、自動売買、そして包括的なパフォーマンステストの交差点を解き明かす旅に出ましょう。


さらに、Pythonスクリプト(.py)を実行ファイルに変換するプロセスを探求し、包括的でユーザーフレンドリーなパッケージを確保します。このステップバイステップのガイドでは、プロセス全体を完全に理解するために、手を抜かずに詳細な洞察を提供します。この記事を読み終える頃には、自動売買における深層学習の実装について深く理解するだけでなく、ソリューションを便利な実行可能な形式にまとめるための実践的な知識も身についているでしょう。コーディングから完全に機能する実行可能なプログラムまでシームレスにナビゲートする詳細なウォークスルーにご期待ください。


記事の締めくくりとして、ONNX形式の出力を生成するスクリプトを作成します。このスクリプトは、EAを使用してONNXモデルをMetaTrader 5 (MT5)に組み込む際に役立ちます。このプロセスにより、MT5プラットフォームへの機械学習機能の適応性と統合が強化され、より洗練された効率的なアルゴリズム取引戦略の開発が容易になります。


コーディングを始める前に

私たちが達成しようとしているのは、2段階のプロセスを経るPythonボットの開発です。まず、利用可能なデータの深層学習分析をおこない、その後、取引注文を実行します。MT5では大量のティックデータをダウンロードできるため、戦略には、このデータを取得し、価格情報に変換することが含まれます。この変換方法では、ティック間の平均値を取ることになり、ボット内でのさらなる分析と意思決定のために、より管理しやすい市場価格の表現を作成できるようになります。


ただし、続行する前に、Pythonを利用する必要があります。便利なPythonのセットアップには、Anacondaをダウンロードしてインストールすることをお勧めします。さらに、Visual Studio Codeをインストールすることで、スクリプティングのためのユーザーフレンドリーな環境が提供されます。


Anaconda

VSC

AnacondaとVisual Studio Codeをインストールしたら、次のステップはVisual Studio Code内でpipを使用していくつかのパッケージをインストールすることです。

Visual Studio Codeで統合端末を開き、以下のコマンドを実行します(Conda/Anacondaを使用している場合は、Anaconda Promptでこれらのコマンドを実行します)。

pip install [package1] [package2] ...

[package1]、[package2]などは、プロジェクトに必要なPythonパッケージ名に置き換えてください。これにより、Pythonボットの開発を進めるために必要なツールやライブラリが環境に備わっていることが保証されます。


パッケージ

MetaTrader 5、TensorFlow、Anacondaに付属するその他のライブラリを含む、Python環境用の特定のパッケージをインストールする必要があります。これらのライブラリのインストール方法についての一般的なガイドは、以下を参照してください。

  1. MetaTrader 5:MetaTrader 5 (MT5)は取引プラットフォームです。残念ながら、2022年1月に私が最後に知識を更新した時点では、MetaTrader 5の公式ディストリビューションでは直接的なPython APIはありません。ただし、サードパーティのライブラリやラッパーが存在する場合もあります。最新情報については、MetaTrader 5の公式ドキュメントまたは関連コミュニティフォーラムをご確認ください。   

    pip install MetaTrader5
  2. TensorFlow:TensorFlowは人気のある機械学習ライブラリです。端末かコマンドプロンプトで以下のpipコマンドを使用してインストールできます。

    pip install tensorflow


コーディングを始める

必要なライブラリのインストールに成功したら、次のステップはPythonコードを書き始めることです。そのためには、インストールしたライブラリをインポートする必要があります。Pythonでは、ライブラリの機能をコードに取り込むためにimport文を使用します。
import MetaTrader5 as mt5
from MetaTrader5 import *
import numpy as np
from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.regularizers import l2
from sklearn.model_selection import KFold


from MetaTrader5 import *

この行は、MetaTrader 5ライブラリからすべての関数とクラスをインポートします。「*」(ワイルドカード)を使用するとすべてがインポートされますが、名前空間が衝突する可能性があるため、この方法は一般的に推奨されません。

import numpy as np

この行はNumPyライブラリをインポートし、それにnpというエイリアスを与えます。NumPyはPythonの数値演算に広く使用されています。

from sklearn.model_selection import train_test_split, cross_val_score
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import mean_squared_error, mean_absolute_error, r2_score

これらの行はscikit-learnライブラリから特定の関数/クラスをインポートします。データ前処理、モデル評価、モデル選択のためのユーティリティが含まれています。

from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
from tensorflow.keras.regularizers import l2

これらの行は、深層学習によく使用されるTensorFlowライブラリからコンポーネントをインポートします。逐次モデル、高密度層、L2正則化が導入されています。

from sklearn.model_selection import KFold

この行はscikit-learnからKFoldクラスをインポートします。

要約すると、スクリプトは、金融データ用にMetaTrader5ライブラリ、数値演算用にNumPy、機械学習ユーティリティ用にscikit-learn、深層学習用にTensorFlowを使用する準備をしています。金融データ分析のための環境を整え、金融予測のための機械学習モデルを構築しているようですね。適切なパッケージマネージャー(pipやcondaなど)を使用して、これらのライブラリがPython環境にインストールされていることを確認してください。


データのダウンロード

ティックをダウンロードするには、まずデータプロバイダー(mt5)に接続する必要があります。そこから必要なものをダウンロードできます。そのために、以下のものを使用します。
# You will need to update the values for path, login, pass, and server according to your specific case.
creds = {
    "path": "C:/Program Files/XXX MT5/terminal64.exe",
    "login": account,
    "pass": clave_secreta,
    "server": server_account,
    "timeout": 60000,
    "portable": False
}
# We launch the MT5 platform and connect to the server with our username and password.
if mt5.initialize(path=creds['path'],
                  login=creds['login'],
                  password=creds['pass'],
                  server=creds['server'],
                  timeout=creds['timeout'],
                  portable=creds['portable']):
    
    print("Plataform MT5 launched correctly")
else:
    print(f"There has been a problem with initialization: {mt5.last_error()}")

これが完了したら、関心のある銘柄のデータをティックの形でダウンロードします。

rates = rates.drop(index=rates.index)
rates = mt5.copy_ticks_from(symbol, utc_from, 1000000000, mt5.COPY_TICKS_ALL)

このコードでは、まず「rates」DataFrameの既存のデータをすべてクリアし、次にMetaTrader 5ライブラリのcopy_ticks_from関数を使用して、特定の銘柄と時間範囲のティックデータを取得します。

Pandas DataFrame(NumPyと一緒によく使用される)にデータを入れて、Pythonで操作しやすくするのが目的なので、Pandas DataFrameにデータを転送します。
rates_frame=pd.DataFrame()
# Empty DataFrame
rates_frame = rates_frame.drop(index=rates_frame.index)
rates_frame = pd.DataFrame(rates)

このコードでは、rates_frameという名前の空のPandas DataFrameを初期化し、その中の既存のデータをクリアし、rates変数のデータで満たします。

物事を単純化するために、データのbid値とask値を足して2で割ってみましょう。こうして平均値を得ますが、これが深層学習の入力となります。
rates_frame['time']=pd.to_datetime(rates_frame['time'], unit='s')
rates_frame['close']=(rates_frame['ask']+rates_frame['bid'])/2

このコードでは、time列を秒を単位とするdatetime形式に変換し、askとbidの平均値を計算し、その結果をrates_frame DataFrameのcloseという新しい列に代入します。

値動きの予測など、金融アプリケーションにおける深層学習の入力データの選択は様々な要因に左右され、万能のソリューションは存在しません。しかし、留意すべき点や一般的なガイドラインもあります。


生データ vs 派生機能(オシレーターと指標)

1.生データ

  • 長所
    • 仮定を追加することなく、利用可能なすべての情報を保持する
    • ニューラルネットワークが生の入力から直接パターンを学習できるようにする
  • 考慮事項
    • ノイズや無関係な情報が含まれている可能性がある
    • データの前処理がさらに必要になる場合がある

2.派生機能(オシレーターと指標)

  • 長所
    • 特徴エンジニアリングは、特定の市場ダイナミクスを捉えることができる
    • より構造化されたデータ表現を提供する可能性がある
  • 考慮事項
    • どのような特徴が関連するかについての仮定を導入する
    • 有効性が、選択した指標とそのパラメータに依存する


ベストプラクティスと考察

1. データの正規化

  • 訓練中の収束を良くするために、データを一定の範囲(例:0~1)にスケーリングします。

2. シーケンスの長さ

  • 時系列データの場合、シーケンスの長さは重要です。様々な長さを試して、関連するパターンの捕捉と計算効率の最適なバランスを見つけます。

3. 時間的側面

  • 時間依存性を捉えるために、ラグ値やスライディングウィンドウのような時間的側面を取り入れることを検討します。

4. 特徴の選択

  • さまざまな特徴のサブセットを試して、特定のタスクに最も有益なものを特定します。

5. モデルアーキテクチャ

  • 入力データの性質に基づいてニューラルネットワークのアーキテクチャを調整します。回帰型ニューラルネットワーク(RNN)や長・短期記憶ネットワーク(LSTM)は、シーケンシャルなデータに有効です。

6. 正規化

  • 特に高次元データを扱う場合は、正則化技術(ドロップアウトなど)を使用して過剰適合を防ぎます。

7. ハイパーパラメータの調整

  • 様々なハイパーパラメータ設定を試して、モデルに最適な設定を見つけます。

実際には、異なるアプローチを経験的に比較することが有益な場合が多いです。あるタスクは生データのシンプルさから恩恵を受けるかもしれないし、他のタスクはうまく作られた派生特徴からパフォーマンスを得るかもしれません。モデルが学習するのに十分な情報を提供することと、ノイズや無関係な詳細を避けることのバランスを取ることが重要です。さらに、市場力学が時間とともに変化する可能性があるため、選択したアプローチを定期的に再評価します。


データの移行

これでPandasのDataFrameにデータが入ったので、これを深層学習の入力として送信することができます。MQL5の深層学習に関する興味深い記事はすでにたくさんあるので、これ以上掘り下げることはしません。Pythonを使用した実践的な側面から説明しましょう。ただし、データを送信してTensorFlowが魔法の働きをする前に、予測のためにデータに適用する時間シフトの入力が必要です(シフトされた時間が、私たちが予測しようとする時間になる)。そのため、コードは次のようになっています。


深層学習、特に時系列予測では、入力変数と目標変数のシーケンスを作成するためにDataFrameをシフトすることが一般的です。時系列予測のための深層学習の文脈でシフトが使用される理由は以下の通りです。

  1. 時間的な依存関係:回帰型ニューラルネットワーク(RNN)や長・短期記憶ネットワーク(LSTM)などの深層学習モデルは、シーケンシャルデータの時間依存性を捉えることができます。DataFrameをシフトすることで、各入力シーケンスが過去のデータのセグメントに対応し、対応する目標シーケンスが未来のデータを表すシーケンスを作成することができます。

  2. 逐次学習:深層学習モデルは、順次データのパターンや依存関係を学習するのに有効です。DataFrameをシフトさせることで、入力配列と目標配列の時間的な整合性を確保し、モデルが過去の文脈から学習し、その文脈に基づいて予測をおこなうことができるようにします。

  3. 入出力ペアの訓練:シフトは、深層学習モデルの学習例を作成するのに役立ちます。シフトされたDataFrameの各行は、入力と出力のペアと考えることができます。ここで、入力は過去のオブザベーションのシーケンスであり、出力は将来予測される目標変数です。


number_of_rows= seconds
empty_rows = pd.DataFrame(np.nan, index=range(number_of_rows), columns=df.columns)
df = df._append(empty_rows, ignore_index=True)
df['target'] = df['close'].shift(-seconds)
print("df modified",df)
  • number_of_rows:秒数を表す変数
  • empty_rows:元のDataFrame (df)と同じ列を持つ、NaN値を持つ新しいDataFrameを作成する
  • df.append(empty_rows,ignore_index=True):連続インデックスを確保するためにインデックスを無視しながら、空の行を元のDataFrame (df)に追加する
  • df['target']=df['close'].shift(-seconds):指定した秒数の負の値だけシフトしたclose値を含む新しいtarget列を作成する(時系列データを予測モデリング用に準備するときによくおこなわれる)

あとは、TensorFlowの入力として使えるようにデータをきれいにするだけです。

# Drop NaN values
df=df.dropna()

その結果、DataFrame (df)が修正され、NaN値で満たされた行が追加され、タイムシフトされたclose値のための新しいtarget列が追加されます。


深層学習

TensorFlowとKerasを使用して、時系列予測のためのニューラルネットワークを構築し、訓練します。

# Split the data into features (X) and target variable (y)
X=[]
y=[]
X = df2[['close']]
y = df2['target']

# Split the data into training and testing sets
X_train=[]
X_test=[]
y_train=[]
y_test=[]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, shuffle=False)

# Standardize the features
X_train_scaled=[]
X_test_scaled=[]
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# Build a neural network model
model=None
model = Sequential()
model.add(Dense(128, activation='relu', input_shape=(X_train.shape[1],), kernel_regularizer=l2(k_reg)))
model.add(Dense(256, activation='relu', kernel_regularizer=l2(k_reg)))
model.add(Dense(128, activation='relu', kernel_regularizer=l2(k_reg)))
model.add(Dense(64, activation='relu', kernel_regularizer=l2(k_reg)))
model.add(Dense(1, activation='linear'))

# Compile the model[]
model.compile(optimizer='adam', loss='mean_squared_error')

# Train the model
model.fit(X_train_scaled, y_train, epochs=int(epoch), batch_size=256, validation_split=0.2, verbose=1)

# Use the model to predict the next 4 instances
X_predict=[]
X_predict_scaled=[]

predictions = pd.DataFrame()
predictions=[]
# Empty DataFrame
#predictions = predictions.drop(index=predictions.index)
X_predict = df2.tail(segundos)[['close']]
X_predict_scaled = scaler.transform(X_predict)
predictions = model.predict(X_predict_scaled)

# Print actual and predicted values for the next 
    n  instances
print("Actual Value for the Last Instances:")
print(df.tail(1)['close'].values)

print("\nPredicted Value for the Next Instances:")
print(predictions[:, 0])
predictions=pd.DataFrame(predictions)

将来の価値を予測するために、過去の金融データを使用してニューラルネットワークを準備し、訓練します。モデルの構築と訓練には、TensorFlowとKerasライブラリを使用します。そして、訓練したモデルに基づいて、次のインスタンスに対する予測が出力されます。

説明

  • モデルはシーケンシャルモデルとして初期化されます。

  • Dense層はニューラルネットワークの 全結合層を表します。パラメータには、ニューロン数(ユニット数)、活性化関数、入力形状(第1層にのみ適用可能)、カーネル正則化(この場合、k_regで指定された強度のL2正則化)が含まれます。

  • 「activation='relu'」は、隠れ層でよく使用される活性化関数であるRectified Linear Unit (ReLU)を意味します。

  • 最後の層には、線形活性化関数を持つニューロンが1つあり、回帰出力を示します。これが分類タスクであれば、シグモイドやソフトマックスのような別の活性化関数が使用されるでしょう。

このアーキテクチャは、回帰を目的とした複数の隠れ層を持つフィードフォワードニューラルネットワークです。特定のタスクとデータセットの特性に基づいて、パラメータと層を調整します。


予測

このモデルの近似性はどうでしょうか。

# Calculate and print mean squared error
mse = mean_squared_error(y_test, model.predict(X_test_scaled))
print(f"\nMean Squared Error: {mse}")

# Calculate and print mean absolute error
mae = mean_absolute_error(y_test, model.predict(X_test_scaled))
print(f"\nMean Absolute Error: {mae}")

# Calculate and print R2 Score
r2 = r2_score(y_test, model.predict(X_test_scaled))
print(f"\nR2 Score: {r2}")

提供されるコードは、訓練済み回帰モデルの3つの評価指標を計算し、表示します。

説明

  • 平均二乗誤差(MSE):予測値と実際の値の平均二乗差を測定します。MSEが低いほどモデルは優れています。

  • 平均絶対誤差(MAE):予測値と実際の値の差の平均絶対値を測定します。MSEと同様、値が小さいほどモデルのパフォーマンスは高くなります。

  • R2得点:決定係数としても知られ,独立変数から予測可能な従属変数の分散の比率を測定します。R2得点が1の場合、適合が完璧です。0の場合、モデルが目標変数の平均を予測するよりも良くないことが示唆されます。負の値はモデルのパフォーマンスが低いことを示します。

これらのメトリクスは、訓練済みモデルがテストセットでどの程度のパフォーマンスを発揮しているかについての洞察を提供します。

この文脈では、データ量(入力遅延)とエポック数を実験する必要があります。例えば、EURUSDでは900日分のデータと2時間分の1エポックを使用します(これについては後で詳しく説明する)。しかし、より少ないデータとより多くのエポック数でも良い結果を得ることができました。


注文

次に、スクリプトがデータを返すのにかかる時間を測定する必要があります。これによって、チャート上に私たちにとっての予測の開始点をマークすることができます(予測はある程度早く始まる:例えば私の場合、15~20分ほどかかる)。注文を開始するのは、その時間が経過した時点からとなります。さらに、このボットを広範囲に使用した結果、最も正確な予測はシフト全体の初めの四分の一であることに気づきました。精度を高めるために、チャートに指値と印をつけて、その特定の期間に注文を執行します。これはtime.now()を使用して簡単に実装できます。予測もX軸の目盛りも秒単位なので、その瞬間の時間をとらえて秒に変換することができます。これらのことを踏まえて、予測の開始位置をマークし、その最初のポイントに基づいて注文がトリガーされます。

これはMetaTrader 5 (MT5)を使用した典型的なPython注文です。関数open_trade_sell2は、MT5プラットフォームで売り注文を出すための一般的な構造を表しています。mt5.order_sendメソッドを利用して、注文を実行するための取引リクエストを送信します。パラメータには、取引アクション(「買い」または「売り」)、銘柄、ロットサイズ、ランダムな整数(おそらくマジックナンバー識別のため)、利食い(tp)、損切り(sl)、偏差が含まれます。

def open_trade_sell2(action, symbol, lot,random_integer, tp, sl, deviation):
        '''https://www.mql5.com/ja/docs/integration/python_metatrader5/mt5ordersend_py
        '''
        # prepare the buy request structure
        symbol_info = get_info(symbol)
        
        if action == 'buy':
            trade_type = mt5.ORDER_TYPE_BUY
            price = mt5.symbol_info_tick(symbol).ask
        elif action =='sell':
            trade_type = mt5.ORDER_TYPE_SELL
            price = mt5.symbol_info_tick(symbol).bid
        point = mt5.symbol_info(symbol).point
        print("el precio mt5 es:", price)

        buy_request = {
            "action": mt5.TRADE_ACTION_DEAL,
            "symbol": symbol,
            "volume": lot,
            "type": trade_type,
            "price": price,
            "sl":sl,
            "tp":tp,
            "deviation": deviation,
            "magic": random_integer,
            "comment": "python open",
            "type_time": mt5.ORDER_TIME_GTC, # good till cancelled
            "type_filling": mt5.ORDER_FILLING_IOC,
        }
        # send a trading request
        result = mt5.order_send(buy_request)        
        return result, buy_request

この関数は、MT5プラットフォームと連動して取引戦略を自動化するスクリプトの一部です。主なステップには、取引タイプの決定、現在のbidまたはask価格の検索、取引要求構造の準備、そして最後に取引要求の送信が含まれます。


注文の決済

def close_position(position,symbol):
    """This function closes the position it receives as an argument."""
   
    request = {
        'action': mt5.TRADE_ACTION_DEAL,
        'position': position.ticket,
        'magic': position.magic,
        'symbol': symbol,
        'volume': position.volume,
        'deviation': 50,
        'type': mt5.ORDER_TYPE_BUY if position.type == 1 else mt5.ORDER_TYPE_SELL,
        'type_filling': mt5.ORDER_FILLING_FOK,
        'type_time': mt5.ORDER_TIME_GTC,
        'comment': "mi primera orden desde Python"
    }
    return mt5.order_send(request)

# Now, we define a new function that serves to close ALL open positions.
def close_all_positions(symbol):
    """This function closes ALL open positions and handles potential errors."""
   
    positions = mt5.positions_get()
    for position in positions:
        if close_position(position,symbol).retcode == mt5.TRADE_RETCODE_DONE:
            print(f"Position {position.ticket} closed correctly.")
        else:
            print(f"An error occurred while closing the position.{position.ticket}: {mt5.last_error()}")

また、今回のために修正したEAを使用して注文をクローズすることもできます。この場合、.pyファイルはドキュメントを作成し、注文をクローズするまでの時間を分単位で書き込みます(これを使用する場合、mt5のFileフォルダにファイルを残すことを忘れないでください)。

#Specify the path for the file and open it in write mode
file_path = "C:/XXX/MetaQuotes/Terminal/XXX/MQL5/Files/python_"+symbol+"_file.txt"
try:
    with open(file_path, "w") as file:
        # Write file parameters
        file.write(str(the_value))
    print(f"File '{file_path}' created.")
except Exception as e:
    print(f"Error creating file: {e}")

そしてこれが、こちらのユーザーから入手したEAを修正したものです(Fileフォルダに正しいパスを追加する必要がある)。

//+------------------------------------------------------------------+
//|                                               Timer_modified.mq5 |
//|                                                                  |
//|                                                                  |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2021, Vladimir Karputov"
#property link      "https://www.mql5.com/ru/market/product/43516"
#property version   "1.000"

//--- display the window of input parameters when launching the script
#property script_show_inputs

//--- parameters for data reading
input string InpFileName="python_file.txt"; // file name
input string InpDirectoryName="Files"; // directory name
//---
#include <Trade\PositionInfo.mqh>
#include <Trade\Trade.mqh>
//#include <File.mqh>
//---
CPositionInfo  m_position;                   // object of CPositionInfo class
CTrade         m_trade;                      // object of CTrade class
//--- input parameters
input uchar    InpAfterHour   = 0; // After: Hour ... (max 255)
input uchar    InpAfterMinutes= 42; // After: Minutes ... (max 255)
input uchar    InpAfterSeconds= 59; // After: Seconds ... (max 255)
//---
int file_handles;
uchar value_uchar;
long     m_after  = 0;
bool         started=false;     // flag of counter relevance
string str1,str2,str3,str4;

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+

int OnInit()
  {
  str1="C:/XXX/MetaQuotes/Terminal/XXXX/MQL5/Files/python_";
  str3="_file.txt";
  str2=Symbol();
  str4=str1+str2+str3;

   // Open file to read
   string file_path = str4;
   file_handles = FileOpen(file_path, FILE_READ|FILE_TXT);
   
   if(file_handles != INVALID_HANDLE)
     {
      PrintFormat("File %s opened correctly", file_path);
      
      // Read uchar value of the file
      if (FileReadInteger(file_handles, INT_VALUE))
        {
         PrintFormat("Uchar value read from file: %u", value_uchar);
         m_after  = 0;
         m_after=value_uchar;
        }
      else
        {
         Print("Error when reading the uchar value from file");
        }

      // Close file after read
      FileClose(file_handles);
     }
   else
     {
      m_after  = 0;
      m_after=InpAfterHour*60*60+InpAfterMinutes*60+InpAfterSeconds;
      PrintFormat("Error when opening file %s, error code = %d", file_path, GetLastError());
     }
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   for(int i=PositionsTotal()-1; i>=0; i--) // returns the number of current positions
      if(m_position.SelectByIndex(i)) // selects the position by index for further access to its properties
        {
         if(TimeCurrent()-m_position.Time()>=m_after)
            m_trade.PositionClose(m_position.Ticket()); // close a position
        }
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//| called when a Trade event arrives                                |
//+------------------------------------------------------------------+
void OnTrade()
  {
   if(started) SimpleTradeProcessor();   
  }  
 void SimpleTradeProcessor()
  {
  str1="C:/Users/XXX/MetaQuotes/Terminal/XXX/MQL5/Files/python_";
  str3="_file.txt";
  str2=Symbol();
  str4=str1+str2+str3;
     // Open file to read it
   string file_path = str4;
   file_handles = FileOpen(file_path, FILE_READ|FILE_TXT);
   
   if(file_handles != INVALID_HANDLE)
     {
      PrintFormat("File %s is opened correctly", file_path);
      
      // Reads the uchar value from the file
      if (FileReadInteger(file_handles, INT_VALUE))
        {
         PrintFormat("value_uchar read form file: %u", value_uchar);
         m_after  = 0;
         m_after=value_uchar;
        }
      else
        {
         Print("Error while reading the value uchar from file");
        }

      // Closes the file after reading
      FileClose(file_handles);
     }
   else
     {
      m_after  = 0;
      m_after=InpAfterHour*60*60+InpAfterMinutes*60+InpAfterSeconds;
      PrintFormat("Error when opening the fileo %s, Code error = %d", file_path, GetLastError());
     }    
  }

注文のクローズについて、2つの異なる方法を紹介しました。Pythonでは、time.sleep(t)を使うだけです。tは注文が出されてからクローズされるまでの秒数です。しかし、この方法は待ち時間が発生し、他のスクリプト操作に使える時間を消費するため、あまり実用的ではありません。どの方法でクロージングオーダーを出すかは、皆さんの判断にお任せします。

例えば、売買注文を出してからクローズするまでの間のtime.sleep()の使用を減らすことで、より多くの注文を出すことができます。やり方ですが、マジックナンバーの値を組み込むことで、変更されたEAを利用することができ、指定されたマジックナンバーと銘柄の注文のみをクローズすることができます。こうすることで、スクリプトがスリープして一時停止する代わりに、アクティブなまま作業を続けることができます。


視覚化

効果的に視覚化するために、グラフにプロットしてトレンドを観察します。最も信頼できる予測の範囲に印をつけ、その範囲内の最大値と最小値を示し、最後にグラフを保存します。

plt.axvline(x=pt_division2, color='gray', linestyle='--', label='75 %')
plt.axvline(x=center, color='grey', linestyle='--', label='50 %')
plt.axvline(x=pt_division3, color='blue', linestyle='--', label='33 %')
plt.axvline(x=pt_division1, color='gray', linestyle='--', label='25 %')
plt.axvline(x=pt_division6, color='blue', linestyle='--', label='16 %')
plt.axvline(x=pt_division10, color='yellow', linestyle='--', label='10 %')
plt.axvline(x=pt_division14, color='blue', linestyle='--', label='7 %')
plt.axvline(x=pt_division20, color='yellow', linestyle='--', label='5 %')
plt.axvline(x=entry_point, color='orange', linestyle='--', label='entrada')
plt.axvline(x=value_25, color='orange', linestyle='--', label='salida 20%')
plt.axvline(x=maximal_index, color='red', linestyle='--', label='maximal') ##### ni idea de porqué no pinta correctamente la linea
plt.axvline(x=manimal_index, color='red', linestyle='--', label='minimal')# lo mismo aquí

plt.plot(dff5.iloc[:, 0], linestyle='-', label='Predicted')

plt.xlabel('Instances')
plt.ylabel('Prediction Price')
plt.legend()
plt.title(f'Predicted {symbol} y quedan en minutos: ' + str(MyParameter))
plt.savefig('Predicted_for_'+str(symbol)+'_quedan_'+str(MyParameter)+'_minutos_desde_'+str(formatted_now2)+'_.png')


スクリプトの機能のしくみ

さて、このスクリプトはどのように機能するのでしょうか。まず、ライブラリを読み込み、次に予測の現在の段階を追跡するために正確な瞬間を記録します。その後、MT5を初期化し、データをダウンロードして処理し、結果を提供します。この結果をもとにグラフを作成し、注文をクローズする具体的なタイミングなど、正確なタイミングで注文を執行します。さらに、注文のクローズする方法も柔軟に選択できます。

同じ通貨ペアでこのプロセスを繰り返したい場合は、単純なループで十分なので、プログラムを連続的に実行するのは簡単です。最適な入力はどうやって決めるのでしょうか。簡単なことです。R2が1に近く、MSEとMAEが0に近いモデルは、近似が良好であることを示します。ただし、過剰適合には注意が必要です。最適な入力値を特定したら、MSE、MAE、R2の計算にはかなりの時間がかかるため、MSE、MAE、R2は無視してもよいです。この文脈において、最も重要なのは結果を得るまでのスピードです。


実行ファイルの作成

通貨ペアから始めるとき、注文を出す前にまず知る必要があるのは、正確な予測ができているかどうかということです。Pythonは継続的に進化しており、ライブラリを更新する必要が出てくるかもしれないことを考えると、すべてをラップアップしておいて損はないでしょう。こうすることで、テストや実験のための統合されたパッケージができあがります。

そのためにTkinterを使い、auto-py-to-exeを使用して実行ファイルに変換します。こうすることで、入力データを決定する際に更なる問題に直面することはなく、注文の実行を担当する.pyファイルをより慎重に扱うことができます。

テスト用に実行ファイルを作成する方法を説明します。カスタマイズできるように注文実行用のものを残しておきます。

実行ファイルには、値を入力するためのグラフィカルインターフェイスを提供するTkinterを使用します。ファイルパスに「/」または「\」を使用することを忘れないでください。インターフェイスはモデルの精度値を取得し、グラフを表示します。

以下はGUI (gui_console)のコードです。

import tkinter as tk
from program_object import execute_program_with
from program_object_without import execute_program_without
import sys

class Aplication:
    def __init__(self, root):
        self.root = root
        self.root.title("DeepLearning Forecast")
        
        # labels and entries
        label1 = tk.Label(root, text="Input account mt5:")
        label1.pack(pady=5)

        self.value1_entry = tk.Entry(root)
        self.value1_entry.pack(pady=5)

        label2 = tk.Label(root, text="Input password:")
        label2.pack(pady=5)

        self.value2_entry = tk.Entry(root)
        self.value2_entry.pack(pady=5)

        label3 = tk.Label(root, text="Input server of mt5:")
        label3.pack(pady=5)

        self.value3_entry = tk.Entry(root)
        self.value3_entry.pack(pady=5)

        label4 = tk.Label(root, text="Input delay in days (for ticks):")
        label4.pack(pady=5)

        self.value4_entry = tk.Entry(root)
        self.value4_entry.pack(pady=5)

        label5 = tk.Label(root, text="Input timeframe 1 (1h),2,4,1d,1w:")
        label5.pack(pady=5)

        self.value5_entry = tk.Entry(root)
        self.value5_entry.pack(pady=5)

        label6 = tk.Label(root, text="Input epochs:")
        label6.pack(pady=5)

        self.value6_entry = tk.Entry(root)
        self.value6_entry.pack(pady=5)

        label7 = tk.Label(root, text="Input symbol:")
        label7.pack(pady=5)

        self.value7_entry = tk.Entry(root)
        self.value7_entry.pack(pady=5)


        label8 = tk.Label(root, text="Input path for mt5:")
        label8.pack(pady=5)

        self.value8_entry = tk.Entry(root)
        self.value8_entry.pack(pady=5)

        # Radio button to select program to execute
        self.opcion_var = tk.StringVar(value="program_object")
        radio_btn_object = tk.Radiobutton(root, text="With r2 Score, MAE & MSE", variable=self.opcion_var, value="program_object")
        radio_btn_object.pack(pady=5)
        radio_btn_object_without = tk.Radiobutton(root, text="Without", variable=self.opcion_var, value="program_object_without")
        radio_btn_object_without.pack(pady=5)

        # Botón start
        boton_execute = tk.Button(root, text="Run Program", command=self.execute_programa)
        boton_execute.pack(pady=10)

        # Botón close
        boton_quit = tk.Button(root, text="Exit", command=root.destroy)
        boton_quit.pack(pady=10)

    def write(self, text):
        # this method y called when sys.stdout.write is used
        self.salida_text.insert(tk.END, text)
    def flush(self):
        pass
    def execute_program(self):
        # Obteined value of the selected option
        selected_program = self.opcion_var.get()

        # Obteined value of inputs
        value1 = self.value1_entry.get()
        value2 = self.value2_entry.get()
        value3 = self.value3_entry.get()
        value4 = self.value4_entry.get()
        value5 = self.value5_entry.get()
        value6 = self.value6_entry.get()
        value7 = self.value7_entry.get()
        value8 = self.value8_entry.get()

                # Redirects stdout & stderr to the console
        sys.stdout = sys.__stdout__
        sys.stderr = sys.__stderr__

        # Calls the function to execute a selected program and pass values as arguments
        if selected_program == "program_object":
            execute_program_with(value1, value2, value3, value4, value5, value6, value7, value8)
        elif selected_program == "program_object_without":
            execute_program_without(value1, value2, value3, value4, value5, value6, value7, value8)
        # Restores stdout to a predeterminate value to no have conflicts
        sys.stdout = self
        sys.stderr = self

if __name__ == "__main__":
    root = tk.Tk()
    app = Aplication(root)
    root.mainloop()

そして以下は呼び出されるコード(コードを貼り付ける場所)です。

import sys
import MetaTrader5 as mt5
from MetaTrader5 import *
import matplotlib.pyplot as plt
import seaborn as sns  # Import seaborn for residual plot



def main(value1, value2, value3, value4, value5, value6, value7,value8):
    # Now you can use variables value1, value2, value3, value4, value5, value6, value7 en tu programa
    print("Numero de cuenta mt5 en mt5: ", value1)
    print("Password en mt5: ", value2)
    print("Servidor en mt5: ", value3)
    print("Delay dias ticks: ", value4)
    print("Time frame: ", value5)
    print("Epochs: ", value6)
    print("Symbol: ", value7)
    print("Path a mt5: ", value8)
    

def execute_program_with(value1, value2, value3, value4, value5, value6, value7, value8):
    main(value1, value2, value3, value4, value5, value6, value7, value8)

そして最後にこう書かれています。

if __name__ == "__main__":
    value1, value2, value3, value4, value5, value6, value7 = sys.argv[1:]
    main(value1, value2, value3, value4, value5, value6, value7)

これには2つあり、1つはモデルの予測スコアとグラフ、もう1つはグラフだけを表示します。

これを実行ファイルに変換するには、auto-py-to-exeを使用します。まず、ライブラリをインストールします。

pip install auto-py-to-exe

端末でauto-py-to-exeと入力するだけで、実行されます。

スクリプトの場所にgui_consolaを追加し、programa_objetivo.pyとprograma_objetivo_sin.pyを追加し、pyをexeに変換するボタンを押すだけです。

auto-py-to-exe

conda環境を使用する必要があるかもしれません。

conda activate XXX

ここで、XXXは環境名です。

Condaで問題に遭遇するかもしれません。これに対処するには、コントロールパネルからAnacondaをアンインストールし([Uninstall a program]に移動)、公式Webサイトから直接Pythonをインストールすることを検討してください。ダウンロードはお使いのオペレーティングシステムを選択してください。

Pythonをインストールする際には、システム変数にパスを追加することを忘れないでください。さらに、長さの制限を無効にします。

さらに、長さの制限を無効にします。セットアップを完了するには、端末かコマンドプロンプトで以下のコマンドを実行して、matplotlib、seaborn、sklearnをインストールします。

pip install matplotlib
pip install seaborn
pip install scikit-learn


GUI

TkGUIとは、PythonのTkinterツールキットを使用して作成されたグラフィカルユーザーインターフェイス(GUI)を指します。TkinterはPython標準ライブラリの組み込みモジュールで、グラフィカルユーザーインターフェイスの開発を容易にします。

こんな感じです。

GUI


mt5のパスを追加し、「˶」を「/」に変更します。

C:/Program Files/XXX MT5/terminal64.exe


GUI

以下は、実行ファイルにラップして実行したときにGUIに表示されるものとほぼ同じです。

001


テスターの結果は以下の通りです。

テスター001


テスターは次のようになります。赤い長方形内の値が重要な値です。明らかにこれらの値は良くありません。R2得点が1に近く、MSEとMAEが0に近いものを探す必要があります。より多くのデータやエポックを使用し、スクリプトでL2の値も変更する必要があります(適切な適合が得られ、注文する時間が確保できることを約束します ... これはゲームのようなものです)。

使用される指標

R2 (R二乗)、MSE(平均二乗誤差)、MAE(平均絶対誤差)は、統計学や機械学習において、モデルのパフォーマンスを評価するためによく使用される指標です。

  1. R2 (R二乗)

    • R2は,独立変数から予測可能な従属変数の分散の比率を表す統計的尺度です。
    • 範囲は0~1で、0はモデルが従属変数の変動を説明していないことを示し、1は完全な説明を示します。
  2. MSE(平均二乗誤差)

    • MSEは、実際の値と予測値の平均二乗差を計算する指標です。
    • 大きな誤差は小さな誤差よりも重く罰せられるため、外れ値の影響を受けやすくなります。
    • 数学的には、2乗差の合計をオブザベーションの数で割ったものです。
  3. MAE(平均絶対誤差)

    • MAEは、実際の値と予測値の差の平均絶対値を計算する指標です。
    • MSEとは異なり、差分を2乗しないため、外れ値の影響を受けにくいです。
    • 差の絶対値の合計をオブザベーションの数で割ったものです。

これらの測定基準は、モデルが結果変数をどれだけよく予測できるかを評価するために、回帰分析で一般的に使用されます。一般に、R2値が高く、MSEまたはMAE値が低いほど、パフォーマンスの良いモデルであることを示します。


過剰適合

取引のための深層学習における過剰適合とは、過去のデータに対してはうまく機能するモデルを訓練しても、新しい未知のデータに対しては効果的に汎化できないことが含まれます。取引のための深層学習の文脈で、過剰適合に伴う危険性をいくつか紹介しましょう。

  1. 限定的な汎化:過剰適合したモデルは、真の市場ダイナミクスを表していないノイズや履歴データの特定のパターンを捕捉する可能性があります。その結果、モデルは新しい市場環境や未知のデータに対して汎化するのに苦労することになります。
  2. ライブデータでのパフォーマンスの低さ:過剰適合したモデルは基本的に過去のデータを記憶しているため、実際の市場データにさらされるとパフォーマンスが低下する可能性があります。モデルが不正確な予測をしたり、変化する市場動向に適応できなかったりする可能性があります。
  3. 市場体制の変化:金融市場はダイナミックであり、異なる市場レジーム(強気、弱気、横ばい)はユニークな特徴を示すかもしれません。特定の市場レジームで訓練された、過剰適合したモデルは、市場がレジームチェンジを起こしたときに適応性を欠き、失敗する可能性があります。
  4. 偽のシグナル:過剰適合は、モデルが過去データのノイズや異常値を捕捉し、結果として誤ったシグナルをもたらす可能性があります。このような誤ったシグナルは、取引戦略を誤らせる可能性があり、実取引のシナリオでは金銭的損失につながります。
  5. データスヌーピングバイアス:過剰適合は、データ盗聴やデータ漏洩によって悪化する可能性があります。学習中にモデルがテストセットの情報に不用意に触れてしまうと、本当に見たことのないデータにうまく汎化できないパターンを学習してしまう可能性があります。
  6. ハイパーパラメータの感度:過剰適合したモデルは、ハイパーパラメータに過敏に反応する可能性があり、さまざまな市場環境にわたって堅固なパフォーマンスを発揮するための微調整が難しくなります。

このような危険性を軽減するために、取引のための深層学習の実践者は、クロスバリデーション、正則化技術、市場のダイナミクスをより広く理解するための特徴の組み込みなどの戦略を採用することが多いです。さらに、過去のデータでモデルのパフォーマンスを解釈し、サンプル外のデータセットでその有効性を検証する際には、慎重なアプローチが必要です。定期的なモニタリングとモデルの再訓練は、進化する市場環境に適応するためにも不可欠です。

深層学習における交差検証

交差検証は、機械学習モデルのパフォーマンスを評価するために使用される統計的手法です。深層学習の文脈では、交差検証はデータセットを複数のサブセットまたはフォールドに分割することを含みます。モデルはこれらのフォールドのいくつかで学習され、残りのフォールドでテストされます。このプロセスは複数回繰り返され、各反復で訓練とテストに異なるフォールドが使用されます。その後、モデルのパフォーマンスをより確実に評価するために、パフォーマンス指標をすべての反復にわたって平均化します。

一般的な交差検証には、データセットがk個のフォールドに分割され、各フォールドが1回だけテストセットとして使用されるkフォールド交差検証と、各データポイントが1つのフォールドとして扱われる一つ抜き交差検証があります。

交差検証は、モデルが未知のデータに対してどの程度汎化するかを評価するのに役立ち、過剰適合や学習不足のリスクを低減します。

カーネルレギュラライザー(kernel_regularizer=l2)

深層学習とニューラルネットワークの文脈では、カーネル正則化という用語は、ニューラルネットワーク層の重み(またはカーネル)に適用される正則化技術を指します。kernel_regularizer=l2パラメータは、特に重みに対してL2正則化を使用することを示します。

L2正則化は、重みの二乗の大きさに比例するペナルティ項を損失関数に加えます。目標は、1つの重みが大きくなりすぎて学習プロセスを支配するのを防ぐことです。これは、モデルが訓練データに適合し過ぎるのを抑制し、過剰適合を防ぐのに役立ちます。

要約すると、kernel_regularizer=l2は、大きな重みにペナルティを課すことによってニューラルネットワークの複雑さを制御するために使用される正則化手法であり、深層学習モデルにおける過剰適合の問題に対処するツールの1つです。


グラフ

このグラフは、スクリプトを実行した場所に保存されます。

タイトルに表示されている数字は、最初のオレンジ色の線からグラフの終わりまでの分単位の時間です。

グラフから必要なものを変更することができます(例えば、このラインコードでオレンジ色のライン間の範囲だけを表示するなど)。

plt.plot(dff5.iloc[punto_entrada, valor_25], linestyle='-', label='Predicted')

ただコードを読んで、理解してみてください。

グラフ

これがそのチャートです。赤い線は、売買注文と決済注文を出すべき場所を示しています。オレンジ色の線は、モデルがより信頼性が高く正確であると推定される範囲、特に最初の20%の区間を示しています。この場合、4時間の時間枠を使用したので、最適なインターバルは最初の1時間であり、エントリおよびエグジットの最大ポイントと最小ポイントを示しています。スクリプトが最後に到達すると、ループバックし、注文を追加すれば、連続的に実行され続けます。残りのマークされた線は、手動で注文を出す際にチャート上の位置を決めるのに役立ちます。

予測に示されている価格は単なる方向性であり、重要なのは、区間内の最小値と最大値がどこにあるかを知ることです。


すべての使い道

私がしているのは次です。

まず、GUIを使用して銘柄を実験し、R2、MAE、MSEでテストします。エポックと遅延日数の値を変えて反復します。次に、過大評価を避けるように注意しながら、予測に有望な値を特定したら、スクリプトに移行します。注文を自律的に実行するスクリプトを自動化し、1週間を通して継続的に注文を実行するためにVPSをリースしています。注目すべきは、高いエラーが発生した場合、調整可能なパラメータがあることです。例えば、暗号通貨の場合、FXで使用される0.001ではなく、0.01のL2を選択するかもしれません。試行錯誤の結果、データ量(遅延日数)とエポックの最適値を決定することができます。


MSE、R2、MAEの計算にはおよそ1エポックかかることを考慮することが重要です。したがって、最初は実験をおこなうことが望ましいです。いったん良いモデル近似が達成されれば、これらのパラメータなしでモデルを採用することができます。Pythonでは、該当するコードをコメントアウトするか、#という記号を使用することでこれを実現します。


私がこのPythonプログラムでやっているのは、ループを使うことです。万が一、注文の決済に失敗した場合に備えて(銘柄からコマンドをキャンセルする仕組みを実装している)、注文の間隔(具体的には1時間)を設定しているので、timer.mql5も活用しています。これにより、1時間以上注文が空くことはありません。


ループ

DeepLearningForecastをループさせるには、while=Trueを実行する代わりに、次のようにします(Loop.py)。

import time
import subprocess

def execute_program():
    
    subprocess.run(['python', 'DeepLearningForecast.py'])

# Stablish and interval in seconds (for example, 60 seconds)
seconds_interval = 5


while True:
    execute_program()
    print(f"Program executed. Waiting {seconds_interval} seconds")

    # waits the interval before executing the program
    time.sleep(seconds_interval)


Telegramボット

MT5では、すでにさまざまな方法で情報を見ることができますが、このボットの場合、正確に予測して正しく注文を実行しているかどうかを知りたいと思うことがあります。これらの行動を追跡し、実際のチャートと予測を比較するために、私はチャートと関連情報をTelegramのボットに送信しています。それでは、Telegramボットの作成方法と、Telegram経由でデータを送信する方法を説明します。

以下は、Telegramでボットを作成し、チャットIDとトークンを取得し、リクエストを通じてメッセージを送信するためのステップバイステップガイドです。

Telegramでボットを作成する

  1. Telegramを開き、BotFatherを検索する

    • Telegramを開き、検索バーで「BotFather」と検索します。
    • BotFatherとチャットを開始します。
  2. 新しいボットを作成する

    • 新しいボットを作成するには、/newbotコマンドを使用します。
    • BotFatherの指示に従って、ボットに名前とユーザー名を割り当てます。
    • 完了すると、BotFatherがトークンを提供します。このトークンはボットの認証に必要です。

チャットIDを取得する

  1. ボットとチャットを開始する

    • ボットを作成したら、Telegramでボットとチャットを開始します。
  2. ボットAPIのURLにアクセスする

    • Webブラウザを開き、以下のURLにアクセスして、BOT_TOKENをご自分のボットのトークンに置き換えます。
    https://api.telegram.org/botBOT_TOKEN/getUpdates
  1. ボットにメッセージを送る

    • Telegramに戻り、チャットを開始したボットにメッセージを送信します。
  2. ブラウザのページを更新する

    • ボットAPIURLを入力したブラウザページに戻ります。
    • ページを更新します。
  3. チャットIDを検索する

    • JSON応答の中で、メッセージの履歴を含むセクションを探します。
    • 最近送信したメッセージを表すオブジェクトを見つけます。
    • そのオブジェクトの中で、チャットフィールドを探し、その中のidフィールドがチャットIDになります。


その結果、次のようなメッセージを受け取ることができます(ボットで追跡するため)。

Telegramメッセージ



その他の修正

注文のクローズの仕方が気に入らなかったので、トレンドを利用するようにスクリプトを修正しました。単純移動平均(SMA)を追加し、価格がSMAを超えたら注文をクローズするように指示しました。

これを解決するためには、

SMA


以下を追加しました。

def obtain_sma_pandas(symbol, periodo):
    prices = mt5.copy_rates_from_pos(symbol, mt5.TIMEFRAME_M1, 0, periodo)
    df_sma = pd.DataFrame(prices)
    sma = df_sma['close'].rolling(window=periodo).mean().iloc[-1]
    return sma

以下も追加しました。

    action="buy"
    price = mt5.symbol_info_tick(symbol).ask
    period_sma=14
    sma = obtain_sma_pandas(symbol, period_sma)
    while True:
        # Obtener el precio actual y la SMA
        actual_price = price
        sma = obtain_sma_pandas(symbol, period_sma)

        # Si el precio está por debajo de la SMA, cerrar la orden
        if actual_price > sma:
            close_all_position(symbol)
            continue

        # Esperar antes de verificar nuevamente
        time.sleep(10)

また、スクリプトにadxを追加して、これでトレンドにあるときの取引を検索することもできます。

def calculate_adx(high, low, close, period):

    tr_pos = []
    tr_neg = []

    for i in range(1, len(close)):
        trh = max(high[i] - high[i - 1], 0)
        trl = max(low[i - 1] - low[i], 0)

        if trh > trl:
            tr_pos.append(trh)
            tr_neg.append(0)
        elif trl > trh:
            tr_pos.append(0)
            tr_neg.append(trl)
        else:
            tr_pos.append(0)
            tr_neg.append(0)

    atr = pd.Series(tr_pos).ewm(span=period, adjust=False).mean() + pd.Series(tr_neg).ewm(span=period, adjust=False).mean()
    dx = (pd.Series(tr_pos).ewm(span=period, adjust=False).mean() / atr) * 100
    adx = dx.ewm(span=period, adjust=False).mean()

    return adx.iloc[-1]


ONNX

現在、MetaQuotesの「MQL5でONNXモデルを使用する方法」稿を参考に、モデルをONNX形式に変換しているところです。同記事に記載されているガイドラインに従って、出来上がったONNXモデルをベースとなるEAに統合し、取引操作を開始します。このアプローチにより、機械学習モデルをMQL5環境にシームレスに統合し、取引アルゴリズムの機能を強化することができます。

ONNXに形式する前に、データをダウンロードする必要があります。これを実現するには、私がアップロードしたスクリプト(ticks_to_csv)を使用します。MQL5 EAフォルダに保存し、IDEで開いてコンパイルするだけです。完了したら、スクリプトをチャートに追加し、しばらく実行させます(銘柄のすべてのティックをダウンロードするので、しばらく時間がかかるかもしれない)。操作ログでは、プロセスが終了すると完了メッセージが表示されます。参考までに、EUR/USDで使用してみたところ、数ギガバイトを使用しました。

#property script_show_inputs
#property strict
//--- Requesting 100 million ticks to be sure we receive the entire tick history
input long      getticks=100000000000; // The number of required ticks
string fileName = "ticks_data.csv";
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   int     attempts=0;     // Count of attempts
   bool    success=false;  // The flag of a successful copying of ticks
   MqlTick tick_array[];   // Tick receiving array
   MqlTick lasttick;       // To receive last tick data

   SymbolInfoTick(_Symbol,lasttick);
//--- Make 3 attempts to receive ticks
   while(attempts<3)
     {

      //--- Measuring start time before receiving the ticks
      uint start=GetTickCount();
      //--- Requesting the tick history since 1970.01.01 00:00.001 (parameter from=1 ms)
      long received=CopyTicks(_Symbol,tick_array,COPY_TICKS_ALL,1,getticks);

      // Check if ticks were successfully copied
      if(received > 0)
        {
         // Open the CSV file for writing
         int fileHandle = FileOpen(fileName, FILE_WRITE | FILE_CSV);

         // Check if the file was opened successfully
         if(fileHandle != INVALID_HANDLE)
           {
            // Write the CSV header
            FileWrite(fileHandle, "Time,Bid,Ask");

            // Write tick data to the CSV file
            for(long i = 0; i < received; i++)
              {
               string csvLine = StringFormat("%s,%.5f,%.5f", TimeToString(tick_array[i].time), tick_array[i].bid, tick_array[i].ask);
               FileWrite(fileHandle, csvLine);
              }


            // Close the CSV file
            FileClose(fileHandle);

            // Print success message
            Print("Downloaded ", received, " ticks for symbol ", _Symbol, " and period ", Period());
            Print("Ticks data saved to ", fileName);
           }
         else
           {
            // Print an error message if the file could not be opened
            Print("Failed to open the file for writing. Error code: ", GetLastError());
           }
        }
      else
        {
         // Print an error message if no ticks were downloaded
         Print("Failed to download ticks. Error code: ", GetLastError());
        }

      if(received!=-1)
        {
         //--- Showing information about the number of ticks and spent time
         PrintFormat("%s: received %d ticks in %d ms",_Symbol,received,GetTickCount()-start);
         //--- If the tick history is synchronized, the error code is equal to zero
         if(GetLastError()==0)
           {
            success=true;
            break;
           }
         else
            PrintFormat("%s: Ticks are not synchronized yet, %d ticks received for %d ms. Error=%d",
                        _Symbol,received,GetTickCount()-start,_LastError);
        }
      //--- Counting attempts
      attempts++;
      //--- A one-second pause to wait for the end of synchronization of the tick database
      Sleep(1000);
     }
  }

そして、このデータ(CSV)から必要なセグメントを読み込み、DataFrameに変換して使用します(DeepLearning_ONNX.pyは今日までの過去1000日分定義されている)。データセット全体を使用することもできますが、十分なRAMが必要です。

データをダウンロードしたら、DeepLearningForecast_ONNX_training.pyでONNXモデルの訓練を開始します。このファイルはMQL5のFileフォルダ配下に保存してください。

以下でデータを読み込みます。

rates = pd.read_csv(file_path, encoding='utf-16le')

モデルの作成

onnx_model = tf2onnx.convert.from_keras(model, output_path=output_path)


結論

本稿では深層学習を使用した自動売買のためのPythonスクリプトを開発するための包括的なアプローチを概説しました。MetaTrader5との統合、データの前処理、モデルの訓練、売買注文の実行について検討しました。Tkinterとauto-py-to-exeを利用し、ユーザーフレンドリーなインターフェイスで実行ファイルを作成することで、スクリプトに実用性が加わりました。

さらに、適切な入力データの選択、モデルパフォーマンスの評価、効果的なクロージングオーダー戦略の実施に関する考察もおこないました。スクリプトの視覚的な出力は、予測、信頼できる範囲、および注文の配置を示し、自動取引と手動取引の両方に明確で実用的な概要を提供します。

最後に、通貨ペアのすべてのティックを読み込む方法を学びます。Pythonを使用してこのデータを読み込み、ONNXモデルを作成し、(次の記事が面白ければ)MT5でEAを使用してモデルを実行します。

ただし、金融市場の動的な性質を強調し、モデルの継続的な監視、適応、潜在的な改善を保証することが不可欠です。概説されたフレームワークは強固な基盤として機能します。進化する市場環境と特定の取引目的に基づいて、さらに調整し、強化するようお勧めします。


免責事項

免責条項: 過去の実績は将来の結果を示すものではありません。暗号通貨やその他の金融商品の取引にはリスクが伴います。どのような戦略も、すべてのシナリオにおいて利益を保証することはできません。投資を決定する前に、常に徹底的な調査をおこない、金融の専門家に助言を求めてください。


MetaQuotes Ltdにより英語から翻訳されました。
元の記事: https://www.mql5.com/en/articles/13975

添付されたファイル |
Timer.mq5 (4.57 KB)
Timer_modified.mq5 (9.73 KB)
Loop.py (0.4 KB)
gui_console.py (3.85 KB)
program_object.py (23.96 KB)
ticks_to_csv.mq5 (3.27 KB)
アルーン(Aroon)取引システムの構築とテスト アルーン(Aroon)取引システムの構築とテスト
この記事では、指標の基本を学んだ後、どのようにアルーンの取引システムを構築できるかを学び、アルーンの指標に基づいた取引システムを構築するために必要なステップを紹介します。この取引システムを構築した後、利益が出るのかさらに最適化が必要なのかをテストします。
MetaTrader 5用のMQTTクライアントの開発:TDDアプローチ(第5回) MetaTrader 5用のMQTTクライアントの開発:TDDアプローチ(第5回)
この記事は、MQTT 5.0プロトコルのネイティブMQL5クライアントの開発ステップを説明する連載の第5回です。今回は、PUBLISHパケットの構造、Publishフラグの設定方法、Topic Name文字列のエンコード方法、必要な場合のPacket Identifierの設定方法について説明します。
ケルトナーチャネル取引システムの構築とテスト ケルトナーチャネル取引システムの構築とテスト
この記事では、金融市場において非常に重要な概念であるボラティリティを利用した取引システムを紹介します。ケルトナーチャネル指標を理解し、それをどのようにコードし、どのように簡単な取引戦略に基づいて取引システムを作成し、様々な資産でテストすることができるかを理解した上で、ケルトナーチャネル指標に基づく取引システムを提供します。
多銘柄多期間指標におけるカラーバッファ 多銘柄多期間指標におけるカラーバッファ
この記事では、多銘柄多期間指標における指標バッファの構造体を確認し、これらの指標のカラーバッファのチャート上での表示を整理します。