English Русский Español Deutsch Português
preview
リプレイシステムの開発(第37回):道を切り開く(I)

リプレイシステムの開発(第37回):道を切り開く(I)

MetaTrader 5 | 16 5月 2024, 16:52
77 0
Daniel Jose
Daniel Jose

はじめに

今回は、非常に重要な問題について触れます。この記事の内容を理解することにできるだけ集中することをお勧めします。単に読むだけではなくて、という意味です。ここで強調しておきたいのは、この記事を理解できなければ、それに続く記事の内容を理解することはできないということです。

この記事で示され、説明され、伝えられることはすべて、後続の記事を少なくとも最低限理解するために不可欠なものです。

冗談ではありません。なぜなら、多くの人が、私たちが何をできるかを知らないからです。純粋にMQL5を使用して、MetaTrader 5でさまざまな要素を特定の方法で強制的に動作させます。

私は、これまでずっと、MetaTrader 5で特定のことをおこなう方法を読者の皆さんに説明する記事を書いてきました。特定のトピックについて話すことを先延ばしにし、要点に触れるのを避け、自分のプログラムで長い間やってきたことについて話そうとしていました。

これらのおかげで、MQL5だけを使用して表示するよりも、ソースコードを修正する方がより多くの作業をしなければならないことが多いほど、自分のシステムを変調させることができます。

これまで読者が目にしてきたコードは、実はすべて修正されたコードです。元々使用していたものとは全然違いました。しかし、今私は岐路に立たされていて、他にどうすればいいのかわかりません。元のコードをお見せするか、実際に使用しているものに近いコードをお見せするかしなければ、リプレイ/シミュレーションシステムのプロジェクトを続けることはできません。

問題はコードの書き方そのものではありません。私の意見では、これは非常に簡単なことです。問題は、システムを使用するだけでなく変更することもできるのに必要な知識を読者に与えたいということです。これは、読者にとって望ましい、あるべき振る舞いをさせるために必要なことであり、読者自身が分析をおこなうことができるようにするためです。

皆さんには、外部の力を借りずに、完全に自分の力で作業することを学んでいただきたいのです。お分かりいただけたでしょうか。

この記事で紹介するのは、指標といくつかのEAを使用して、ある種の複雑なシステムを作成するところまで、非常に特殊な動作と非常にモジュール化されたプログラミングをおこなう方法です。ただし、ここで問題があります。コンパイルするものはできるだけ少なくするということです。

現在、リプレイ/シミュレーションシステムには、EA、サービス、指標の3つの実行ファイルが含まれています。それでいて、発注システムを発展させることができます。このようなシステムは取引サーバーを置き換えるので、デモまたはライブ口座で取引して分析を実行できることを覚えておいてください。

まだ過去のものをリプレイ/モデリングシステムに持ち込まなければなりません。これは例えば、Chart Traderに当てはまります。したがって、何らかのシステムが必要ですが、安定していて使いやすいものでなければなりません。「一からの取引エキスパートアドバイザーの開発(第30回):指標としてのCHART TRADE?」でおこないましたが、これは私たちには合いません。

もっと透明性が高く、不便することがないように物事を進める必要があります。

これをもっとうまくおこなうことができます。もっと簡単な例で説明しましょう。もし望みのアプリケーションに直行するのであれば、私たちが議論していることについていける人はほとんどいないに違いません。こんなことにはなってほしくありません。では、どうすればいいのか見てみましょう。私の宇宙に入る準備をしてください。


指標を作り始める

MetaTrader 5の仕組みを知らない人から見ると、これからやることは非常に難しいです。最後に添付ファイルは含めません。ここで見たことを体験し、すべてがどのように機能するのかを詳しく学ぶことができることを知ってもらうために、説明に従ってほしいのです。

指標を作ることから始めましょう。次にMetaEditorを開き、次のようにします。

図01

図01:作成するものを選択する

図02

図02:ディレクトリを作成する

図03

図03:指標に名前を付ける

図04

図04:物事はシンプルに

図04にあるように、どのようなタイプの指標を作る場合でも、作成方法は同じです。図04の時点では、どちらか一方しかない場合もありますが、いずれにせよ、イベント管理機能は、必要に応じて後から追加したり変更したりできます。指標の作成は通常通りおこなえるので、ご安心ください。

図05

図05:[Finish]をクリックする

その結果、図05のようになります。この時点で[Finish]ボタンをクリックするだけです。

アイデアは、ZEROウィンドウに配置する指標を作成することです。しかし、同じ概念でどのウィンドウにも指標を配置することができます。これも、ご心配無用です。記事の主旨に注意を払ってください。

