MT4用裁量支援ツール作成(2)

プログラミング

こんにちは、たかはしみのるです。

前回に引き続き、裁量支援ツールの作成について書いていきたいと思います。

前回の記事を読んでいない方は、ぜひそちらから読んでください。

今回実装するのは以下の2つです。
  • 前回作成したエントリーダイアログのラジオボタンの排他処理
  • 残り2つのダイアログ作成

この図の右2つです。

エントリーダイアログのラジオボタンの排他処理

前回、エントリーダイアログのラジオボタンの排他処理は本体プログラムで作成すると書きましたが、エントリーダイアログの中で実装することにします。

この処理は、ラジオボタン3つのうち、どれか1つがクリックされた場合、残りの2つのラジオボタンのチェックを外すことで実現できます。

EntryDialogクラスのヘッダーファイルに以下の記述を追加します。

EVENT_MAP_BEGIN( CEntryDialog )
ON_EVENT(ON_CHANGE,m_rbtnStream,OnClickRBtnStream )
ON_EVENT(ON_CHANGE,m_rbtnPending,OnClickRBtnPending )
ON_EVENT(ON_CHANGE,m_rbtnStopLimit,OnClickRBtnStopLimit )
EVENT_MAP_END(CAppDialog )

void CEntryDialog::OnClickRBtnStream(){
   m_rbtnPending.State(false);
   m_rbtnStopLimit.State(false);
}
void CEntryDialog::OnClickRBtnPending(){
   m_rbtnStream.State(false);
   m_rbtnStopLimit.State(false);
}
void CEntryDialog::OnClickRBtnStopLimit(){
   m_rbtnStream.State(false);
   m_rbtnPending.State(false);
}

これでラジオボタンが押されたときに残りのラジオボタンのチェックが外れます。

決済用ダイアログ

前回の内容を踏まえ、決済用ダイアログはサクッと作っていきます。

決済用のダイアログはこんな感じで設計しました。

これに基づいてコーディングしてきます。

特に注意点はないですが、部品にCheckBoxを用いています。

#include <Controls\Dialog.mqh>
#include <Controls\Edit.mqh>
#include <Controls\Label.mqh>
#include <Controls\Button.mqh>
#include <Controls\CheckBox.mqh>

class CExitDialog : public CAppDialog{
   public:
      CExitDialog();
      ~CExitDialog();
      
      //create
      virtual bool Create(const long chart,const string name,const int subwin);
      
   protected:
      //Label
      CLabel m_labelExit;
      CLabel m_labelTotal;
      CLabel m_labelTotalPips;
      CLabel m_labelPips1;
      CLabel m_labelPips2;
      CLabel m_labelTrailPips;
      
      CCheckBox m_checkTrail;
      CCheckBox m_checkPips;
      
      CEdit m_editTrailPips;
      
      CButton m_btnExitPair;
      CButton m_btnExitAll;
      CButton m_btnDeletePips;
      
      
      bool CreateLabelExit();
      bool CreateLabelTotal();
      bool CreateLabelTotalPips();
      bool CreateLabelPips1();
      bool CreateLabelPips2();
      bool CreateLabelTrailPips();
      
      bool CreateCheckTrail();
      bool CreateCheckPips();

      bool CreateEditTrailPips();
      
      bool CreateBtnExitPair();
      bool CreateBtnExitAll();
      bool CreateBtnDeletePips();
      
};

CExitDialog::CExitDialog(){}
CExitDialog::~CExitDialog(){}

