English Русский 中文 Español Deutsch Português 한국어 Français Italiano Türkçe
標準ライブラリクラスを使ってオリジナルのMarket Watchを作成します。

標準ライブラリクラスを使ってオリジナルのMarket Watchを作成します。

MetaTrader 5 | 6 10月 2015, 17:35
1 227 1
Dmitriy Skub
Dmitriy Skub

はじめに

タスクの主要な目標は、MetaTrader 5クライアント端末のチャート上で任意の textual情報のアウトプットに使いやすい拡張可能なツールの作成です。たとえば、Expert Advisorの現在の設定、またはテーブルとして提供される指定された間隔中のその作業結果、トレーダーが使用する価格値やインディケータ値のテーブル、Expert Advisorトレーディングのログ。この情報はすべてEA はインディケータの動作中にチャート上で動的に表示することができるものです。それらがこのライブラリを使用します。

ライブラリ作成の基本として、 MetaTrader 5 クライアント端末の標準ライブラリクラス コレクションが使われました。最初にこれらクラスを考察し、それからタスク達成のためにそれらを拡張します。


グラフィックオブジェクトの基本クラス

興味を引かれるクラスのセットはIncludeフォルダ および Include\ChartObjectsフォルダにあります。

それは以下のファイルです。

  • Object.mqh - CObjectベースクラスを含み、その他のクラスすべてを作成します。グラフィックオブジェクトに連携しています。
  • ChartObject.mqh - おなじく CChartObject クラスを含みます。c CObjectからの派生です。これはグラフィックオブジェクトの一般的データとメソッドの機能性とカプセル化を拡張します。
  • ChartObjectsTxtControls.mqh - 数々のクラスを含みます。テキストを含みチャートに様々なグラフィックオブジェクトを表示します。(CChartObjectText 基本クラス。その後継は CChartObjectLabelCChartObjectEditCChartObjectButton

上述のクラスを細かくみていきます。


CObject: the 基本クラス

クラス記述は短いので、ここで見ます。

class CObject
{
protected:
   CObject          *m_prev;
   CObject          *m_next;

public:
                     CObject();

   CObject          *Prev()                { return(m_prev); }
   void              Prev(CObject *node)   { m_prev=node;    }
   CObject          *Next()                { return(m_next); }
   void              Next(CObject *node)   { m_next=node;    }

   virtual bool      Save(int file_handle) { return(true);   }
   virtual bool      Load(int file_handle) { return(true);   }

   virtual int       Type() const          { return(0);      }

protected:
   virtual int       Compare(const CObject *node,int mode=0) const { return(0); }
};

//+------------------------------------------------------------------+
void CObject::CObject()
{
   m_prev=NULL;
   m_next=NULL;
}

見てのとおり、このクラスは一般的目的データとメソッドだけを含んでいます。それらはチャートのアウトプットに直接連携していません。

ただし、ひとつたいへん重要なプロパティがあります。- 単リンクおよび二重リンクリストの作成に使われることが可能です。これら機能はCObject*タイプのデータフィールドCObject::m_prevCObject::m_nextと、それらの読み込み/書き込みメソッドによって提供されます。CObject::m_prev フィールドは以前のリストエレメントを参照します。一方 CObject::m_next は次のリストエレメントを参照します。後にリスト構築の詳細について述べます。

また、CObject* タイプの2つのオブジェクトを比較するメソッドがあります。 - CObject::Compare メソッドで、これはリストエレメントをソートするのに使われます。もう2つ役に立つメソッドがあります。それにより、ファイル内でデータフィールドを保存/カウントすることができます。それらは CObject::Saveメソッド そして CObject::Loadメソッドです。望む機能性を取得するために、これらメソッドは後継クラスにオーバーロードする必要があります。

CObject::Type はオブジェクトタイプ特定メソッドです。このメソッドはリスト操作のとき有用です。それは異なるタイプのオブジェクトを含みます。

CObject クラス(とそのインスタンス)には次の機能があります。

  • リスト内で近くのエレメントとの相対的位置の特定
  • オブジェクトタイプ特定
  • オブジェクトデータを保存およびロードするメソッド
  • 指定のオブジェクトと比較するメソッド

上述のメソッドはほとんどバーチャル で基本クラスには実装されません。基本クラスは物理的な意味での実プロパティを持っていません。OOPでは普通のことですが、機能性は後継クラスに実装される必要があります。


CChartObject: グラフィックオブジェクトの基本クラス

The CChartObject CObject クラスの後継。

その名前にこれが抽象的なグラフィックオブジェクトを述べるクラスだということがわかります。この抽象的オブジェクトはすでに物理的プロパティとそれらプロパティと連携するメソッドを有しています。これらプロパチは MetaTrader 5のすべてのグラフィックオブジェクトに共通です。よってそれらとこのクラスに入れることは論理的です。

ではもっと詳しくみていきます。グラフィックオブジェクトをチャートウィンドウにアッタッチするのに以下のデータを使用します。

protected:
  long       m_chart_id;    // identifier of the chart, which contains 
                               // specified graphic object (0 - current chart)
  int        m_window;      // number of chart sub-window (0 - main window)
  string     m_name;        // unique name of the object on the chart
  int        m_num_points;  // number of points for anchoring the object

実際のグラフィックオブジェクトのプロパティを指定したり読みだす前に、それをオブジェクト(クラスインスタンス)にアタッチする必要があります。これは CChartObject::Attach で行われます。後継クラスでは、チャート上のグラフィックオブジェクト作成後すぐに呼ばれます。

bool CChartObject::Attach(long chart_id,string name,int window,int points)
{
  if(ObjectFind(chart_id,name)<0)
  {
    return(false);
  }

  if(chart_id==0) chart_id=ChartID();

  m_chart_id  =chart_id;
  m_window    =window;
  m_name      =name;
  m_num_points=points;

  return(true);
}

まず、実グラフィックオブジェクトの存在を確認します。存在していれば、そのプロパティは CChartObject クラスオブジェクトの内部フィールドに格納されます。このあと、グラフィックオブジェクトのプロパティを読んだり変更したりできます。(色、位置など)

グラフィックオブジェクトのプロパティの保存/読み出しメソッドはすでにCChartObject::Saveメソッド および CChartObject::Load メソッドに実装されています。保存/読み込みの親メソッドはそれ自身のメソッドよりも先にまず後継クラスで呼ばれる必要があります。

CChartObject クラス(とそのインスタンス)には基本クラスに比べて、次のような新しいプロパティがあります。

  • クラスインスタンスを伴いチャート上で実グラフィックオブジェクトをアタッチ
  • すべてのグラフィックオブジェクトのの共通プロパティを読み出しおよび変更
  • チャートからグラフィックオブジェクトを削除
  • チャート上でグラフィックオブジェクトを移動


CChartObjectText: Text-Graphic オブジェクト用クラス

ChartObjectsTxtControls.mqhファイルに移ります。テキストを含みさまざまなグラフィックオブジェクトをチャートにアウトプットするのに作成されたクラスの記述を見つけます。基本機能を考察します。

それらの基本クラスは CChartObjectText クラスです。チャート上テキストアウトプットに関わるプロパティおよびメソッドをカプセル化します。

以下がクラス記述です。

class CChartObjectText : public CChartObject
{
public:
   double            Angle() const;
   bool              Angle(double angle);
   string            Font() const;
   bool              Font(string font);
   int               FontSize() const;
   bool              FontSize(int size);
   ENUM_ANCHOR_POINT  Anchor() const;
   bool              Anchor(ENUM_ANCHOR_POINT anchor);

   bool              Create(long chart_id,string name,int window,datetime time,double price);

   virtual int       Type() const { return(OBJ_TEXT); }

   virtual bool      Save(int file_handle);
   virtual bool      Load(int file_handle);
};

CChartObjectと比べると、それはテキストグラフィックオブジェクトのプロパティ - チャート上のテキストorientationの角度、テキストのフォント名、フォントサイズ、グラフィックオブジェクトの座標、を読み変更するメソッドを持っています。 新規メソッドが登場しました。 CChartObjectText:: Create それにより、チャート上に OBJ_TEXT タイプの実グラフィックオブジェクトを作成することができます。

それの実装は以下です。

bool CChartObjectText::Create(long chart_id,string name,int window,datetime time,double price)
{
  bool result = ObjectCreate( chart_id, name, OBJ_TEXT, window, time, price );
  if(result)
  {
    result &= Attach(chart_id, name, window, 1 );
  }

  return(result);
}

グラフィックオブジェクトをうまく作成した場合( ObjectCreateメソッドはtrueを返します。) 、 CChartObject:: Attach メソッドを呼びます。これは以前に考察済みメソッドです。

それで親クラスを比較すると、CChartObjectText は新しい機能を備えています。

  • テキスト系グラフィックオブジェクトのプロパティ読み出しおよび変更
  • チャート上にOBJ_TEXTタイプの実グラフィックオブジェクトを作成


CChartObjectLabel: 『テキストラベル』向けグラフィックオブジェクト

標準クラスの階層内、次のクラスは CChartObjectLabel クラスです。それによりチャート上に OBJ_LABEL タイプ(テキストレベル)のグラフィックオブジェクトを作成することができます。

以下がこのクラスの記述です。

class CChartObjectLabel : public CChartObjectText
{
public:
   int               X_Distance() const;
   bool              X_Distance(int X);
   int               Y_Distance() const;
   bool              Y_Distance(int Y);
   int               X_Size() const;
   int               Y_Size() const;
   ENUM_BASE_CORNER  Corner() const;
   bool              Corner(ENUM_BASE_CORNER corner);

   bool              Time(datetime time) { return(false);  }
   bool              Price(double price) { return(false);  }

   bool              Create(long chart_id,string name,int window,int X,int Y);

   virtual int       Type() const        { return(OBJ_LABEL); }

   virtual bool      Save(int file_handle);
   virtual bool      Load(int file_handle);
};

グラフィックオブジェクト OBJ_TEXTタイプ とオブジェクト OBJ_LABEL タイプの違いを知っておく必要があります。

全社は価格チャートまたはサブウィンドウのチャートでバインディングしています。後者はウィンドウまたはチャートのサブウィンドウ(ピクセル)のチャート座標上でバインディングしています。

よってOBJ_TEXTタイプオブジェクトはスクロールするとチャートと共に移動します。一方OBJ_LABEL タイプはスクロール中も留まっています。タスクによってグラフィックテキスト系オブジェクトの特定タイプを選ぶ必要があります。

親クラスと比較すると、CChartObjectLabel は以下の弁別的機能を備えています。

  • チャート座標はグラフィックオブジェクトを配置するときに使われろ
  • それによりアンカーコーナーを変更できる実際、これはグラフのウィンドウの四隅の一つに座標の始まりを割り当てている
  • クライアント端末のチャート上にOBJ_LABELタイプの実グラフィックオブジェクト作成する


CChartObjectEdit: 『インプットフィールド』 グラフィックオブジェクト用クラス

標準クラスの階層内、次のクラスは CChartObjectEdit クラスです。これは OBJ_EDIT タイプ(インプットフィールド)のグラフィックオブジェクトを作成するクラスです。

このタイプのオブジェクトは OBJ_LABEL タイプを同じ方法でチャート座標(ピクセル)を使いバインディングします。それが標準クラスと同じように CChartObjectLabel クラスから派生するのは理論的です。

class CChartObjectEdit : public CChartObjectLabel
{
public:
   bool              X_Size(int X);
   bool              Y_Size(int Y);
   color             BackColor() const;
   bool              BackColor(color new_color);
   bool              ReadOnly() const;
   bool              ReadOnly(bool flag);

   bool              Angle(double angle) { return(false);    }

   bool              Create(long chart_id,string name,int window,int X,int Y,int sizeX,int sizeY);

   virtual int       Type() const        { return(OBJ_EDIT); }

   virtual bool      Save(int file_handle);
   virtual bool      Load(int file_handle);
};

OBJ_EDIT タイプのインプットフィールドがテキストラベルと異なる点は以下です。

  • インプットフィールドには幅と高さプロパティ(スクリーンピクセルで指定された)があり、それはチャートのグラフィックオブジェクトサイズを制限します。テキストラベルのサイズは自動で調整されるので、テキスト全体を見ることができます。
  • テキスト変更を有効化/無効化するメソッドがあります。 - CChartObjectEdit:: ReadOnly
  • メソッドはグラフィックオブジェクトで占められた領域の背景色を変更するのに追加されます。
  • オブジェクトが表示されている角度は変更できません。インプットフィールドは水平方向にしか表示されません。
  • それにより、チャート上に OBJ_EDIT タイプの実グラフィックオブジェクトを作成できます。


CChartObjectButton: 『ボタン』 グラフィックオブジェクト用クラス

テクスト系グラフィックオブジェクトの階層内、もう一つ別のクラスは CChartObjectButton クラスです。このオブジェクトはボタンと呼ばれ、押下するボタン形式で、チャート上のエレメントをコントロールするため作成されます。CChartObjectEdit クラスの後継d、その機能性を受け継いでいます。

class CChartObjectButton : public CChartObjectEdit
{
public:
  bool             State() const;
  bool             State(bool state);

  virtual int       Type() const { return(OBJ_BUTTON); }

  virtual bool      Save(int file_handle);
  virtual bool      Load(int file_handle);
};

OBJ_BUTTONタイプのボタンがインプットフィールド異なる点は以下です。

  • 押されたボタンのように見えます。Windowsのダイアログで使われるものと似ています。
  • ボタン状態(押されている/押されていない)を読む/変更する新しいメソッドです。 CChartObjectButton::State.
  • それによりチャート上でOBJ_BUTTONタイプの実グラフィックオブジェクトを作成できます。


グラフィックテクスチャルオブジェクトへの基本クラスのストラクチャ全体

Standard Library クラスのストラクチャ(階層)は次のようにまとめることができます。

標準クラスの全体的ストラクチャ

図1 標準クラスの全体的ストラクチャ

CObject クラスはその他の標準クラスの基本クラスです。たとえば、CList クラスは他と同じようにリストを処理します。


標準ライブラリクラスの機能性の拡張

標準クラスの階層について軽く触れました。それはテクスト系グラフィックオブジェクト生成のため作成されます。この階層を新しいクラスで拡張します。まず、実装に必要な機能性を確定する必要があります。要件を解説します。テクスト形式の情報アウトプットを扱っているので、以下のストラクチャ形式にこの情報を提供するのは理論的です。

タイトル 情報テキスト

テキスト形式情報の表現であるスト楽者はシンプルなケースの大部分に適しています。

たとえば、シンボルパラメータのインディケータは次のようなものです。

テキスト形式情報のストラクチャ表示例

図2 テキスト形式情報のストラクチャ表示例

上記にあるようにストラクチャの情報フィールドを6個使います。空のストラクチャエレメントもある可能性があります。たとえば、図2で一番上のフィールドのタイトルが表示されていません。他のフィールドにはタイトルとテキストがあります。このインディケータは、本稿に添付のPricelInfo.mq5 ファイルにあります。


グラフィックオブジェクトの配置

考えるべき第二の点は、チャート上でグラフィックオブジェクトを配置する方法です。スクリーンで座標をピクセルで指定するメソッドを取り入れたことで、チャートの任意の位置にオブジェクトを配置することができるようになりました。

実際に複数のテキスト形式オブジェクトを異なる場所に置く必要があるとk、不便です。というのもスクリーンのすべての座標を計算する必要があるからです。その上、チャートサイズを変えたら、すべてのピクセル座標の画面上の相対位置が変わらないように再計算の必要があります。

チャートウィンドウを同じサイズの長方形(フィールド)に描き、そのような長方形を縦横の座標に割り当てたら、汎用ポジションシステムを取得することになります。それは画面解析とは別のものです。

グラフィックテクストオブジェクトを作成するとき、ユーザーは立て横方向に最大値を、そしてオブジェクトの座標はそのフィールドにパラメータとして設定することができます。適切なクラスに埋め込まれた機能性が、画面の解像度を変更すると自動でグラフィックオブジェクトの座標を調整します。この方法で座標は一度指定され、それ以上の調整を必要としません。


ユニークなオブジェクト名の自動生成

次にあがる疑問はグラフィックテキストオブジェクト名の自動生成でしょう。生成メソッドへの主要な要求は与えられたウィンドウ内でユニークな名前を取得することです。これにより、非重複名の発明の必要を気にすることなくスクリーンに十分な数のオブジェクトを配置できます。

名前の生成に以下のメソッドを提案します。(ストリング、フィールドd構成します)

日時 ミリ秒の数

日次を含めストリングの一部を入手するため、以下の呼び出しを使います。

TimeToString(TimeGMT(), TIME_DATE|TIME_MINUTES|TIME_SECONDS);

ミリ秒の数を入手するため、以下の呼び出しを使います。

DoubleToString(GetTickCount(), 0);

しかし、ミリ秒の時間を計測してもGetTickCount () 関数を2回以上連続して呼ぶ同じ値を取得します。これはオペレーティングシステムとプロセッサの内部タイマーの離散性の制限によります。これにはそのような事態を調査する追加の手法が必要です。

提案するメソッドは以下の関数に実装されます。

string GetUniqName()
{
  static uint prev_count = 0;

  uint count = GetTickCount();
  while(1)
  {
    if(prev_count == UINT_MAX)
    {
      prev_count = 0;
    }
    if(count <= prev_count)
    {
      prev_count++;
      count = prev_count;
    }
    else
    {
      prev_count = count;
    }

//  Verify that there is no object already existing with such a name:
    string name = TimeToString(TimeGMT(), TIME_DATE|TIME_MINUTES|TIME_SECONDS)+" "+DoubleToString(count, 0);
    if(ObjectFind(0, name) < 0)
    {
      return(name);
    }
  }

  return(NULL);
}

この手法の限界: 1秒に4294967295 (UINT_MAX) 以上のユニーク名は生成しません。明らかにこれは練習では十分です。万が一に備え、同じ名前のグラフィックオブジェクトの存在を確認する別の方法があります。


情報を持つストレクチャのタイトル表示 - TTitleDisplayクラス

端末画面にタイトルを表示するクラスを以下に示します。

class TTitleDisplay : public CChartObjectLabel
{
protected:
  long    chart_id;
  int     sub_window;
  long    chart_width;       // width of the chart in pixels
  long    chart_height;      // height of the chart graph in pixels
  long    chart_width_step;  // step of the coordinates grid in the horizontal direction
  long    chart_height_step; // step of the coordinates grid in the vertical direction
  int     columns_number;    // number of columns
  int     lines_number;      // number of lines
  int     curr_column;
  int     curr_row;

protected:
  void    SetParams(long chart_id, int window, int cols, int lines);// specify the object's parameters

protected:
  string  GetUniqName();    // get a unique name
  bool    Create(long chart_id, int window, int cols, int lines, int col, int row);
  void    RecalcAndRedraw();// recount the coordinates and re-draw

        
public:
  void    TTitleDisplay();  // constructor
  void    ~TTitleDisplay(); // destructor
};

グラフィックテクストオブジェクトを作成する基本メソッド

bool Create(long chart_id, int window, int _cols, int _lines, int _col, int _row);

入力パラメータの割当ては以下です。

  • chart_id - ウィンドウ識別子(0 -メインウィンドウ);
  • window - サブウィンドウ数 (0 - メイン);
  • cols - 横向き グラフィックテクストオブジェクトの最大数(行数);
  • lines -縦向きグラフィックテクストオブジェクトの最大数 (列数);
  • col - グラフィックオブジェクト水平座標の( ゼロからcols - 1へ変化)
  • row - グラフィックオブジェクト垂直座標の( ゼロからcols - 1へ変化)

メソッドTTitleDisplay:: SetParams は、画面の位置に関してオブジェクトのパラメータを計算します。

実装は以下です。

void TTitleDisplay::SetParams(long _chart_id, int _window, int _cols, int _lines)
{
  this.chart_id = _chart_id;
  this.sub_window = _window;
  this.columns_number = _cols;
  this.lines_number = _lines;

//  Specify the size of the window in pixels:
  this.chart_width = GetSystemMetrics(SM_CXFULLSCREEN);
  this.chart_height = GetSystemMetrics(SM_CYFULLSCREEN);

//  Calculate the step of the coordinates grid:
  this.chart_width_step = this.chart_width/_cols;
  this.chart_height_step = this.chart_height/_lines;
}

ここではGetSystemMetrics を使いました。WinAPI 関数が減じ表示設定を取得するために呼びます。この関数はuser32.dll Windows システムライブラリからインポートされています。

情報テキスト作成のクラスTFieldDisplay は似たように構築されています。詳細は、本稿に添付のTextDisplay.mqhライブラリにあります。


CList Class: リストのオブジェクト操作

別の標準クラスを考察します。それはわれわれの計画おn実現に必要なものです。このくらすによりオブジェクトをクラスにグループ化することができます。それは Include\Arrays\List.mqhファイルにあります。このファイルは標準 CList クラスの記述を実装をします。それは本稿で前に考察した CObject 基本クラスの後継です。それはリストのオブジェクトを操作するメソッドセットを含みます。(リストへの追加、リストからの削除、リストの任意のエレメントへのアクセス、リスト消去)

基本メソッドを考察します。

  • リストに追加
   int Add(CObject *new_node);
   int Insert(CObject *new_node,int index);

新規アイテムをリストに追加するには2つメソッドがあります。第一メソッド CList::Add によって新規エレメントnew_node をリストの終わりに追加することができます。第二メソッド CList::Insert によって新規エレメントnew_node を任意の箇所(indexによって指定された)に挿入できます。

  • リストからの削除
   bool  Delete(int index);

CList::Deleteメソッドによりエレメントを指定のindex でリストから削除できます。一方、リストから削除するのに加え、 CObject タイプのエレメントに占められたメモリが解放されます。それは CObjectタイプのエレメントに占められていました。言い換えると、オブジェクトは「物理的に」削除されます。

  • リストの任意の エレメントへのアクセス
   int       IndexOf(CObject* node);
   CObject*  GetNodeAtIndex(int index);
   CObject*  GetFirstNode();
   CObject*  GetPrevNode();
   CObject*  GetNextNode();
   CObject*  GetLastNode();

CList:: IndexOf メソッドはリスト上の特定エレメントのインデックスを返します。インデックスの数はゼロから始まります。最初のエレメントはインデックスゼロです。このメソッドは逆処理を行います。エレメントのポインタでインデックスを返します。エレメントがリストになければ -1を返します。

リスト作業に使う4個のメソッドです。CList:: GetFirstNode 前のエレメントを返します。 CList:: GetNextNode 次のエレメントを返します。 CList:: GetLastNode リスト上最後のエレメントを返します。

  • リストの消去
   void  Clear();

CList::Clear メソッドによりリストの全エレメントを消去することができます。またオブジェクトに占められているメモリを解放することができます。

これらは CList クラスの基本メソッドです。残りはMQL5 Referenceに記載があります。


TableDisplay クラス:チャート上でテキストを表示するためのテーブル作成

計画実現のために必要なものをすべて手に入れました。テキスト形式のグラフィックオブジェクトを任意のサイズのテーブルで作成できるシンプルなクラスです。

class TableDisplay : public CList
{
protected:
  long  chart_id;
  int   sub_window;

public:
  void  SetParams(long _chart_id, int _window, ENUM_BASE_CORNER _corner = CORNER_LEFT_UPPER);
  int   AddTitleObject(int _cols, int _lines, int _col, int _row, 
                      string _title, color _color, string _fontname = "Arial", int _fontsize = 8);
  int   AddFieldObject(int _cols, int _lines, int _col, int _row, 
                          color _color, string _fontname = "Arial", int _fontsize = 8);
  bool  SetColor(int _index, color _color);
  bool  SetFont(int _index, string _fontname, int _fontsize);
  bool  SetText(int _index, string _text);

public:
  void  TableDisplay();
  void  ~TableDisplay();
};

テーブルにグラフィックオブジェクトを追加する前に、パラメータの設定が必要です。char識別子、サブウィンドウインデックス、アンカーポイントです。これは TableDisplay:: SetParams メソッドを呼ぶことで行います。このあと、タイトルやテキストフィールドのすきな番号をテーブルに追加することができます。

作成したライブラリの完全なテキストは、本稿に添付の TextDisplay.mqhライブラリにあります。


3. Market Watch作成例

インディケータの形式で複数のシンボルの値を表示するテーブルの作成例を考察します。

このようにざっと見ることが必要です。

スクリーンテーブルの例

Рисунок 3. スクリーンテーブルの例

  • ステップ 1 - ライブラリをインクルードします。(インディケータのソースコードに)
#include  <TextDisplay.mqh>
  • ステップ 2 - タイトルの名前と座標を伴う配列の作成
#define  NUMBER  8
//---------------------------------------------------------------------
string  names[NUMBER]   = {"EURUSD", "GBPUSD", "AUDUSD", "NZDUSD", "USDCHF", "USDCAD", "USDJPY", "EURJPY"};
int     coord_y[NUMBER] = {2,        3,        4,        5,        6,      7,        8,       9};
座標はゼロから始まり順番になっています。
  • ステップ 3 - 表示されるテキストオブジェクトをすべて保存するための TableDisplay タイプのテーブルオブジェクトの作成
TableDisplay  Table1;
  • ステップ 4 -オブジェクトタイトルとオブジェクト情報フィールドをテーブルに追加します。
int OnInit()
{
//  Creating a table
  Table1.SetParams(0, 0);

  for(int i=0; i<NUMBER; i++)
  {
    Table1.AddFieldObject(40, 40, 3, coord_y[i], Yellow);
  }

  for(int i=0; i<NUMBER; i++)
  {
    Table1.AddTitleObject(40, 40, 1, coord_y[i], names[i]+":", White);
  }

  ChartRedraw(0);
  EventSetTimer(1);

  return(0);
}

OnInitイベントハンドラで行うのは最適です。まず、情報フィールドを追加します。 TableDisplay:: AddFieldObject メソッドを使って行います。それからタイトルを追加します;TableDisplay:: AddTitleObjectメソッドを使って行います。

追加は2つの理由により別のサイクルで実装します:まず、タイトル数は一般的に情報フィールド数と一致しません。第二に更新された情報フィールドは行でインデックスされているとき整理しやすくなっています。(この場合、ゼロから値NUMBER - 1)

  • ステップ 5 - 動的情報更新のためのコード追加

この場合、動的情報を更新することはタイマーイベントハンドラによって行われます。OnTimer ハンドラはこのイベントが与えられたインスツルメントについて価格値を受け取り、その値をチャートに表示します。

このテキストは以下です。

//---------------------------------------------------------------------
double    rates[NUMBER];
datetime  times[NUMBER];
MqlTick   tick;
//---------------------------------------------------------------------
// OnTimer event handler
//---------------------------------------------------------------------
void OnTimer()
{
  for(int i=0; i<NUMBER; i++)
  {
//  Obtain the price values:
    ResetLastError();
    if(SymbolInfoTick(names[i], tick) != true)
    {
      Table1.SetText(i,"Err "+DoubleToString(GetLastError(),0));
      Table1.SetColor(i,Yellow);
      continue;
    }

    if(tick.time>times[i])
    {
       Table1.SetText(i, DoubleToString(tick.bid, (int)(SymbolInfoInteger(names[i], SYMBOL_DIGITS))));

       if(tick.bid>rates[i])
       {
         Table1.SetColor(i, Lime);
       }
       else if(tick.bid<rates[i])
       {
         Table1.SetColor(i, Red);
       }
       else
       {
         Table1.SetColor(i, Yellow);
       }
       rates[i] = tick.bid;
       times[i] = tick.time;
    }
  }

  ChartRedraw(0);
}

サイクルの初め、指定のインスツルメントへのチックデータが読まれ、それからでおーたの適正性が確認されます。以前とティック時間が変わったら、データの不適切性を考えます。のちに以前のティックについてクオート値を分析します。

現在価格が前よりも大きければ、情報フィールドにグリーンを指定します。少なければ赤を、等しければ黄色を指定します。サイクルの終わりに価格の現在値とティック時間が保存されOnTimerイベントハンドラの呼び出し時に分析されます。

一般に動的情報の更新コードはタスク依存です。基本的にユーザーだけがこのコードのパートを実装する必要があります。図2の価格の右側にスプレッドを追加すると決めたとします。どうやってするか見ます。

するべきことは、テーブルに追加のデータフィールドを加えるだけです。

  for(int i=0; i<NUMBER; i++)
  {
    Table1.AddFieldObject(40, 40, 5, coord_y[i], Yellow);
  }

そしてコードをインクルードします。それはスプレッドの値をOnTimeイベントハンドラに更新します。

  Table1.SetText(i+NUMBER, DoubleToString((tick.ask-tick.bid)/SymbolInfoDouble(names[i], SYMBOL_POINT), 0));

結果、以下の絵を取得します。

スプレッドを伴う価格

図4 スプレッドを伴う価格

スプレッド用のインデックスフィールド の値はNUMBER (もしゼロであれば)から始まることを知らせます。

  • ステップ 6 - 作成したオブジェクトの消去
void OnDeinit(const int _reason)
{
  EventKillTimer();

//  Removing the elements of display:
  Table1.Clear();
}

ここでタイマーとテーブルが消去されます。同時にすべてのオブジェクトがまたメモリから解放されます。

このインディケータの完全なテキストは、本稿に添付の PriceList.mq5 ファイルにあります。添付はスプレッドを表示するインディケータの『改善』版を含んでいます。それはタイトル色とチャート内tテーブル位置の特定のために外部パラメータを多く持っています。


おわりに

添付のMarketWatch.mq5 (とインクルードされたMarketWatch.mqh)はトレーディングインスツルメントの基本パラメータを表示するためのインディケータをサマリテーブル形式で含んでいます。 図2に近い各シンボル、情報、が表示されています。

また、価格変動を指定の時間間隔でパーセンテージで表示しています。シンボルセット(16以下)と時間間隔はエレメントを伴うストリングでセミコロンで分離されて指定されています。本インディケータの動作結果は図5で示しています。

マーケットレビューのインディケータ

図5 Market Watchインディケータ

MetaTrader 5 クライアント端末のチャートでテキスト情報を表示する方法を考察してきました。

クライアント端末に提供されている標準ライブラリクラスを使用することで二次元テーブルの形式でテキスト情報を表現する新しい機能性を簡単に速く作成することができました。、MQL5言語のオブジェクトを基にしたアプローチはひじょうに力強いものです。

MetaQuotes Ltdによってロシア語から翻訳されました。
元の記事: https://www.mql5.com/ru/articles/179

添付されたファイル |
marketwatch.mq5 (11.51 KB)
priceinfo.mq5 (8.76 KB)
pricelist.mq5 (7.29 KB)
textdisplay.mqh (15.54 KB)
marketwatch.mqh (9.48 KB)
最後のコメント | ディスカッションに移動 (1)
ama
ama | 3 10月 2018 において 05:48

very buggy, incomplete shitty library. this will consume your precious time many.

新しいMQL4のオフラインチャート 新しいMQL4のオフラインチャート
新しいバージョンのMQL4では、履歴データの保存方法が変更され、MqlRates構造体が新たに追加されました。MqlRates構造体は、Time、Open、Low、High、Close、Volumeなどの値を保存するのに役立ちます。長年にわたってトレーダーは、オフラインチャートを作成する為にHSTファイルに自分のデータを集めて書き込む、自分のプログラムをMQL4で作成していました。各トレーダーは、以前にコンパイルされた全てのEX4ファイルが、新しいMetaTrader4ターミナルで、以前と同様に動作すると確信していることでしょう。
ファジー理論を使用しインディケータを作成する簡単な例 ファジー理論を使用しインディケータを作成する簡単な例
本稿はファイナンシャルマーケット分析にファジー理論の概念を実用的に適用することに特化しています。エンベロープインディケータ上で2つのファジールールに基づくインディケータ生成シグナルの例を提供します。作成されたインディケータは複数のインディケータバッファを使用します。7個のバッファを計算に、5個のバッファをチャート表示に、2個をカラーバッファとします。
追加バッファなしの中間計算用物価系列の平均化 追加バッファなしの中間計算用物価系列の平均化
本稿は、もっともシンプルでシングルタイプのクラスに搭載された、従来のまた独自の平均化アルゴリズムを数々取り上げます。それらはほとんどすべてといってよいほどインディケータの開発に汎用的に使用されます。提案するクラスが、カスタムインディケータおよびテクニカルインディケータの「大量」呼び出しに対する有効な代替手段になればよいと思っています。
MQL5ウィザード:プログラミングしないExpert Advisorsの作成 MQL5ウィザード:プログラミングしないExpert Advisorsの作成
プログラミングで時間を無駄にせずトレーディング戦略を試してみたいと思いませんか?MQL5ウィザードではただトレーディングシグナルを選び、トレーリングポジションと資金管理のモジュールに追加するだけです。 - それで仕事は終わりです!独自のモジュール実装または、Jobsサービスから注文します。 - そうして新しいモジュールを既存のモジュールと融合させるのです。