このプロセスの最後に、MetaEditorウィンドウに以下のコードが表示されます。

#property copyright "Daniel Jose"
#property link      ""
#property version   "1.00"
#property indicator_chart_window
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- indicator buffers mapping
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
//---
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+

多くの方がMetaEditorのネイティブ形式を使用することを好むことはわかっています。わかりますが、私にとってはこの形式は使い心地が悪いのです。でも、人それぞれの問題です。本当に重要なのは、コードを簡単に読んで理解できることです。

では、この標準的なコードを必要なものに修正していきましょう。

この標準コードをコンパイルしようとすると、警告が表示されます。

図06

図06:コンパイラの出力

図06はコードがコンパイルされたことを示していますが、正確に正しい方法で生成されたわけではありません。多くのプログラマーは、コンパイラがエラーについて警告してくれることを無視しています。赤い矢印がそれを示しています。

一見重要でないように見えるエラーであっても、エラーが発生するという事実は、コードが危険にさらされる可能性があるということです。したがって、コンパイラが欠陥があると報告したコードは、いかなる場合にも使用してはなりません。絶対に使用してはいけません。

この問題を解決するために、とても単純なことをしましょう。指標を使用することで何ができるかをコンパイラに伝えるのです。

#property copyright "Daniel Jose"
#property link      ""
#property version   "1.00"
#property indicator_chart_window
#property indicator_plots 0
//+------------------------------------------------------------------+
int OnInit()
{
        return INIT_SUCCEEDED;
}
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
{
        return rates_total;
}
//+------------------------------------------------------------------+

強調表示した行を追加することで、私たちが何をしているかをコンパイラに知らせることができます。結果を図07に示します。

図07

図07:理想的なコンパイルの結果

コードをコンパイルするときはいつも、コンパイラが図07と同じことを示しているよう注意してください。これが、致命的な問題を起こさずに完璧にコンパイルされたコードを得る唯一の方法です。

このようなことはもう知っていると思われるかもしれませんが、はっきりさせておきたいのです。何らかの修正によってシステムが機能しなくなったとか間違った方法で機能するとかいった文句を、誰にも言われたくないのです。このシステムを自分自身のニーズに合わせて修正し、適応させることをお勧めします。そのためには、まず基本的なことを知り、知識や考え方の基礎をしっかりと固める必要があります。

基本的な指標ができたので、基本的なEAを作成してみましょう。


EAを作り始める

必要なものを実装するためにEAを構築します。順を追ってやっていきましょう。

図08

図08:これから作るもの

図09

図09:使用するディレクトリを決定する

図10

図10:実行ファイル名を決定する

おわかりのように、私たちは指標の段階とすべて同じステップを踏んでいます。唯一の違いは、作成の最初に選択をおこなったことだけです。

図11

図11:デフォルトを保持する

図12

図12:[Finish]をクリックする

これらのステップをすべて完了すると、以下のようにMetaEditorにファイルが表示されます。

#property copyright "Daniel Jose"
#property link      ""
#property version   "1.00"
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---
   
  }
//+------------------------------------------------------------------+

指標と同様、ここでもいくつかの書式を変更します。しかし指標とは異なり、MetaEditorにこのコードのコンパイルを依頼すると、コンパイラから次のような情報が送られてきます。

図13

図13:コンパイルリクエストの結果

それはどういうことでしょうか。読者の皆さん、落ち着いてください。ご安心ください。私たちが何をしようとしているのか、すぐに理解できるでしょう。

さて、指標とEAの基本的なシステムができたので、この記事を始めた目的である、両者を接続してみましょう。

指標やEAをどのように作成するか、また、それらをどのように相互作用させ、連動させるかを理解することが重要です。多くの人は、EAが指標によって計算されたデータを使用できるように、指標を使用できるようにする基本を知っています。 

もしこの方法を知らないのであれば、まず学ぶことをお勧めします。出発点として良いのはこの記事です。「一からの取引エキスパートアドバイザーの開発(第10部):カスタム指標へのアクセス」では、指標が算出した値にアクセスする方法について、非常にシンプルに説明しています。同時に、これからやろうとしていることに応じて計算された情報にアクセスする前に、非常に簡単な方法で指標を初期化する方法を見ていきます。

これはすべてとても美しくてシンプルです。図14のアイデアを使えば、指標の内容を読み取ることができるからです。さて、図15を使用して、EAを使用した指標を作成してみましょう。

図14

図14:指標データを読み取るEA

図15

図15:EAによる指標の作成