bool CExitDialog::Create( const long chart, const string name, const int subwin){
   int x1 = 315;
   int y1 = 50;
   int x2 = 580;
   int y2 = 280;
   if(!CAppDialog::Create(chart, name, subwin, x1, y1, x2, y2)) return false;
   
   if(!CreateLabelExit()) return false;

   if(!CreateLabelTotal()) return false;
   if(!CreateLabelTotalPips()) return false;
   if(!CreateLabelPips1()) return false;

   if(!CreateLabelTrailPips()) return false;
   if(!CreateEditTrailPips()) return false;
   if(!CreateLabelPips2()) return false;
   
   if(!CreateCheckTrail()) return false;
   if(!CreateCheckPips()) return false;   
   
   if(!CreateBtnExitPair()) return false;
   if(!CreateBtnExitAll()) return false;
   if(!CreateBtnDeletePips()) return false;
   
   
   int i;
   string objName;
   string prefix=Name();
   int total=ControlsTotal();
   for(i=0;i<total;i++){
      CWnd*obj=Control(i);
      objName=obj.Name();
      if(objName==prefix+"Client"){
         CWndClient *wndclient=(CWndClient*) obj;
         wndclient.ColorBackground(clrLavender);
         ChartRedraw();
      }
      if(objName==prefix+"Caption"){
         CEdit *edit=(CEdit*) obj;
         edit.ColorBackground(clrLightSteelBlue);
         ChartRedraw();
      }
   }
   

   total = ObjectsTotal();
   for(i=0; i < total; i++){
      objName = ObjectName(i);
      if(objName==prefix+"Chk_PipsLabel"){
         ObjectSetString(m_chart_id, objName, OBJPROP_FONT, "MS Pゴシック"); 
         ObjectSetInteger(m_chart_id, objName, OBJPROP_BGCOLOR, clrLavender);
         ObjectSetInteger(m_chart_id, objName, OBJPROP_BORDER_COLOR, clrLavender);
         ChartRedraw();
      }
      if(objName==prefix+"Chk_TrailLabel"){
         ObjectSetString(m_chart_id, objName, OBJPROP_FONT, "MS Pゴシック"); 
         ObjectSetInteger(m_chart_id, objName, OBJPROP_BGCOLOR, clrLavender);
         ObjectSetInteger(m_chart_id, objName, OBJPROP_BORDER_COLOR, clrLavender);
         ChartRedraw();
      }
   }
   
   return true;
}

bool CExitDialog::CreateLabelExit(){
   int x1 = 5;
   int y1 = 5;
   int x2 = 60;
   int y2 = 20;
   
   if(!m_labelExit.Create(m_chart_id, m_name+"Label_Exit", m_subwin, x1, y1, x2, y2)) return false;
   if(!m_labelExit.Text("■決済")) return false;
   if(!m_labelExit.Font("MS Pゴシック")) return false;
   if(!Add(m_labelExit)) return false;

   return true;
}

bool CExitDialog::CreateLabelTotal(){
   int x1 = 80;
   int y1 = 27;
   int x2 = 125;
   int y2 = 51;
   
   if(!m_labelTotal.Create(m_chart_id, m_name+"Label_Total", m_subwin, x1, y1, x2, y2)) return false;
   if(!m_labelTotal.Text("Total: ")) return false;
   if(!m_labelTotal.Font("Arial")) return false;
   if(!m_labelTotal.FontSize(14)) return false;
   if(!Add(m_labelTotal)) return false;

   return true;
}

bool CExitDialog::CreateLabelTotalPips(){
   int x1 = 145;
   int y1 = 27;
   int x2 = 195;
   int y2 = 51;
   
   if(!m_labelTotalPips.Create(m_chart_id, m_name+"Label_TotalPips", m_subwin, x1, y1, x2, y2)) return false;
   if(!m_labelTotalPips.Font("Arial")) return false;
   if(!m_labelTotalPips.FontSize(14)) return false;
   if(!Add(m_labelTotalPips)) return false;

   return true;
}

bool CExitDialog::CreateLabelPips1(){
   int x1 = 195;
   int y1 = 27;
   int x2 = 225;
   int y2 = 51;
   
   if(!m_labelPips1.Create(m_chart_id, m_name+"Label_Pips1", m_subwin, x1, y1, x2, y2)) return false;
   if(!m_labelPips1.Text("pips")) return false;
   if(!m_labelPips1.Font("Arial")) return false;
   if(!m_labelPips1.FontSize(14)) return false;
   if(!Add(m_labelPips1)) return false;

   return true;
}


bool CExitDialog::CreateLabelTrailPips(){
   int x1 = 45;
   int y1 = 83;
   int x2 = 145;
   int y2 = 98;
   
   if(!m_labelTrailPips.Create(m_chart_id, m_name+"Label_TrailPips", m_subwin, x1, y1, x2, y2)) return false;
   if(!m_labelTrailPips.Text("トレーリング幅")) return false;
   if(!m_labelTrailPips.Font("MS Pゴシック")) return false;
   if(!Add(m_labelTrailPips)) return false;

   return true;
}

