ダイアログを使用して取引支援ツールを作る(1)

今回から何度かに渡って、MQLの標準ライブラリを使用した取引支援ツールの作成について書く。
コーディングはMQL5で行う。

以前、MT4/5のインタフェースは知っておきたいで、MT5ではいくらか有用なUIが追加されている事にほんのり触れたが、取引支援ツールの需要は以前としてあると思っている。
特に複数ポジションに対する一括操作は、MT5であっても決済しか提供されていないため、SL/TPの一括設定やドテンなどの操作、ポジション全体での建値SL設定などはかなり面倒。

MQLの標準ライブラリのパネルとダイアログを使用して、GUIの取引支援ツールの作成を目標に、どのようなコーディングが必要になるかまとめる。

ダイアログを表示する

CAppDialogを使用する。
CAppDialogは、Include¥Controls¥Dialog.mqhで定義されている。

最終的に決済などを行わせるため、EAとして作成する。

#property copyright "nisai"
#property link      "https://nisaifx.com"
#property version   "1.00"

//ダイアログをインクルード
#include <Controls/Dialog.mqh>

//ダイアログを宣言
CAppDialog dialog;

int OnInit(){
   //ダイアログを生成
   dialog.Create(
      0,         //表示させるチャート(0なら現在のチャート)
      "Dialog",  //ダイアログの名前
      0,         //表示させるウィンドウ(0ならメインウィンドウ)
      20,        //左上のX座標
      20,        //左上のY座標
      300,       //右下のX座標
      300        //右下のY座標
   );
   //ダイアログを実行
   dialog.Run();
   return(INIT_SUCCEEDED);
}

これを実行すると、チャートにダイアログが表示される。

ダイアログを見ると、”最少化”と”閉じる”のアイコンがあるが、このままではクリックしても何も起こらない。
またダイアログを移動することもできない。

OnChartEventイベントハンドラを用意して、CAppDialogのChartEvent関数にそのまま渡す。
これで、ダイアログの移動、最少化/最大化、閉じるの実行が可能になる。

#property copyright "nisai"
#property link      "https://nisaifx.com"
#property version   "1.00"

#include <Controls/Dialog.mqh>

CAppDialog dialog;

int OnInit(){
   dialog.Create(0, "Dialog", 0, 20, 20, 300, 300);
   dialog.Run();
   return(INIT_SUCCEEDED);
}

void OnChartEvent(const int id,
                  const long& lparam,
                  const double& dparam,
                  const string& sparam){
   dialog.ChartEvent(id,lparam,dparam,sparam);
}

ダイアログの構成を確認する

ダイアログを表示して、チャートのオブジェクトリストを確認すると、オブジェクトが確認できる。

CAppDialogは6つのオブジェクトによって構成されていることが分かる。
オブジェクトの先頭にある数字は、今作成したダイアログの名前として付けられたIDのようなもので、各オブジェクトにはBorderとかBackとかの名前が付いている。

プログラムでも確認してみる。
Controlsにある全てのオブジェクトの親クラスであるCWndが持つControlsTotal関数でオブジェクトの個数を取得してループさせる。
Name関数で名前を取得・表示してみる。

#property copyright "nisai"
#property link      "https://nisaifx.com"
#property version   "1.00"

#include <Controls/Dialog.mqh>

CAppDialog dialog;

int OnInit(){
   dialog.Create(0, "Dialog", 0, 20, 20, 300, 300);
   dialog.Run();
   
   //ダイアログの名前を取得
   string prefix=dialog.Name();
   Print("Dialogの名前(接頭辞):", prefix);

   //ダイアログを構成するオブジェクトの個数を取得
   int total=dialog.ControlsTotal();
   
   for(int i=0;i<total;i++){
      //オブジェクトをCWndとして取得する
      CWnd* wnd=dialog.Control(i);
      
      Print(wnd.Name());
   }
   return(INIT_SUCCEEDED);
}

void OnChartEvent(const int id,
                  const long& lparam,
                  const double& dparam,
                  const string& sparam){
   dialog.ChartEvent(id,lparam,dparam,sparam);
}