しかし、それにもかかわらず、Chart Traderを使用しておこなったようなことをおこなう必要がある場合、この方法は機能しません。Chart Traderを指標にしたとき、別のパスを使用しなければなりませんでした。その時もすでに、将来的には変わるだろうと話していました。その記事では、図16に示すスキームを使用しました。

図16

図16:双方向通信

異なる当事者間というか、異なるプロセス間で情報を伝達する必要がある場合、そのための一定の手段が必要になります。MetaTrader 5では、グローバルターミナル変数を使用できます。これと同じ概念は、リプレイ/シミュレーションシステムでも古くから使用されています。これにより、サービスが何らかの形で指標と相互作用できることが保証されます。

同じ通信を促進する方法は他にもありますが、MQL5とMetaTrader 5のすべての利点をフルに活用できないようなテクニックは使いたくありません。プラットフォームとその言語を最大限に活用することで、将来の改良の恩恵を受けることができます。提供される機能をフルに活用しない解を考案し始めたら、MQL5やMetaTrader 5が改善されたときに、どのような恩恵を受けることができるでしょうか。

図16のシステムは多くの状況に適していますが、あまりメリットはありません。

それを理解するために、次の事実を理解しましょう。リプレイ/シミュレーションシステムで良い経験を得るためには、チャートにいくつの指標を置くべきでしょうか。1つ、2つ、それとも5つでしょうか。実際のところ、それを知ることは不可能です。ただし、すでに分かっていることがあります。少なくとも2つの指標が必要だということです。これは今のところであり、後のことではありません。今必要なのです。リプレイ/シミュレーションシステムには少なくとも2つの指標が必要です。

なぜ2つなのか不思議に思われるかもしれません。最初の指標は、リプレイ/シミュレーションをコントロールするために使用されます。この指標はすでにあります。もう1つが必要です。Chart Traderです。これで直接注文ができるようになります。Chart Traderが必要なのは、物理的な市場とは異なり、リプレイ/シミュレーションでは上隅のボタンが必要ないからです(図17)。

図17

図17:クイックトレーダーのボタン

注文を出す方法は必要ですが、それはデモ口座でもリアル口座でも同じであるべきです。プラットフォームと対話するための同じ方法を持つべきです。

図16は、EAと指標の間で注文を送信するための相互作用を可能にしますが、これは最良の方法ではありません。というのも、この場合、他の目的に使用する方がよいグローバル変数を保持する必要があるからです。必要な通信を確立するために、まったく別の道を歩むこともできます。

これに基づいて、図18に見られるような新しいアプローチを適用し始めました。

図18

図18:新しい通信プロトコル

この図を見て、私がおかしくなったと思われるかもしれません。EAと指標が直接通信できるようにするにはどうすればいいのでしょうか。この話のどこにひっかけがあるのでしょうか。いいえ。これは冗談ではないし、私がおかしくなったわけでもありません。実は、この通信を直接おこなう手段があります。図14と15を見ればわかります。ただし、これらの手段に加えて、もう1つ自由に使える手段があります。私たちが本当に必要としているのは、これらの手段をどう使用するのがベストなのかを理解することです。

続ける前に聞いておきたいのですが、MetaTrader 5を他の人とは違う方法でテストしたり使おうとしたことがありますか。MQL5を使用して、あることがその方法でできると言うところまで実験したことがありますか。この2つの質問のどちらかの答えが「いいえ」なら、これがどこまで深く続くか見てみることをお勧めします。


プロセス間の通信の開始

これまでのトピックでお分かりのように、ここでは特別な場合を除き、グローバルターミナル変数を使用しないようにして指標とEA間の通信方法を構築します。これにより、効率的な情報交換が可能になります。

アイデアはシンプルで、概念はさらにシンプルです。しかし、いくつかの詳細を理解しなければ、成功しないでしょう。これから説明することを正しく理解することが非常に重要です。MQL5のプログラミング方法をすでに知っていることで十分だとは思わないでください。これから説明することは、MetaTrader 5やMQL5言語の通常の使い方を超えたものです。

特定のことから始める必要があります。それはプロトコルを作成するようなものです。どう思われようと、この道に従えば結果は出ます。逸脱すれば失敗します。

指標のコードでは、まず以下のように最初の行を追加します。

 1. #property copyright "Daniel Jose"
 2. #property link      ""
 3. #property version   "1.00"
 4. #property indicator_chart_window
 5. #property indicator_plots 0
 6. //+------------------------------------------------------------------+
 7. #define def_ShortName       "SWAP MSG"
 8. #define def_ShortNameTmp    def_ShortName + "_Tmp"
 9. //+------------------------------------------------------------------+