bool CExitDialog::CreateLabelPips2(){
   int x1 = 205;
   int y1 = 83;
   int x2 = 245;
   int y2 = 98;
   
   if(!m_labelPips2.Create(m_chart_id, m_name+"Label_Pips2", m_subwin, x1, y1, x2, y2)) return false;
   if(!m_labelPips2.Text("pips")) return false;
   if(!m_labelPips2.Font("Arial")) return false;
   if(!Add(m_labelPips2)) return false;

   return true;
}

bool CExitDialog::CreateEditTrailPips(){
   int x1 = 150;
   int y1 = 83;
   int x2 = 200;
   int y2 = 103;
   
   if(!m_editTrailPips.Create(m_chart_id, m_name+"Edit_TrailPips", m_subwin, x1, y1, x2,y2)) return false;
   if(!Add(m_editTrailPips)) return false;
   if(!m_editTrailPips.Font("Arial")) return false;
   if(!m_editTrailPips.FontSize(9)) return false;
   return true;
}

bool CExitDialog::CreateCheckTrail(){
   int x1 = 15;
   int y1 = 61;
   int x2 = 240;
   int y2 = 81;
   
   if(!m_checkTrail.Create(m_chart_id, m_name+"Chk_Trail", m_subwin, x1, y1, x2, y2)) return false;
   //if(!m_checkTrail.Text("Enable Trailing Stop")) return false;
   if(!m_checkTrail.Text("トレーリングストップ有効化")) return false;
   if(!Add(m_checkTrail)) return false;
   
   return true;
}

bool CExitDialog::CreateCheckPips(){
   int x1 = 15;
   int y1 = 158;
   int x2 = 140;
   int y2 = 178;
   
   if(!m_checkPips.Create(m_chart_id, m_name+"Chk_Pips", m_subwin, x1, y1, x2, y2)) return false;
   //if(!m_checkPips.Text("Display Pips")) return false;
   if(!m_checkPips.Text("Pips表示")) return false;
   if(!Add(m_checkPips)) return false;
   
   return true;
}

bool CExitDialog::CreateBtnExitPair(){
   int x1 = 20;
   int y1 = 113;
   int x2 = 120;
   int y2 = 143;
   
   if(!m_btnExitPair.Create(m_chart_id, m_name+"Btn_ExitPair", m_subwin, x1, y1, x2, y2)) return false;
   if(!m_btnExitPair.Text("現通貨決済")) return false;
   if(!m_btnExitPair.Font("MS Pゴシック")) return false;
   if(!m_btnExitPair.ColorBackground(clrTomato)) return false;
   if(!Add(m_btnExitPair)) return false;

   return true;
}

bool CExitDialog::CreateBtnExitAll(){
   int x1 = 140;
   int y1 = 113;
   int x2 = 240;
   int y2 = 143;
   
   if(!m_btnExitAll.Create(m_chart_id, m_name+"Btn_ExitAll", m_subwin, x1, y1, x2, y2)) return false;
   if(!m_btnExitAll.Text("全通貨決済")) return false;
   if(!m_btnExitAll.Font("MS Pゴシック")) return false;
   if(!m_btnExitAll.ColorBackground(clrTomato)) return false;   
   if(!Add(m_btnExitAll)) return false;

   return true;
}

bool CExitDialog::CreateBtnDeletePips(){
   int x1 = 140;
   int y1 = 153;
   int x2 = 240;
   int y2 = 183;
   
   if(!m_btnDeletePips.Create(m_chart_id, m_name+"Btn_DeletePips", m_subwin, x1, y1, x2, y2)) return false;
   if(!m_btnDeletePips.Text("Pips消去")) return false;
   if(!m_btnDeletePips.Font("MS Pゴシック")) return false;
   if(!m_btnDeletePips.ColorBackground(clrKhaki)) return false;   
   if(!Add(m_btnDeletePips)) return false;

   return true;
}

表示してみたものがこちら。

設計通りになっています。

予約注文管理用ダイアログ

