
単一チャート上の複数インジケータ(第04部): エキスパートアドバイザーに進む
はじめに
以前の記事では、複数のサブウィンドウでインジケータを作成する方法を説明しました。これは、カスタムインジケータを使用するときに興味深いものになります。これは非常に簡単にできました。ただし、エキスパートアドバイザーではカスタムインジケータで使用したツールがないため、同じ機能を実装しようとすると少し複雑になります。この時点で、プログラミングが不可欠になります。サブウィンドウを作成するための正しいコードを記述できることが最も重要です。このタスクはそれほど簡単ではありませんが、サブウィンドウをEAに配置する方法を知ることには多くのコーディングは必要ではありません。必要なのはMQL5がどのように機能するかについての知識だけです。
計画
カスタムインジケータはすでに機能しています。つまり、オブジェクトクラスはすでに機能しています。これはオブジェクトクラスであるため、他のモデルに簡単に転送できます。ただし、EAでクラスを宣言して使用しようとしてもカスタムインジケータと同じように機能しません。EAにサブウィンドウ機能がないためです。ただし、その後、「すでにコンパイルされ機能しているカスタムインジケータを使用し、iCustomコマンドを使用してEAから呼び出すとどうなるか」という考えを思いつきました。サブウィンドウは不要で、コマンドは次のようになるため、実際に機能する可能性があります。
#property copyright "Daniel Jose" //+------------------------------------------------------------------+ input string user01 = ""; //Used indicators input string user02 = ""; //Assets to follow //+------------------------------------------------------------------+ int OnInit() { int m_handleSub; //... Expert Advisor code ... if ((m_handleSub = iCustom(NULL, 0, "Chart In SubWindows\\Chart In SubWindow.ex5", user01, user02)) == INVALID_HANDLE) return INIT_FAILED; if (!ChartIndicatorAdd(ChartID(), 0, m_handleSub)) return INIT_FAILED; //... Expert Advisor code ... ChartRedraw(); return(INIT_SUCCEEDED); } //...The rest of the Expert Advisor code ...
この単純なコードスニペットはカスタムインジケータを読み込むことができますが、サブウィンドウがないため正しく機能しません。この場合、コードがEAで実行されると、EAはメインウィンドウに直接インジケータを適用します。つまり、インジケータによってロードされたテンプレートによってチャートが非表示になります。これは、ここで探しているものではありません。
ここで本当の主な問題は、すでに機能しているインジケータを使用できるように使用できるサブウィンドウを作成することです。しかし、なぜインジケータを後で起動するためのサブウィンドウを作成するのでしょうか。意味がありません。EAに直接機能を追加して、発生する可能性のある制限を克服することをお勧めします。
これに基づいて、いくつかのタスクを実行する必要があります。
タスク | 目的 |
---|---|
1=>汎用インジケータを作成する | チャートを汚染することなく、iCustomコマンドを作成して使用できる |
2=>このインジケータを何らかの方法でEAに含める | すべての機能を備えたエキスパートアドバイザーを問題なく転送できるようになる |
3=>サブウィンドウの一般的なオブジェクトクラスを生成する | EAを介してサブウィンドウを追加できるようにする |
4=>ウィンドウクラスにバインドされたC_TemplateChartクラスを取得する | すでに実行中のコードを変更することなく、サブウィンドウのコンテンツを管理できるようになる |
難しく見えるかもしれませんが、問題は非常に簡単に解決されます。それぞれのポイントに取り組みましょう。
実装: 汎用インジケータの作成
この部分は、完全にクリーンで機能的なカスタムインジケータコードを作成することで解決できます。この場合のコードは次のようになります。
#property copyright "Daniel Jose" #property version "1.00" #property description "This file only enables support of indicators in SubWin." #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; } //+------------------------------------------------------------------+
これだけです。このファイルをSubSupport.mq5として保存しましょう。ただし、他のインジケータと一緒に配置せず、代わりに、エキスパートアドバイザーのRESOURCEディレクトリに移動します。ファイル構造は次の図のようになります。
実装: EAに一般的な指標を含める
これを行うには、EAの先頭に次のコードを追加する必要があります。
//+------------------------------------------------------------------+ #define def_Resource "Resources\\SubSupport.ex5" //+------------------------------------------------------------------+ #resource def_Resource //+------------------------------------------------------------------+
一般的なインジケータのコンパイル済みコードがEAに含まれます。これが行われると、一般的なインジケータの.ex5ファイルが不要になるため、削除されます。ここで、EAコードのコンパイル時にSubSupport.ex5ファイルが見つからない場合、コンパイラはSubSupport. mq5汎用インディケータのコードを自動的にコンパイルして、この新しくコンパイルされた実行可能ファイルをエキスパートアドバイザーに追加することに注意してください。万が一SubSupport.mq5ファイルを編集して変更をエキスパートアドバイザーに追加する必要がある場合は、SubSupport.ex5を削除してください。そうしないと、変更は追加されません。
この詳細は重要です。リソースに新しく実装された変更を追加する方法を本当に知る必要がある場合があります。
さて、汎用インジケータがエキスパートアドバイザーの一部になったので、次のタスクに進みましょう。
実装: サブウィンドウオブジェクトクラスの作成
この部分もシンプルです。ここでは、コーディングする前にいくつかのポイントを定義する必要があります。つまり、このクラスで本当に必要な機能は何かということです。当初、私は以下を使用することにしました。
関数 | 説明 |
---|---|
Init | EAを介してサブウィンドウを追加できるようにする |
Close | EAを介してサブウィンドウを追加できるようにする |
これらの関数はテストされないため、EAの存続期間中に一度だけ呼び出されると仮定します。ただし、EAが成長するにつれて、将来的にさらに実用的にすることを検討するのは良いことなので、C_Terminalという新しいオブジェクトクラスを作成しましょう。このクラスは、グラフィカルターミナルに関連するいくつかの機能をサポートします。これについては後で詳しく説明します。解決策を部分的に実装する方法がないため、最後のタスクを見てみましょう。
実装: C_TemplateChartクラスの継承
OOP(オブジェクト指向プログラミング)を使用して新しいものを作成することにしたのは、このアプローチを使用するとセキュリティと継承を含む大きなメリットがあることをすでに知っていたからです。ポリモーフィズムもありますが、これは後で両建て注文システムを作成するときに使用します。この特定の場合、OOPのメリットの1つである継承を使用します。C_TemplateChartはすでに完全に機能するクラスです。これを見れば、すべてを再プログラミングする手間をかけたり、クラスが他の場所で使用できなくなるリスクを冒してクラスにコードを追加したくはなくなるでしょう。解決策は、元のコードをまったく変更せずに新しいコードまたは関数を追加できる継承を使用することです。
継承を使用することには、すでにテストされたコードはテストされたままである、コードサイズを均等に増やさずに複雑さを増す、実際にテストする必要があるのは新機能だけである、変わらないものは単に継承されて安定性が得られるといった多くのメリットがあります。言い換えれば、最小限の労力で物事を改善し、最大限のセキュリティを持つことができます。これを理解するために、下の図を見てみましょう。
祖父母クラスは、データ操作のレベルが最も低い最も基本クラスですが、親クラスが祖父母から何かを継承すると、祖父母クラスでpublicとして宣言されたすべてのものを親クラスが表示して使用できます。また、親クラスに新しいものを追加することもできます。これは、継承され、継承によってサポートされるものには影響しません。親クラスがすでに完成して機能しており、下のクラスで何も変更せずに拡張したい場合は、子クラスを作成します。これにより、前のクラスのすべての機能が利用できるようになります。また、動作方法を変更することもできます。これらの変更は他のクラスに影響を与えないため、継承について興味深いことです。ただし、多重継承を許可するC ++とは異なり、ここには制限があります。子供が父側と母側の両方から機能を継承できる場合、これはMQL5では不可能です。それでも継承の恩恵を受けることができます。多重継承の例を以下に示します。
でも、MQL5でそれを行い、継承を宣言してそれを利用できるようにするにはどうすればよいでしょうか。これを理解する最も正確な方法はオブジェクト指向プログラミング(OOP)コンテンツを読むことですが、ここでは要点を簡単に説明します。継承は次の行を使用して行われます。
#include "C_TemplateChart.mqh" //+------------------------------------------------------------------+ class C_SubWindow : public C_TemplateChart { // ... Class code };
C_SubWindowクラスがC_TemplateChartクラスをpublicに継承することを確認してください。これで、C_SubWindowを使用して、C_TemplateChartクラスの機能にアクセスできるようになります。
上記のコードスニペットでは、1つのことを強調しました。通常のように、山括弧(<>)ではなくて引用符( ")で囲まれています。なぜでしょうか。C ++言語と同様、MQL5にも非常に興味深いものがいくつかありますが、プログラミングの技術を学び始めたばかりの人を混乱させるものもあります。ヘッダーファイルを山括弧(<>)で囲むと絶対パスが意味されます。この場合、コンパイラは指定したパスを正確にたどります。ただし、(今回のように)引用符を使用すると、コンパイラは相対パスを使用します。わかりやすく言えば、最初に作業ファイルが配置されている現在のディレクトリから開始します。奇妙に思えるかもしれませんが、内容が異なり、異なるディレクトリに同名のファイルがあるかもしれないが現在のディレクトリを参照したいので、引用符を使用します。
前述した、使用予定の2つの関数(INITとCLOSE)を以下に示します。
//+------------------------------------------------------------------+ bool Init(void) { if (m_handleSub != INVALID_HANDLE) return true; if ((m_handleSub = iCustom(NULL, 0, "::" + def_Resource)) == INVALID_HANDLE) return false; m_IdSub = (int) ChartGetInteger(Terminal.Get_ID(), CHART_WINDOWS_TOTAL); if (!ChartIndicatorAdd(Terminal.Get_ID(), m_IdSub, m_handleSub)) return false; return true; } //+------------------------------------------------------------------+ void Close(void) { ClearTemplateChart(); if (m_handleSub == INVALID_HANDLE) return; IndicatorRelease(m_IdSub); ChartIndicatorDelete(Terminal.Get_ID(), m_IdSub, ChartIndicatorName(Terminal.Get_ID(), m_IdSub, 0)); ChartRedraw(); m_handleSub = INVALID_HANDLE; } //+------------------------------------------------------------------+
コードはとてもシンプルで短いです。ただし、注意しなければならないことがあります。強調表示されている部分に注意してください。この部分を追加するときに間違えないように注意してください。そのままにしないと、EAに追加するように要求したSubSupport.ex5実行可能ファイルがEA内に表示されず、EAの外に表示されるためです。詳細については、リソースをご覧ください。ただし、基本的に(::)を使用する場合、これはEAがその内部で使用可能な内部リソースを使用する必要があることを示します。ただし、リソース名だけを指定すると、EAはMQL5ディレクトリ内で検索し、指定した場所にファイルが存在しない場合は、EAリソースとして追加しても機能しなくなります。
次に、リソースが読み込まれたら、存在するサブウィンドウの数を確認し、そのサブウィンドウにインジケータを追加します。
コードが実際に行っていることを以下に示します。
input string user01 = ""; //Used indicators input string user02 = ""; //Assets to follows //+------------------------------------------------------------------+ int OnInit() { int m_handleSub; //... if ((m_handleSub = iCustom(NULL, 0, "Chart In SubWindows\\Chart In SubWindow.ex5", user01, user02)) == INVALID_HANDLE) return INIT_FAILED; if (!ChartIndicatorAdd(ChartID(), (int) ChartGetInteger(ChartID(), CHART_WINDOWS_TOTAL), m_handleSub)) return INIT_FAILED; //... ChartRedraw(); return(INIT_SUCCEEDED); } //...The rest of the Expert Advisor code ...
どちらのコードも同じように機能しますが、上記のバージョンは統合バージョンであり、変更されないため、オブジェクトクラスバージョンでは、時間の経過とともにさらに多くのものを追加できます。どちらのバージョンも同じことを行います。EAからサブウィンドウを作成し、以前に作成したすべてのカスタムインジケータをこのサブウィンドウに配置します。記事冒頭のコードと比較して、コードに加えられた変更に注意してください。変更は色で強調表示されています。
終わりに
目標を達成するための道をどのようにたどることを決定するかは非常に興味深いです。困難に直面し、目標を達成するのが困難だと思うこともありますが、少しの忍耐と献身で、最初は乗り越えられなかった障害を克服することができます。この記事では、継承を通じて、クラスを変更せずにクラスの機能を拡張する方法を示します。同時に、チャートにインジケータを追加して、すでにテスト済みのように機能させる方法を示します。ex5プログラムをEA内に追加し、EAをロードするだけで元のex5を移植せずに使用できます。
添付ファイルには、れまでに開発されたすべての改善点が含まれていますが、このコードにはすぐに、さらに興味深いものが含まれる予定です。😁👍
MetaQuotes Ltdによりポルトガル語から翻訳されました。
元の記事: https://www.mql5.com/pt/articles/10241





- 無料取引アプリ
- 8千を超えるシグナルをコピー
- 金融ニュースで金融マーケットを探索
新しい記事1つのチャートに複数のインジケータ(パート04):EAで始めるインジケーター 運用」を掲載しました:
著者ダニエル・ホセ
こんにちは、ダニエル。あなたの記事を拝見していますが、パート03についてはどうですか?
しかし、私はすでにパート03の公開を許可しています。現在、彼らが分析するための記事がさらに15本あり、そのすべてがこのEAの開発に関与しており、そのたびに事態は複雑になっている......しかし、シリーズにお付き合いいただきありがとうございます......記事05以降、たくさんの新情報を楽しみにしていてください!それ以降は本当に大きなものになるので、価値がありそうです!この最初の数本は、これから起こることを紹介するためのものです...😁👍。
こんにちは、ダニエル、
多色のインジケーターで困っているのですが、あなたの記事を読んでいると、解決策をご存知かもしれません。
例えば、#property indicator_color1 clrCrimson,clrWhite,clrLime などです。
下のテスト・プログラムでわかったことは、#property indicator_color1 clrCrimson,clrWhite,clrLimeが 含まれている場合、プログラムは正しく動作するのに対し、コメントアウトした場合、プログラムは正しく動作しないということです。この場合、"高い?"時間枠を使用しているかのようにデータ・ポイントの一部だけをプロットしているか、いくつかのデータ・ポイントをスキップしているようです。 私は、複数の色が指定されている場合、property colorディレクティブが、私が識別していない属性をさらに設定しているのではないかと疑っています。
2つ目の問題は、マルチカラー・プロットを使用するための詳細と要件を明らかに理解していないことです。 ドキュメントを検索しましたが、マルチカラー・インジケータの 使用方法の概要を提供する記事は見つかりませんでした。 最初のプロットは正しく色が変わりますが、安値をプロットする2番目のプロットは、私の関数呼び出しに従って色が変わりません。このプロットが正しく動作するには、type2、color2、width2の3つのプロパティすべてが必要です。 プロパティ宣言が3ではなく2を使用している理由にも困惑しています。MladenのLaguerre Adaptive Filterインジケータを使用して、プロパティインジケータが正しく表示するためにインジケータ番号3ではなく、プロット番号2を使用していることを確認しました。
何かご提案、参考文献、ヘルプがありましたら、ぜひご連絡ください。
ありがとうございました。
何かご提案、ご参考、お力添えなどございましたら、何なりとお申し付けください。
敬具 CapeCoddah
あなたが少し混乱しているのは理解できますが、その混乱はすべて、あなたが実際にコードの詳細を見ていないことにあります。コメントにある詳細をいくつか説明してから、あなたのコードについて少し話そうと思う...。
最初のポイントは、#property indicator_colorNを使わなくても、多色のインジケータを作成することはできますが、ユーザーにとっても、あなたにとっても、より実用的で、より安全で、コードを理解し修正するのが簡単だということです。これは、#property indicator_colorN を 使用しない場合の方法です。しかし、プロパティを使用する場合、他の色を設定するためにPlotIndexSetInteger コマンドを使用する意味がないことがよくあります、たとえそのコードがあなたのもので、あなただけがそのインジケータを使用するとしても、まれに動的なカラーパターンを作成する場合を除き、あまり意味がないからです。
次に2つ目の点について:この場合の問題は、インジケータがプロットするものの数(2本の線の場合は2つ)とオブジェクトのプロパティ(この場合は線)を混同していることです。線をプロットするためには、実際には少なくとも3つの情報を宣言する必要があります。あきらめないで...勉強し続ければ、すぐに物事はクリアになる...。😁👍
では、君のコードをいくつか見てみよう...。具体的な直し方を紹介するつもりはない(これをやると面白くなくなる......😁👍✌)が、次の事実に注目してほしい、これは重要なことだ:
あなたのコードで2つのことに印をつけたことに注目してください...それでは、グラフ上で再生されたときに何が起こっているのか見てみましょう...。
LOWタグが表示されていないという事実は、使用されているカラーパターンが#property indicator_color 2で宣言されているものであることを示しています。これは、PlotIndexSetInteger コールの使用によって動的に行われます......奇妙に思えますが......これが起こっていることなのです......。
もし、PlotIndexSetIntegerを使って行オブジェクトのデータをダイナミックに宣言したいのであれば、#property indicator_color コンパイル・コマンドをシーンから削除することができます。
さて、上の画像を見て、#property indicator_colorで使っている色と比較してほしい......これらの色を注意深く見てほしい......そうすれば、そこに何か奇妙なものがあることに気づくだろう......もう一度言うが、楽しみを失うなとは言わないが、どれも繰り返さずに、異なる色を使ってみてほしい......繰り返すと、どこに間違いがあるのか理解するのが難しくなる......。😁👍
さて、最後に細かいことを一つ:いくつかのポイントだけをプロットして、他のポイントを飛ばしていると思うのは、2つの理由が考えられます:色パターンがグラフの背景と対照的でない。グラフの背景と対照的な色を使うようにしてください。もう一つは、実際にはそうではないと思いますが、OnCalculeイベントで失敗している可能性があります。
こんにちは、ダニエル、
描画特性はMQ4のようにバッファ仕様で定義されると思っていたのですが、少なくともDRAW_COLOR...仕様では、描画特性はシーケンシャルプロット識別子で定義されるのですね。さらに、indicator_colorXプロパティは実際には2つの機能を持っており、まず色 数をカウントして設定し、次に指定された各色を適切な配列位置に設定します。2つのファイルを添付します。1つはColor Testで、現在正しく動作していますが、さらに改良が必要です。もう1つはMLADENのMACD Original2_1を少し修正したものです。 Mladenのプログラムは、2つのプロットを定義していますが、1つのカラー・インデックス・バッファしか使用しておらず、興味深いものです。
ご協力ありがとうございました。