10. input double user00 = 0.0;
11. //+------------------------------------------------------------------+
12. long m_id;
13. //+------------------------------------------------------------------+
14. int OnInit()
15. {
16.     m_id = ChartID();
17.     IndicatorSetString(INDICATOR_SHORTNAME, def_ShortNameTmp);
18.     if (ChartWindowFind(m_id, def_ShortName) != -1)
19.     {
20.              ChartIndicatorDelete(m_id, 0, def_ShortNameTmp);
21.             Print("Only one instance is allowed...");
22.             return INIT_FAILED;
23.     }
24.     IndicatorSetString(INDICATOR_SHORTNAME, def_ShortName);
25.     
26.     return INIT_SUCCEEDED;
27. }
28. //+------------------------------------------------------------------+
29. int OnCalculate(const int rates_total, const int prev_calculated, const int begin, const double &price[])
30. {
31.     return rates_total;
32. }
33. //+------------------------------------------------------------------+

見た目はゴチャゴチャですが、混乱はないはずです。この時点で、MetaTrader 5に、チャート上に指標が1つしかないことを確認させます。どうすればいいでしょうか。簡単に言うと、指標がチャート上にあるかどうかを確認します。

必要であれば、上記のコードを使用して、MetaTrader 5に1つの指標だけをチャートに表示させることができます。しかし、その仕組みを理解するためには、重要な行を列挙して説明することで分解し、説明全体を追いやすくする必要があります。

7行目では、指標の名前を定義します。この名前は、指標がチャート上にある限り、MetaTrader 5に保存されます。

この名前を決めるには、24行目のメソッドを使用します。ここでは、指標が使用する名前を設定します。8行目を定義する理由は、MetaTrader 5の動作方法にあります。

MetaTrader 5はイベントベースのプラットフォームです。つまり、値動き、チャート上の時間の変化、マウスの動き、キーの押下、チャートからの何かの追加や削除など、何らかのイベントが発生すると、MetaTrader 5は何らかのイベントをトリガーします。どんな出来事にも目的と結果があります。

MetaTrader 5が更新イベントをトリガーすると、チャート上に存在するすべてのオブジェクト、指標、EA、その他の要素が何らかの方法で更新されなければなりません。スクリプトの場合は単にチャートからリセットされ、指標やEAの場合はOnInit関数が新たに呼び出されます。何か問題が発生し、指標をゼロから更新しなければならない場合、MetaTrader 5は強制的に14行目を呼び出します。何が問題なのでしょうか。問題は、指標がMetaTrader 5で認識できる短い名前を持っている必要があるために発生します。そうしないと、18行目に示されているように確認できません。

24行目を18行目の前に移動させればいいと思うかもしれませんが、そこに問題があります。18行目の前に24行目を追加すると、18行目でマークした指標がすでにチャート上に存在する場合、肯定的なの結果が得られます。これは、MetaTrader 5が指標をチャートからリセットする原因となります。実際には、20行目が実行されたときにそれを残しておきたいのにです。ただし、そのインスタンスは1つだけにしたいです。

おわかりでしょうか。上記の理由により、8行目で定義された一時的な名前が必要になります。指標がすでにチャート上にある場合、18行目で確認する前に指標の短縮名に少し変更を加えます。17行目で指標の一時的な名前を設定します。注:この名前は一意でなければならず、そうでない場合は問題が発生します。

指標がすでにチャート上に存在する場合、18行目によって20行目が実行され、チャート上に現れようとしている指標が取り除かれます。21行目では、ユーザーにエラーを通知するために、MetaTrader 5のメッセージボックスにメッセージを表示します。指標は22行目に戻り、チャート上に表示できなかったことを示します。

指標がチャート上に表示されると、24行目で指標名が修正されるため、基本的に新しい指標をチャート上に配置することはできません。しかし、実際にはMetaTrader 5のギャップではない「抜け穴」があります。幸いなことに、MetaTrader 5は、チャートに新しい指標を追加する際に、それらを区別することができます。これを理解するために、10行目のコードがあります。

指標をチャート上に配置する際、ユーザーが変数の値を変更しない場合(変数は10行目で宣言されます)、MetaTrader 5は、その指標がすでにチャート上で実行されているものであれば、その指標と同じものであると理解します。ユーザーが値を変更した場合、MetaTrader 5は、同じ指標か新しい指標が追加されているかに基づいて、2つの異なる判断を下すことができます。

  • 最初のケースは、指標がない場合です。
  • もう1つは、指標がすでに存在している場合です。この場合、変数に指定された値がすでにチャートに表示されている指標と異なる場合、MetaTrader 5はそれを別の指標として認識します。値が同じであれば、MetaTrader 5はそれらを同じ指標として認識します。