今回作成しているツールには、MT5のStopLimit注文を疑似的に再現する機能を組み込みます。ただMT4ではStopLimit注文を行うことができないため、あらかじめ決めた値段になるまでプログラム中に注文予約という形で保持しておき、条件を達成したら指値注文を入れる形で実装します。

このため、プログラム中に保持した予約注文を管理するダイアログが必要になります。

設計はシンプルです。

中央の大きな四角はListViewです。

配置場所さえ決まれば、あまり難しいことはありません。こちらもサクッと作っていきます。

で、出来上がったのがこちらです。

#include <Controls\Dialog.mqh>
#include <Controls\Label.mqh>
#include <Controls\Button.mqh>
#include  <Controls\ListView.mqh>

class CReservedOrderDialog : public CAppDialog{
   public:
      CReservedOrderDialog();
      ~CReservedOrderDialog();
      
      //create
      virtual bool Create(const long chart,const string name,const int subwin);
      
   protected:
   
      CLabel  m_labelManageReservedOrder;
      CLabel  m_labelColumn;
      
      CListView m_listviewList;
      
      CButton m_btnCancelSelected;
      CButton m_btnCancelAll;
      
      bool CreateLabelReservedDialog();
      bool CreateLabelColumn();
      bool CreateList();
      bool CreateBtnCancel();
      bool CreateBtnCancelAll();
};
CReservedOrderDialog::CReservedOrderDialog(){};
CReservedOrderDialog::~CReservedOrderDialog(){};

bool CReservedOrderDialog::Create(const long chart,const string name,const int subwin){
   int x1 = 50;
   int y1 = 340;
   int x2 = 310;
   int y2 = 520;
   
   if(!CAppDialog::Create(chart, name, subwin, x1, y1, x2, y2)) return false;
   if(!CreateLabelReservedDialog()) return false;
   if(!CreateLabelColumn()) return false;
   if(!CreateList()) return false;
   if(!CreateBtnCancel()) return false;
   if(!CreateBtnCancelAll()) return false;
   
   int i;
   string objName;
   string prefix=Name();
   int total=ControlsTotal();
   for(i=0;i<total;i++){
      CWnd*obj=Control(i);
      objName=obj.Name();
      if(objName==prefix+"Client"){
         CWndClient *wndclient=(CWndClient*) obj;
         wndclient.ColorBackground(clrLavender);
         ChartRedraw();
      }
      if(objName==prefix+"Caption"){
         CEdit *edit=(CEdit*) obj;
         edit.ColorBackground(clrLightSteelBlue);
         ChartRedraw();
      }
   }
   return true;
}

bool CReservedOrderDialog::CreateLabelReservedDialog(){
   int x1 = 5;
   int y1 = 5;
   int x2 = 110;
   int y2 = 20;
   
   if(!m_labelManageReservedOrder.Create(m_chart_id, m_name+"Label_Reserved", m_subwin, x1, y1, x2, y2)) return false;
   if(!m_labelManageReservedOrder.Text("■予約注文管理(StopLimit)")) return false;
   if(!m_labelManageReservedOrder.Font("MS Pゴシック")) return false;
   if(!Add(m_labelManageReservedOrder)) return false;
   return true;
}

bool CReservedOrderDialog::CreateLabelColumn(){
   int x1 = 15;
   int y1 = 24;
   int x2 = 240;
   int y2 = 39;
   
   if(!m_labelColumn.Create(m_chart_id, m_name+"Label_Column", m_subwin, x1, y1, x2, y2)) return false;
   if(!m_labelColumn.Text("ロット, 注文, 到達価格, エントリー価格")) return false;
   if(!m_labelColumn.Font("MS Pゴシック")) return false;
   if(!m_labelColumn.FontSize(8)) return false;
   if(!Add(m_labelColumn)) return false;
   return true;
}

bool CReservedOrderDialog::CreateList(){
   int x1 = 15;
   int y1 = 40;
   int x2 = 240;
   int y2 = 100;
   
   if(!m_listviewList.Create(m_chart_id, m_name+"ReservedList", m_subwin, x1, y1, x2, y2)) return false;
   if(!Add(m_listviewList)) return false;   
   return true;
}

bool CReservedOrderDialog::AddItem(string str){
   if(!m_listviewList.AddItem(str)) return false;
   return true;
}