上記を実行してログを確認する。

正しく取得できた(実行する度に、Dialogの名前(接頭辞)は変更される)。
チャートでオブジェクトリストを確認して「名前」の列と比較すると、”ClientBack”が”Client”になっている以外は一致している。

それぞれのオブジェクトは以下のクラスのインスタンスになっている。
(CDialogクラス及びCAppDialogクラスで定義されているメンバー変数を確認すればわかる。)

  • Border:CPanel
  • Back:CPanel
  • Caption:CEdit
  • Close:CBmpButton
  • Client:CWndClient
  • MinMax:CBmpButton

ダイアログの色を変更する

ダイアログの色を変更したい場合は、Back、Caption、Clientの部分を変更する。
CWndのままでは色を変更するための関数が見つからないので、CWndを派生クラスにキャストする。
CPanelとCEditは親クラスであるCWndObjが提供するColorBackground関数、CWndClientは自身が持つColorBackground関数を使う。
CWndClientはCWndObjではないので、オブジェクトの名前を確認してifで分岐させる。

#property copyright "nisai"
#property link      "https://nisaifx.com"
#property version   "1.00"

#include <Controls/Dialog.mqh>

CAppDialog dialog;

int OnInit(){
   dialog.Create(0, "Dialog", 0, 20, 20, 300, 300);
   dialog.Run();
   
   string prefix=dialog.Name();
   int total=dialog.ControlsTotal();
   
   for(int i=0;i<total;i++){
      CWnd* wnd=dialog.Control(i);
      if(wnd.Name()==prefix+"Back"){
         CWndObj* back=(CWndObj*)wnd;
         back.ColorBackground(clrRed);
      }
      if(wnd.Name()==prefix+"Caption"){
         CWndObj* caption=(CWndObj*)wnd;
         caption.ColorBackground(clrYellow);
      }
      if(wnd.Name()==prefix+"Client"){
         CWndClient* client=(CWndClient*)wnd;
         client.ColorBackground(clrBlue);
      }
   }
   return(INIT_SUCCEEDED);
}

void OnChartEvent(const int id,
                  const long& lparam,
                  const double& dparam,
                  const string& sparam){
   dialog.ChartEvent(id,lparam,dparam,sparam);
}

実行してみる。

正しく(センスの無い色に)変更された。

ここまで作ったEAをチャートに適用した後、EAを削除するとチャートウィンドウまで閉じてしまう現象が起こる。
これを避けるには、OnDeinitイベントハンドラ内で、ダイアログをDestroyしてやるようにする。

#property copyright "nisai"
#property link      "https://nisaifx.com"
#property version   "1.00"

#include <Controls/Dialog.mqh>

CAppDialog dialog;

int OnInit(){
   dialog.Create(0, "Dialog", 0, 20, 20, 300, 300);
   dialog.Run();
   
   string prefix=dialog.Name();
   int total=dialog.ControlsTotal();
   
   for(int i=0;i<total;i++){
      CWnd* wnd=dialog.Control(i);
      if(wnd.Name()==prefix+"Back"){
         CWndObj* back=(CWndObj*)wnd;
         back.ColorBackground(clrRed);
      }
      if(wnd.Name()==prefix+"Caption"){
         CWndObj* caption=(CWndObj*)wnd;
         caption.ColorBackground(clrYellow);
      }
      if(wnd.Name()==prefix+"Client"){
         CWndClient* client=(CWndClient*)wnd;
         client.ColorBackground(clrBlue);
      }
   }
   return(INIT_SUCCEEDED);
}

void OnChartEvent(const int id,
                  const long& lparam,
                  const double& dparam,
                  const string& sparam){
   dialog.ChartEvent(id,lparam,dparam,sparam);
}

void OnDeinit(const int reason){
   dialog.Destroy(reason);
}

ダイアログについてはこれくらいにして、次回はボタンなどを配置していく。

2件のフィードバック

  1. MQL5で取引ダイアログを作る方法を調べてきました。
    大変参考になりますm(__)m

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

コメントする