この方法によって、チャート上の同じ名前の指標の数を1つだけに制限することができます。必要であれば、同じ名前の指標の最大数を設定することができます。必要なのは18行目の確認を変更するだけです。したがって、MetaTrader 5を設定して、たとえば同じ名前の3つの指標が使用可能なようにすることができます。ただし、ユーザーが同じ名前の4つ目の指標を配置しようとすると、MetaTrader 5はこれを禁止します。より正確には、これは指標コードによっておこなわれ、4つ目の指標を配置しようとする試みを阻止します。

ご覧のように、チャート上で指標の重複を許さないように、システムをカスタマイズし、制限することができます。これは非常に重要なことで、リプレイ/シミュレーションシステムについては、本連載の後半で詳しく説明します。

この指標のコードにはいくつかのポイントがありますが、グローバルターミナル変数を使用せずにEAと指標の相互作用が明確になるように、後で説明します。5行目と10行目のことです。この種のプログラミングの背後にあるロジックを理解することが重要です。

実際に何が起こっているのかを理解するために、上記で詳しく説明したコードを作成し、MetaTrader 5プラットフォーム上で実行してみてください。


結論

この記事では、MetaTrader 5プラットフォームで説明したコードを作成し実行することで、チャート上で複数の指標の配置をブロックまたは制限する方法を紹介しました。この知識を使用して他の多くのタスクを容易にすることができます。それによってトレーダーおよび MetaTrader 5プラットフォームのユーザーははるかに楽になり、体験が向上します。

この記事を読んでもその理由はよくわからないかもしれませんが、紹介した知識を正しく使えば、より多くのことができるようになり、チャート上に重複した、あるいは不必要な指標が存在することに関連する多くの問題を回避することができます。

MetaTrader 5をあまり使用したことのないユーザーは、同じ指標を何度もチャート上に配置することが珍しくないため、これらの指標の使用や設定が厄介になります。ですが、これらはすべて、かなり単純なコードを使用することで回避できます(ご覧になったように)。設計されたとおりのことは十分にできます。

この知識が役に立つことを願っています。次回は、リプレイシミュレーションシステムをさらに実装するために必要な、EAと指標間の直接通信を実現するための次のステップについて見ていきます。


MetaQuotes Ltdによりポルトガル語から翻訳されました。
元の記事: https://www.mql5.com/pt/articles/11585

添付されたファイル |
swap.mq5 (1.24 KB)
RestAPIを統合したMQL5強化学習エージェントの開発(第1回):MQL5でRestAPIを使用する方法 RestAPIを統合したMQL5強化学習エージェントの開発(第1回):MQL5でRestAPIを使用する方法
この記事では、異なるアプリケーションやソフトウェアシステム間の相互作用におけるAPI (Application Programming Interface)の重要性についてお話しします。アプリケーション間のやり取りを簡素化し、データや機能を効率的に共有することを可能にするAPIの役割を見ていきます。
Developing a Replay System (Part 36): Making Adjustments (II) Developing a Replay System (Part 36): Making Adjustments (II)
One of the things that can make our lives as programmers difficult is assumptions. In this article, I will show you how dangerous it is to make assumptions: both in MQL5 programming, where you assume that the type will have a certain value, and in MetaTrader 5, where you assume that different servers work the same.
RestAPIを統合したMQL5強化学習エージェントの開発(第2回):三目並べゲームREST APIとのHTTPインタラクションのためのMQL5関数 RestAPIを統合したMQL5強化学習エージェントの開発(第2回):三目並べゲームREST APIとのHTTPインタラクションのためのMQL5関数
この記事では、MQL5がPythonやFastAPIとどのように相互作用できるか、MQL5のHTTP呼び出しを使用してPythonの三目並べゲームと相互作用する方法について説明します。この記事では、この統合のためのFastAPIを使用したAPIの作成について説明し、MQL5でのテストスクリプトを提供することで、MQL5の多用途性、Pythonのシンプルさ、そして革新的なソルーションを生み出すために異なるテクノロジーを接続するFastAPIの有効性を強調しています。
リプレイシステムの開発(第35回):調整(I) リプレイシステムの開発(第35回):調整(I)
前に進む前に、いくつかのことを解決する必要があります。これらは実際には必要な修正ではなく、クラスの管理方法や使用方法の改善です。その理由は、システム内の何らかの相互作用によって障害が発生したということです。このような失敗をなくすために原因を突き止めようと試みましたが、すべて失敗に終わりました。例えば、C/C++でポインタや再帰を使用すると、プログラムがクラッシュしてしまいます。