bool CReservedOrderDialog::ItemDelete(const int index){
   return m_listviewList.ItemDelete(index);
}

bool CReservedOrderDialog::ItemsClear(void){
   if(!m_listviewList.ItemsClear()) return false;
   return true;
}


bool CReservedOrderDialog::CreateBtnCancel(){
   int x1 = 20;
   int y1 = 110;
   int x2 = 120;
   int y2 = 140;
   
   if(!m_btnCancelSelected.Create(m_chart_id, m_name+"CancelSelected", m_subwin, x1, y1, x2,y2)) return false;
   if(!Add(m_btnCancelSelected)) return false;
   if(!m_btnCancelSelected.Text("選択取消")) return false;
   if(!m_btnCancelSelected.FontSize(10)) return false;
   if(!m_btnCancelSelected.Font("MS Pゴシック")) return false;
   if(!m_btnCancelSelected.ColorBackground(clrKhaki)) return false;
   
   return true;
}

bool CReservedOrderDialog::CreateBtnCancelAll(){
   int x1 = 140;
   int y1 = 110;
   int x2 = 240;
   int y2 = 140;
   
   if(!m_btnCancelAll.Create(m_chart_id, m_name+"CancelAll", m_subwin, x1, y1, x2,y2)) return false;
   if(!Add(m_btnCancelAll)) return false;
   if(!m_btnCancelAll.Text("一括取消")) return false;
   if(!m_btnCancelAll.FontSize(10)) return false;
   if(!m_btnCancelAll.Font("MS Pゴシック")) return false;
   if(!m_btnCancelAll.ColorBackground(clrTomato)) return false;
   return true;
}

出来上がったものを表示します。

こちらも設計した通りになっています。

ダイアログ作成は今回でほぼ終了です。(セッターやゲッターを追加する必要はありますが。。)

残っている作業は、成行注文、指値注文、一括決済などの具体的な機能の追加になります。みなさんの役に立ちそうな内容があれば、「プログラミング」カテゴリーで記事を書こうと思います。

特になければ、「自作ツール」カテゴリーで出来上がったものを共有したいと思っていますので、引き続きお付き合いください。

コメント

  1. アバター ひろすえ より:

    大変貴重な情報
    ありがとうございます。

    今までやりたかったことがすべてここにあり、
    大変参考になっております。

    ただ、私はC言語はわかりますが、MQL4のC++的な(そう感じてます)
    コーディングの解読には一苦労しています。

    OnInit()やOnTick()などからの呼び出し方法がわかると幸いです。
    あるいは、MQL4の新規作成から何を選んで作成すればよいかわかると幸いです。

    勝手なお願いで大変恐縮でございますが、
    お時間がある時に、ご回答いただけると幸いです。

    よろしくお願いいたします。

  2. ひろすえ様
    コメントありがとうございます。
    ここで作成したダイアログは”.mqh”というファイルに保存することになりますので、
    「インクルード(*.mqh)」を選択することになります。

    プログラム中で呼び出す場合は、
    1. mqhファイルをインクルードする
    2. 作成したクラスの変数を定義し初期化する
    というステップで呼び出すことができるようになります。

    私は過去、作成したダイアログのmqhファイルを消してしまったことがあり、
    EAやインジケーターフォルダにmqhファイルを保存していますので、
    インクルード方法が若干異なるかもしれませんが、実例を書きます。
    (他のMT4にソースファイルをコピーし忘れないようにしています)

    1. mqhファイルをインクルードする
    “EntryDialog.mqh”というmqhファイルを作成してEAと同じディレクトリに保存した場合、EAのプログラムの冒頭部分に

    #include “EntryDialog.mqh”

    と記述することでmqhファイルをインクルードすることができます。
    これでプログラム中で作成したクラスを使うことができるようになります。

    2. 作成したクラスの変数を定義し初期化する
    “CEntryDialog”クラスの変数”EntryWindow”を作成する場合、私は

    CEntryDialog *EntryWindow;

    で定義しています。(グローバル変数にしています)
    OnInit()の中で

    EntryWindow = new CEntryDialog;

    と記述することで、使えるようになります。

    もし不明な点があれば、またコメントいただけるとうれしいです。

タイトルとURLをコピーしました