
MQL5 ウィザードおよび Hlaiman EA ジェネレータを用いたニューラルネットワーク EA の作成
はじめに
実際トレーダーは皆ニューラルネットワークの存在を知っています。彼らの大多数にとってはそれはブラックボックスのままです。唯一わかっていることはパターンを認識し、関連したソリューションを産み出し、学習するニューラルネットワークの能力、またマーケット動向を予測することと自動化されたトレーディングに有効であることです。ニューラルネットワークのアプリケーションに着目した多くの情報ソースがその難しさについてよく言及します。このテーマをよく知り、将来ニューラルネットワークを使いこなせるようになるには多大な時間と労力を費やす必要があることを強調します。
こういった議論に意義を唱え高度な自動手法がトレーダーに対して簡単にニューラルネットワークを始めることを可能とし、長い学習プロセスを避けることができることを証明するのが本稿のねらいです。ニューラルネットワークを経験するのになにも難しいことはありません。テクニカル分析に比べると確実に簡単です。
このことを視野に入れて、MQL5 ウィザード と Hlaiman EA ジェネレータを使用してMetaTrader 5 用ニューラルネットワーク EA の自動作成方法についてお話していきます。
取り組むタスクを行うためのツールは決まっています。
- MQL5 ウィザード がこれまで効率的で、別のモジュールを用いて作成されたコードのサイズを測定できる自動 MQL5 コード作成の最速メカニズムです。
- Hlaiman EA ジェネレータ はオブジェクト統合の柔軟なメカニズムを持つニューラルネットワークで、Expert Advisor の MQL5 で直接プログラミングが可能です。
短縮形 'EA' は意図的に Expert Advisor につけられています。なぜなら名前の中で 'EA' の使用が誤解を招く恐れがあるものごとの本質を反映していない場合と異なり、認識と学習に関わる人間のような特性はニューラルネットワーク EA では卓越しています。
概要
本稿の目的でお話したとおり、ここには理論情報、分類、ニューラルネットワークのストラクチャ、金融マーケットに関連したリサーチデータはありません。そういった情報は別の資料で入手可能です。本稿では連想的な考えと、グラフィカルな価格パターン認識に基づくマーケット参入を予測できるブラックボックスとしてのニューラルネットワークのコンセプトに限定し時間をかけて 考えていきます。同様の理由で、収益性ある価格変動の前に現れるトレーディングインスツルメントのチャート上でのバーの連続的な変化として、パターンをもっともシンプルに表記します。
課題解決ツールについて少しお話します。Hlaimanとは異なり、MQL5 ウィザードはさまざまな記事やドキュメンテーションで頻繁に話題にされてきているので MetaTrader 5とちょうど同じように解説は必要ありません。社会的指向の Hlaiman プロジェクトはプラグイン形式で多目的ソフトウェアを開発し発展させることを意図されており、EA ジェネレータ もその一つです。前述のように EA ジェネレータは 機能的に統合メカニズムを持つニューラルネットワークエンジンの代表です。
Hlaiman EA ジェネレータ は <hlaim.exe> を持ちます。これは動的にロード可能なコンポーネントライブラリ形式の複数ドキュメントとプラグインを持つ Windows GUI アプリケーションを代表するシェルです。システムは幅広いマニュアル、アルゴリズムの調整、プラグインの一部として標準的なものとロード可能なもの両方のコンポーネント制御メソッドを備えています。システムオペレーションに関しては、スクリプトなどのオブジェクト調査と自動ソフトウェアツールを利用してオブジェクトの複雑な階層を作成し、それらのメソッドおよびプロパティを柔軟に制御することができます。
Hlaiman EA ジェネレータを MQL5 と統合することで「オブジェクトパスカル」文字列翻訳機能を持ちます。そしてソースコードが名前のついたパイプを介して渡されます。メインのニューラルコンポーネントとしては多層パーセプトロン (MLP) が使用されます。
Hlaiman EA ジェネレータはシグナルライブラリモジュール:SignalHNN.mqhを使用して MQL5 ウィザードと統合されます。自動的に作成される Expert Advisor はあらゆる数のインスツルメントおよび時間枠でトレードを行うように教えられます。МetaТrader 5 ターミナルではシグナルを示す矢印が矢印用のグラフィカルオブジェクトを使うことで価格チャート上にマニュアルで描画するか、または Expert Advisor のティーチングプロセスを同時に開始する TeachHNN.mq5 スクリプトを使用して自動で描画することができます。
これで理論的なお話は終わりです。ここから2セクション:処理の原則と実装に分けて実用部分に話を進めていきます。
第二セクションはソフトウェア開発者向けです。本ウェブサイトに配慮してここに提供されます。よって、特にプログラム技能取得には興味がないがニューラルネットワーク EA の作成とその有効性あるいはトレーディングに関して有用性がないことの評価に興味のあるトレーダーの方にとってはその部分はオプションです。
処理の原則
In MQL5.communityでは話を進めていくのに MetaТrader 5 ターミナルが必要であると言うまでもないでしょう。まだお持ちでないならダウンロードし、インストールしてください。おそらくHlaiman EA ジェネレータ デモバージョンのダウンロードおよびインストールも必要です。
МetaТrader 5 ターミナルおよび MetaEditor の起動MQL5 ウィザードを開きます。「標準」ツールバーの「新規」オプション、「ファイル」メニュー、ホットキー 'Ctrl+N' を使って開くことができます。
MQL5 ウィザードウィンドウでは、「Expert Advisor (作成)」を選択し、「次へ」をクリックします。
図1 MQL5 ウィザードでの Expert Advisor 作成
Expert Advisorの位置と名前を指定します。例:'Experts\SampleHNN'など。そして「次へ」をクリックします。
図2 Expert Advisorの一般的特性
「追加」ボタンをクリックします。「シグナルモジュールのパラメータ」ウィンドウが表示されます。そこでドロップダウンリストから「Hlaiman ニューラルネットワーク EA ジェネレータ」を選択し、「OK」をクリックします。
図3 「Hlaiman ニューラルネットワーク EA ジェネレータ」のトレードシグナルモジュール選択
ひじょうに基本的な実装の場合は MQL5 ウィザードのその後のステップすべてで「次へ」をクリックします。必要に応じて追加オプションを選択することで Expert Advisor を強化することが可能です。
コード作成の完了すれば「完了」をクリックし、MetaEditor ウィンドウを閉じます。作成済みの Expert Advisor が 'Expert Advisors'の下で MetaTrader 5 ターミナルの「ナビゲータ」パネルに表示されます。
図4 SampleHNN Expert Advisor
作成した Expert Advisorにティーチングする前にターミナル内にて必要なシンボルと時間枠のチャートを開く必要があります。Hlaiman EA ジェネレータアプリケーションをアップし実行します。
図5 ニューラルネットワークティーチング準備
Expert Advisorにティーチングするにはターミナルの「ナビゲータ」パネルにある「スクリプト」下の「TeachHNN」を選択し、指定のチャートに対して起動します。
'TeachHNN' スクリプト実行前に適切な設定がすべて整っているか確認します。以下のパラメータを持ちます。
- ドキュメント名 -ティーチング用 Expert Advisor の名前
- ニューラル階層 ニューラルネットワーク階層の番号
- ミドルニューロン -ニューロン番号
- ティーチングエポック -ティーチングエポック数
- パターンバー -パターン内のバー番号
- ネットをティーチングするか? -ニューラルネットワークティーチングプロセス(または単純にシグナル作成)の開始
- SignalsCreate シグナルのグラフィックイメージを自動で作成するため
- SignalsBarPoints ポイント表示のシグナル作成閾値
- SignalsBarsCount -ポイント計算のためのバー数
- SignalsStartTime、SignalsEndTime -シグナル作成開始および終了期間
- SignalsClear ティーチング終了時シグナルイメージを自動で削除するため
図6 TeachHNN 文字列パラメータ
すべての準備が整えば、「OK」をクリックして Expert Advisorティーチングプロセスを開始します。これでチャート内で使用可能な各シグナルに対するグラフィックバターンの自動作成を始めます。
適切な情報はターミナルの「ツールボックス」パネル上「エキスパート」タブに表示されます。また対応のオブジェクトはHlaiman EA 作成ウィンドウに表示されます。
パターン作成が終了するとティーチングプロセスが開始されます。それは画面上のティーチングプロセス進捗バーに表示されます。
図7 進捗パネルのティーチング
プロセスが完了するまで待ちます。ティーチングプロセスバー上で右クリックし、コンテクストメニューで適切なオプションを選択すると完了前にティーチングプロセスを終了することが可能です。
ティーチングプロセスとスクリプト処理が完了すると、「エキスパート」タブのログに適切なメッセージが追加されます。たとえば「ニューラルネットの作成は成功しました!」など。431 パターンでは、431シグナルを用いてExpert Advisor のティーチングが問題なく完了したことを示します。
こういったメッセージはティーチングプロセスで使用されたパターン数を示し、そのパターンの番号を見つけ出します。特に「買い」と「売り」は次のタイプのメッセージによって決定されます。:パターンNo.211で検出される「売り」シグナル。
図8 ティーチング中の TeachHNN スクリプトメッセージ
Expert Advisor ティーチングプロセスがエラーを伴ってスタートする理由は以下です。
- Hlaiman アプリケーションが必要に応じて開始前にアップされ実行されていなかった。この場合次のようなエラーメッセージとなります。「CSignalHNN::InitHNN:パイプサーバー起動エラー!(可能な理由:HLAIMAN アプリケーションが実行されていません!)」
- シグナル自動作成無効なチャート内にてシグナルを示す矢印の不在(SignalsCreate 変数 = 偽)。この場合表示されるエラーメッセージは次のようなものです。「OnStart:エラー。オーダー矢印が見つかりません」シグナル自動作成が有効であれば(SignalsCreate 変数 = 真)、エラー原因はチャート内に別のグラフィックオブジェクトがあることかもしれません。というのもカスタムマーキングはプログラム内で干渉されるはずではないからです。よってシグナル自動作成にはすべてのチャートを個別に開くことが推奨されます。
Expert Advisor のティーチングが完了すると、GUI Hlaiman に切り替え適切なオブジェクトおよび視角化パネルを選択することで応じた結果を閲覧することができます。
図9 Hlaiman アプリケーションの「テキスト」タブ
図10 Hlaiman アプリケーションの「グラフ」タブ
少なくとも1つのトレードインスツルメントで Expert Advisor をうまくティーチングできたら、検証および/または最適化に進むことが可能です。
このためには「ストラテジーテスタ」でティーチング済みの Expert Advisor名、シンボル、時間枠、間隔、その他検証パラメータを選択します。必要に応じて外部変数を設定し、検証を実行します。
図11 バックテスト用 SampleHNN Expert Advisor の設定
図12 SampleHNN Expert Advisor の外部変数は変更可能です。
以下は「ストラテジーテスタ」の Expert Advisor 処理レポート例です。Expert Advisor はデフォルトで設定されたティーチングスクリプトの外部パラメータをすべて使って自動作成シグナルを用いてティーチングされました。ティーチング機関:2010年1月1日~2013年7月1日。インスツルメント: EURUSD H4。
ストラテジーテスタレポート
Expert Advisor。 | SampleHNN |
---|---|
シンボル: | EURUSD |
期間: | H4 (2010.01.01-2013.07.12) |
通過: | USD |
初期資本: | 10,000.00 |
レバレッジ: | 0,111111111 |
バックテスト | |
履歴クオリティー: | 100% |
バー: | 5497 |
純利益: | 9,159.58 |
粗利: | 29,735.97 |
総損失: | -20,576.39 |
プロフィットファクター: | 1.45 |
リカバリーファクター: | 12.81 |
AHPR: | 1.0005 (0.05%) |
GHPR: | 1.0005 (0.05%) |
トータルトレード: | 1417 |
トータルディール: | 2246 |
ティック: | 60211228 |
残高ドローダウン絶対値: | 0.00 |
残高ドローダウン最大値: | 679.98 (3.81%) |
残高ドローダウン相対値: | 4.00% (715.08) |
予想ペイオフ: | 6.46 |
Sharpe 比率: | 0.16 |
LR 相関: | 0.98 |
LR 標準エラー: | 595.06 |
ショートトレード(勝利 %): | 703 (56.61%) |
収益トレード(トータル %): | 793 (55.96%) |
最大収益トレード: | 53.00 |
平均収益トレード: | 37.50 |
最大連続勝利: | 9 (450.38) |
最大連続収益: | 450.38 (9) |
平均連続勝利: | 2 |
シンボル: | 1 |
資本ドローダウン絶対値: | 6.60 |
資本ドローダウン最大値: | 715.08 (4.00%) |
資本ドローダウン相対値: | 4.00% (715.08) |
マージンレベル: | 6929.24% |
Z アカウント | -1.24 (78.50%) |
OnTester 結果: | 0 |
ロングトレード(勝利 %): | 714 (55.32%) |
損失トレード(トータル %): | 624 (44.04%) |
最大損失トレード: | -53.30 |
平均損失トレード: | -32.97 |
最大連続敗北: | 9 (-234.00) |
最大連続損失: | -276.67 (7) |
平均連続敗北: | 2 |
図13 SampleHNN Expert Advisor バックテスト結果
図14 SampleHNN Expert Advisor マーケット参入統計
図15 SampleHNN Expert Advisorの収益と MFE/MAE の相関関係
図16 統計を保持する SampleHNN Expert Advisor のポジション
実装
MQL5 の主要実装コンポーネントは SignalHNN.mqh シグナルモジュールに記載されるCSignalHNN クラスです。このクラスは基本クラス CExpertSignal から派生し、Hlaimanの処理および統合、MQL5 ウィザードを用いて作成される Expert Advisors との連携に必要なフィールドとメソッドをすべて持ちます。
以下がそのクラスのテンプレートです。
//+------------------------------------------------------------------+ //| Class CSignalHNN. | //| Purpose: Class of generator of trade signals based on | //| the 'Hlaiman EA Generator Neural Net' indicator. | //| Is derived from the CExpertSignal class. | //+------------------------------------------------------------------+ class CSignalHNN :public CExpertSignal { protected: //--- variables int m_hnn; // handle of HNN connect string hnn_path; // MT5 Terminal data path string hnn_fil; // HNN file w neural net string hnn_nam; // Expert name string hnn_sym; // Symbol name string hnn_per; // Period name ENUM_TIMEFRAMES hnn_period; // Period timeframe int hnn_index; // Index ext multinet int hnn_bar; // index of last bar int hnn_in; // input layer int hnn_out; // output layer int hnn_layers; // layers count int hnn_neurons; // neurons count int hnn_epoch; // learn epoch double hnn_signal; // value of last signal double pattern[]; // values of the pattern bool hnn_norm; // normalize pattern public: CSignalHNN(void); // class constructor ~CSignalHNN(void); // class destructor //--- methods of setting adjustable parameters void PatternBarsCount(int value) { hnn_in = value; ArrayResize(pattern, value + 1); } void LayersCount(int value) { hnn_layers = value; } void NeuronsCount(int value) { hnn_neurons = value; } void EpochCount(int value) { hnn_epoch = value; } void Normalize(bool value) { hnn_norm = value; } //--- method of verification of settings virtual bool ValidationSettings(void); //--- method of creating the indicator and timeseries virtual bool InitIndicators(CIndicators *indicators); //--- methods of checking conditions of entering the market virtual double Direction(void); bool FillPattern(datetime tim = 0); // prepare pattern bool AddPattern(string name, int ptype); // add new pattern bool TeachHNN(void); // learn neural net bool SaveFileHNN(void); // neural net file double CalculateHNN(void); // calc neural signal //protected: //--- method of initialization of the Hlaiman Application bool InitHNN(bool openn); // Hlaiman App Init void FreeHNN(void) { // Hlaiman App Deinit if(m_hnn!=0 && m_hnn!=INVALID_HANDLE) { FileClose(m_hnn); m_hnn=0; } }; };
コンストラクターを用いてクラスインスタンスを作成したら、このオブジェクトは主要な2モードで動作します。
- ティーチングモード:このモードはマーケットパターンの収集およびニューラルネットワークのティーチングに関連づけられています。
- インディケータモード:このモードでは現在パターンを使ってニューラルネットワークシグナルが計算されます。
このモードはブール型パラメータ opennを用いてInitHNN 初期化モードを呼ぶときに特定されます。このパラメータ値はインディケータモード(2)でティーチングされたニューラルネットワークの不データファイルの検索を開始、またそのロードと処理を行います。このモードは処理モードとみなされ、トレード用 Expert Advisorで使われます。
openn = 偽で InitHNN メソッドを呼ぶときに起動されるティーチングモード (1) とは異なり、インディケータモードは Expert Advisor の準備を行いティーチングスクリプトの処理に使用されます。
初期化メソッドは以下のように実装されます。
//+------------------------------------------------------------------+ //| Initialize HNN | //+------------------------------------------------------------------+ bool CSignalHNN::InitHNN(bool openn) { //--- initialize Hlaiman Application int num=0; ulong res=0; if(m_symbol!=NULL) { hnn_sym=m_symbol.Name(); hnn_period=m_period; } else { hnn_sym=_Symbol; hnn_period=_Period; } hnn_per = string(PeriodSeconds(hnn_period) / 60); hnn_fil = hnn_nam + NAME_DELIM + hnn_sym + hnn_per + NAME_DELIM + string(hnn_index) + TYPE_NEURO; if(m_hnn== 0|| m_hnn == INVALID_HANDLE) m_hnn=FileOpen(HLAIMAN_PIPE,FILE_READ|FILE_WRITE|FILE_BIN); if(m_hnn!=0 && m_hnn!=INVALID_HANDLE) { string source,result=""; if(openn==true) { result=CON_OPENN+CON_TRUE; if(!FileIsExist(hnn_fil,FILE_READ)) { if(FileIsExist(hnn_fil,FILE_READ|FILE_COMMON)) hnn_fil=TerminalInfoString(TERMINAL_COMMONDATA_PATH)+PATH_FILES+hnn_fil; else { // hnn_fil = hnn_path + PATH_MQL5 + PATH_FILES + hnn_fil; hnn_fil=TerminalInfoString(TERMINAL_DATA_PATH)+PATH_MQL5+PATH_FILES+hnn_fil; } } else hnn_fil=TerminalInfoString(TERMINAL_DATA_PATH)+PATH_MQL5+PATH_FILES+hnn_fil; } else { result=CON_OPENN+CON_FALSE; hnn_fil=TerminalInfoString(TERMINAL_DATA_PATH)+PATH_MQL5+PATH_FILES+hnn_fil; } source="unit InitHNN; Interface "+result+" var libr, term, exp, sym: TObject;" " Implementation function main: integer;\n\r" // Line #1 " begin" " Result := 0;" " libr := Open('mt45.dll');\n\r" // Line #2 " if (libr <> nil) then" " begin" " term := Open('"+hnn_path+"');\n\r" // Line #3 " if (term <> nil) then" " begin" " exp := term.ObjectOfName('"+hnn_nam+"');" " if (exp = nil) then exp := term.AddObject('TMT45Expert');\n\r" // Line #5 " if (exp <> nil) then" " begin" " if (exp.Name <> '"+hnn_nam+"') then exp.Name := '"+hnn_nam+"';\n\r" // Line #6 " sym := exp.ObjectOfName('"+hnn_sym+hnn_per+"');" " if (sym = nil) then sym := exp.AddObject('TMT45Symbol');" " if (sym <> nil) then" " begin" " sym.Log.Add('"+hnn_sym+hnn_per+"');\n\r" " if (sym.Name <> '"+hnn_sym+hnn_per+"') then sym.Name := '"+hnn_sym+hnn_per+"';" " if (sym.Period <> "+hnn_per+") then sym.Period := "+hnn_per+";" " if (openn = true) then" " begin" // " sym.Log.Add('" + hnn_fil + "');" " if (sym.Open('"+hnn_fil+"')) then Result := sym.TeachInput;\n\r" // ret input Line #8 " end else" " begin" " sym.TeachInput := "+IntegerToString(hnn_in)+";" " sym.TeachOutput := "+IntegerToString(hnn_out)+";" " sym.TeachLayer := "+IntegerToString(hnn_layers)+";" " sym.TeachNeurons := "+IntegerToString(hnn_neurons)+";" " sym.TeachEpoch := "+IntegerToString(hnn_epoch)+";" " sym.FileName := '"+hnn_fil+"';" " Result := sym.TeachInput;\n\r" // ret input Line #9 " end;" " end;" " end;" " end;" " end;" " end; end."; FileWriteString(m_hnn,source,StringLen(source)); FileFlush(m_hnn); while(res<=0 && (MQL5InfoInteger(MQL5_TESTER) || num<WAIT_TIMES)) { Sleep(SLEEP_TIM); res=FileSize(m_hnn); num++; } if(res>0) { result=FileReadString(m_hnn,int(res/2)); res=StringToInteger(result); if(res<=RES_OK) printf(__FUNCTION__+": Error! Initialization data(possible reason: FILE NOT EXIST OR CORRUPTED "+hnn_fil); else { printf(__FUNCTION__+": Initialization successful! NEURAL PATTERN "+string(res)); ArrayResize(pattern,int(res+1)); return(true); } } else printf(__FUNCTION__+": Error! pipe server not responding(possible elimination: RESTART HLAIMAN APPLICATION)"); } else printf(__FUNCTION__+": Error! initializing pipe server (possible reason: HLAIMAN APPLICATION IS NOT RUNNING!)"); //--- ok return(false); }
コードにあるように、初期化の第一ステップでは Hlaiman アプリケーションとの連携用の名前付パイプを開こうとします。これが失敗すると(たとえば<hlaim.exe> が実行しない)ネガティブなステータスで終了します。第二ステップでは(第一ステップが問題なく完了し、インディケータモードが開いたら)ニューラルネットワークデータを持つ必要な名前でターミナルのローカルフォルダおよび共通フォルダが検索されます。第三ステップでは Hlaiman アプリケーションで直接初期化するためObjectPascal (Delphi) でコードの準備を行います。
そうするとコードのテキストはソースストリングに移動します。フォーマットしやすいように '\n\r' を用いて従属文字列に分割され、Hlaiman オブジェクトプロパティとメソッドを起動します(コメント参照)。テキストで定義されているように、MetaTrader 5 Hlaiman プラグインのオブジェクトに基づく環境はツリー構造をしており、プラグインのオブジェクトは根にあたります。
МetaТrader 5 ターミナルオブジェクトは次のレベルにあり、それに Expert Advisor およびシンボルオブジェクトが続きます。うまく翻訳ができ名前付パイプを介して渡されるソースコードが実行されると、返される「結果」の値がニューラルネットワークインプットベクターのエレメント番号を持ちます。コードが表すように、この値はパターン配列を初期化するのに使用され、メソッドの実行はポジティブ状態で完了します。
CSignalHNN クラスのその他のキーメソッドは CalculateHNN、AddPattern、TeachHNNです。CalculateHNN はインディケータモードでニューラルネットワークの計算結果を返します。その他2つはそれぞれパターン収集とニューラルネットワークティーチング起動時に使用されます。
以下が<SignalHNN.mqh>でのそれらメソッドの実装です。
//+------------------------------------------------------------------+ //| Calculate HNN signal | //+------------------------------------------------------------------+ double CSignalHNN::CalculateHNN(void) { if(m_hnn==0 || m_hnn==INVALID_HANDLE) return(0.0); int num = 0; ulong siz = 0; double res=0.0; string source,result=""; if(FillPattern(0)==true) { result=CON_START; for(int i=1; i<(ArraySize(pattern)-1); i++) result= result+DoubleToString(pattern[i])+CON_ADD; result = result + DoubleToString(pattern[ArraySize(pattern) - 1]) + CON_END; source = "unit CalcHNN; Interface " + result + " var i: integer; libr, term, exp, sym, lst: TObject;" " Implementation function main: double;\n\r" // Line #1 " begin" " Result := 0.0;" " libr := Open('mt45.dll');\n\r" // Line #2 " if (libr <> nil) then" " begin" " term := Open('"+hnn_path+"');\n\r" // Line #3 " if (term <> nil) then" " begin" " exp := term.ObjectOfName('"+hnn_nam+"');\n\r" // Line #4 " if (exp <> nil) then" " begin" " sym := exp.ObjectOfName('"+hnn_sym+hnn_per+"');\n\r" // Line #5 " if (sym <> nil) then" " begin" " lst := TStringList.Create;" " if (lst <> nil) then" " begin" " lst.Text := cons;" " if (lst.Count >= sym.NetInputs.Count) then" " begin" " for i := 0 to sym.NetInputs.Count - 1 do" " begin" " sym.NetInputs.Objects[i].NetValue := StrToFloat(lst[i]);\n\r" // Line #6 // " sym.Log.Add('Input ' + IntToStr(i) + ' = ' + lst[i]);" " end;" " sym.Computed := true;" " Result := sym.NetOutputs.Objects[0].NetValue;\n\r" // ret input Line #7 " end;" " lst.Free;" " end;" " end;" " end;" " end;" " end;" " end; end."; FileWriteString(m_hnn,source,StringLen(source)); FileFlush(m_hnn); while(siz<=0 && (MQL5InfoInteger(MQL5_TESTER) || num<WAIT_TIMES)) { Sleep(SLEEP_TIM); siz=FileSize(m_hnn); num++; } if(siz>0) { result=FileReadString(m_hnn,int(siz/2)); res=StringToDouble(result); } } //else Print("fill pattern error!"); return(res); } //+------------------------------------------------------------------+ //| AddPattern | //+------------------------------------------------------------------+ bool CSignalHNN::AddPattern(string name,int ptype) { int num=0; long res=0; ulong siz=0; string result,source,nam=name; if(m_hnn!=0 || m_hnn!=INVALID_HANDLE) { pattern[0]=ptype; result=CON_START; for(int i=0; i<(ArraySize(pattern)-1); i++) result= result+DoubleToString(pattern[i])+CON_ADD; result = result + DoubleToString(pattern[ArraySize(pattern) - 1]) + CON_END; source = "unit AddPatternHNN; Interface " + result + " Implementation function main: integer;" " var i: integer; out: double; onam: string;" " libr, term, exp, sym, ord, tck, lst: TObject;\n\r" // Line #1 " begin" " Result := 0;" " libr := Open('mt45.dll');\n\r" // Line #2 " if (libr <> nil) then" " begin" " term := Open('"+hnn_path+"');\n\r" // Line #3 " if (term <> nil) then" " begin" " exp := term.ObjectOfName('"+hnn_nam+"');\n\r" // Line #4 " if (exp <> nil) then" " begin" " sym := exp.ObjectOfName('"+hnn_sym+hnn_per+"');\n\r" // Line #5 " if (sym <> nil) then" " begin" " lst := TStringList.Create;" " if (lst <> nil) then" " begin" " lst.Text := cons;" " if (lst.Count >= (sym.TeachInput + sym.TeachOutput)) then" " begin" " out := StrToFloat(lst[0]);" " if(out >= 0) then onam := 'BUY-"+nam+"'" " else onam := 'SELL-"+nam+"';" " ord := sym.ObjectOfName(onam);" " if (ord = nil) then ord := sym.AddObject('TMT45Order');\n\r" // Line #6 " if (ord <> nil) then" " begin" " if (ord.Name <> onam) then ord.Name := onam;\n\r" // Line #7 " if (out >= 0) then ord.OrderType := 0 else ord.OrderType := 1;" " if (ord.NetOutput <> out) then ord.NetOutput := out;\n\r" // Line #8 " for i := 1 to sym.TeachInput do" " begin" " if(i <= ord.Count) then tck := ord.Items[i - 1] else" " tck := ord.AddObject('TMT45Tick');\n\r" // Line #10 " if (tck <> nil) then" " begin" " tck.x := i;" " tck.y := StrToFloat(lst[i]);\n\r" // Line #11 " end;" " end;" " end;" " Result := sym.Count;\n\r" // ret input Line #12 " end;" " lst.Free;" " end;" " end;" " end;" " end;" " end;" " end; end."; FileWriteString(m_hnn,source,StringLen(source)); FileFlush(m_hnn); while(siz<=0 && (MQL5InfoInteger(MQL5_TESTER) || num<WAIT_TIMES)) { Sleep(SLEEP_TIM); siz=FileSize(m_hnn); num++; } if(siz>0) { result=FileReadString(m_hnn,int(siz/2)); res=StringToInteger(result); } } return(res>0); } //+------------------------------------------------------------------+ //| TeachHNN | //+------------------------------------------------------------------+ bool CSignalHNN::TeachHNN(void) { int num=0; long res=0; ulong siz=0; string result,source; if(m_hnn!=0 || m_hnn!=INVALID_HANDLE) { source="unit TeachHNN; Interface const WAIT_TIM = 100; WAIT_CNT = 100;" " var i: integer; libr, term, exp, sym: TObject;" " Implementation function main: integer;\n\r" // Line #1 " begin" " Result := 0;" " libr := Open('mt45.dll');\n\r" // Line #2 " if (libr <> nil) then" " begin" " term := Open('"+hnn_path+"');\n\r" // Line #3 " if (term <> nil) then" " begin" " exp := term.ObjectOfName('"+hnn_nam+"');\n\r" // Line #4 " if (exp <> nil) then" " begin" " sym := exp.ObjectOfName('"+hnn_sym+hnn_per+"');\n\r" // Line #5 " if (sym <> nil) then" " begin" " if (sym.Teached) then sym.Teached := false;\n\r" // Line #6 " sym.Teached := true;\n\r" // Line #7 " Result := sym.Count;\n\r" // ret input Line #8 " end;" " end;" " end;" " end;" " end; end."; FileWriteString(m_hnn,source,StringLen(source)); FileFlush(m_hnn); while(siz<=0) {// && (MQL5InfoInteger(MQL5_TESTER) || num < WAIT_TIMES)) { Sleep(SLEEP_TIM); siz=FileSize(m_hnn); num++; } if(siz>0) { result=FileReadString(m_hnn,int(siz/2)); res=StringToInteger(result); } } return(res>0); }
コードにあるように、メソッド本文はまずソース行で構成されます。そのテキストは上記 InitHNN メソッド記述で考えられているテキスト同様に整列されます。唯一の相違はプラグインのオブジェクトに基づく階層にはオーダーとティック、2つのレベルがあることです。さらに、コードは別のオブジェクトプロパティとメソッドを持ちます。たとえば、ニューラルネットワーク計算の開始は「シンボル」オブジェクトの「計算された」フラグによりフラグされます。また「ティーチングされた」フラグはティーチングプロセス開始時に使用されます。
CalculateHNN メソッドもまたこの場合「ダブル」タイプの関数により返される「メイン」の値タイプであるその他メソッドとは異なります。この値はニューラルネットワークのアウトプット値です。すなわちシグナルで、「買い」レベルが 0..1 の範囲にあり、「売り」レベルは 0..-1の範囲にあります。このシグナルはトレードポジションのオープンまたはクローズに従った判断を行うとき Expert Advisor によって使用され Direction メソッドによって制御されます。このメソッドは新規バーの場合再計算を行い、パーセントで表されるその値を返します。
//+------------------------------------------------------------------+ //| Check conditions for trading signals. | //+------------------------------------------------------------------+ double CSignalHNN::Direction(void) { if( m_hnn == 0 || m_hnn == INVALID_HANDLE) return(EMPTY_VALUE); //--- check new bar condition int cur_bar = Bars(hnn_sym, hnn_period); if (hnn_bar != cur_bar) { //--- condition OK hnn_signal = CalculateHNN() * 100; hnn_bar = cur_bar; } return(hnn_signal); }
Expert Advisor のシグナル応答閾値をトレードポジションのオープンおよびクローズに対するシグナルに対して設定するには、以下の外部変数を利用することができます。
- input int Signal_ThresholdOpen =10; // Signal threshold value to open [0...100]
- input int Signal_ThresholdClose=10; // Signal threshold value to close [0...100]
実践ではシグナルレベルはニューラルネットワークのティーチングクオリティーと強さに依存します。その強さはティーチング中のインディケータに表示される計算誤差の変動が減ることをモニターすることで目で見て判断することができます。
おわりに
Hlaiman EA ジェネレータは MQL5との統合へのコンポーネントと透過的な制御されたオブジェクトに基づく環境を提供します。それにより以下につながります。
- MQL5 ウィザードインターフェースがシグナルとパターン認識に基づく別のタイプ、またニューラルネットワークEAを作成する機能を取得します。
- 迅速にニューラルネットワーク EAを作成する能力に加え、それを変動する市場行動にすばやく適応し、異なるトレードインスツルメントと時間枠で繰り返しティーチングすることができます。
- MQL5 ウィザードが複数のシグナルモジュールを有効にできるため、複数通過対応ニューラルネットワーク EAを作成および/またはインディケータに基づくニューラルネットワーク EAを組み合わせることができます。それらはまた時間フィルターなど別のフィルターと連結することができます。
- 最後にニューラルネットワークモジュール自体は既製の Expert Advisorの効率を高めるための追加フィルターとして使用することが可能です。これは元の Expert Advisorの検証結果のビジュアル化チャートを用いてニューラルネットワークをティーチングする能力があるために可能となるものです。
あまり高くない処理のような統合計算システムを起こすスクリプト翻訳機能の利用は上記実装のデメリットの一つとみなされています。ただ、最初に Hlaiman プラグインの処理同様、スクリプトコードの解釈は EX5に非同期的である、すなわち並列タスク処理を行う必要があることに注意が必要です。次に、大きなニューラルネットワークの処理をするときなど時間のかかる計算速度を高めるために、MetaTrader 5 および Hlaiman は名前の付いたネットワークパイプを介して連結している異なるコンピュータで実行することができます。個別のコンピュータでトレードターミナルを起動することで、パフォーマンスが上昇するだけでなく、安全性も高まります。
大局的に見るとトレード中に自己学習可能な Expert Advisors の作成を詳しく調査することができます。現時点では Expert Advisor のコードをティーチングスクリプトコードと連結することでこれを行うのがもっとも簡単な方法です。それは両者が必要な機能性を提供する CSignalHNN クラスを使用するためです。この資料は興味を引くものに思えるなら後に続く記事のテーマ、またはまったく新しい記事の基本になるかもしれません。
Hlaiman EA ジェネレータのデモバージョンは ここからダウンロードできます。
添付
- SignalHNN.mqh -シグナルモジュール "MQL5\Include\Expert\Signal\".
- TeachHNN.mq5 -ティーチングスクリプト "MQL5\Scripts\".
- SampleHNN.mq5 -トレードシグナルモジュール「Hlaiman ニューラルネットワーク EA」パターンシグナルを基にMQL5 ウィザードを用いて作成される Expert Advisor
MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/706





- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索