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

プログラミング

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

この記事から数回に分けて、裁量支援ツールの作成について書いていきます。

この記事は以下のような方を主な対象としています。
  • Dialogを使ったツールを作りたい
  • 裁量支援ツールを自作したい

ツール概要

今回作成するツールの主な機能は、

  • 成行、指値(逆指値)でのエントリー機能
  • (MT5のような)StopLimitエントリ機能
  • ポジションの一括決済機能
  • ポジションのトレーリングストップ機能

です。結構盛りだくさんですね。

エントリ用の画面、決済用の画面とStopLimit注文の管理画面の3つの画面を想定しています。

※画面は詳細を詰めていく中で変わる可能性があります

今回はエントリー用のダイアログの外観を作成してきます。

画面設計

まずはエントリー用の画面の詳細を細かく設計していきます。

ダイアログにラベル、エディットボックス、ボタン、ラジオボタンを配置していきますので、それぞれどんな配置にするのか考えます。

できました。こんな感じでパーツをどこに配置するかあらかじめ決めておくと、コーディングの際に迷わなくて済みます。

プログラミング

では、実際のコードを見ていきます。

インポート

まずは、部品をインポートします。

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


これで、Dialog、Edit、Label、Buton、RadioButtonを使用する準備ができました。

メンバー定義

次に今回作成するエントリー画面用のクラスを定義します。CEntryDialogクラスをCAppDialogを継承して作成します。

class CEntryDialog : public CAppDialog{
   public:
      CEntryDialog();
      ~CEntryDialog();
      //create
      virtual bool Create(const long chart,const string name,const int subwin);
      
      //Label
      CLabel m_labelEntry;
      CLabel m_labelLots;
      CLabel m_labelTP;
      CLabel m_labelSL;
      CLabel m_labelStop;
      CLabel m_labelStopLimit;
      
      //Edit
      CEdit m_editLots;
      CEdit m_editTP;
      CEdit m_editSL;
      CEdit m_editPO;
      CEdit m_editStop;
      CEdit m_editLimit;
      
      //Button
      CButton m_btnSell;
      CButton m_btnBuy;
      
      //RadioButton
      CRadioButton m_rbtnStream;
      CRadioButton m_rbtnPending;
      CRadioButton m_rbtnStopLimit;
            
   protected:
      bool CreateLabelEntry();
      bool CreateLabelLots();
      bool CreateLabelTP();
      bool CreateLabelSL();
      bool CreateLabelStop();
      bool CreateLabelStopLimit();
      
      bool CreateRBtnStream();
      bool CreateRBtnPending();
      bool CreateRBtnStopLimit();
      
      bool CreateEditLots();
      bool CreateEditTP();
      bool CreateEditSL();
      bool CreateEditPO();
      bool CreateEditStop();
      bool CreateEditLimit();
      
      bool CreateBtnSell();
      bool CreateBtnBuy();
};

CEntryDialog::CEntryDialog(){}
CEntryDialog::~CEntryDialog(){}


ここまででメンバ変数、メンバ関数の宣言が終わりました。

ダイアログのCreate

次はダイアログのCreate関数です。

ここではダイアログ自身を作成し、各部品のCreate関数を呼び出します。

bool CEntryDialog::Create( const long chart, const string name, const int subwin){
   int x1 = 50;
   int y1 = 50;
   int x2 = 310;
   int y2 = 340;
   int i;
   string objName;
   if(!CAppDialog::Create(chart, name, subwin, x1, y1, x2, y2)) return false;
   
   if(!CreateLabelEntry()) return false;
   if(!CreateLabelLots()) return false;
   if(!CreateLabelTP()) return false;
   if(!CreateLabelSL()) return false;
   if(!CreateLabelStop()) return false;
   if(!CreateLabelStopLimit()) return false;

   if(!CreateRBtnStream()) return false;
   if(!CreateRBtnPending()) return false;
   if(!CreateRBtnStopLimit()) return false;
   
   if(!CreateEditLots()) return false;
   if(!CreateEditTP()) return false;
   if(!CreateEditSL()) return false;
   if(!CreateEditPO()) return false;
   if(!CreateEditStop()) return false;
   if(!CreateEditLimit()) return false;
   if(!CreateBtnSell()) return false;
   if(!CreateBtnBuy()) return false;


また、ここでダイアログや部品の色やフォントを変える処理を行います。

ダイアログ自体の部品は、ダイアログのコントロール自体を触ります。

その他のオブジェクトについては、オブジェクト名を指定してフォントや色を変更しています。

   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+"RadioButton_StreamLabel"){
         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+"RadioButton_PendingLabel"){
         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+"RadioButton_StopLimitLabel"){
         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 CEntryDialog::CreateLabelEntry(){
   int x1 = 5;
   int y1 = 5;
   int x2 = 60;
   int y2 = 20;
   
   if(!m_labelEntry.Create(m_chart_id, m_name+"Label_Entry", m_subwin, x1, y1, x2, y2)) return false;
   if(!m_labelEntry.Text("■エントリー")) return false;
   if(!m_labelEntry.Font("MS Pゴシック")) return false;
   if(!Add(m_labelEntry)) return false;
   
   return true;
}

bool CEntryDialog::CreateLabelLots(){
   int x1 = 15;
   int y1 = 22;
   int x2 = 80;
   int y2 = 37;
   
   if(!m_labelLots.Create(m_chart_id, m_name+"Label_Lots", m_subwin, x1, y1, x2, y2)) return false;
   if(!m_labelLots.Text("ロット数")) return false;
   if(!m_labelLots.Font("MS Pゴシック")) return false;
   if(!Add(m_labelLots)) return false;
   
   return true;
}

bool CEntryDialog::CreateLabelTP(){
   int x1 = 15;
   int y1 = 44;
   int x2 = 150;
   int y2 = 59;
   
   if(!m_labelTP.Create(m_chart_id, m_name+"Label_TP", m_subwin, x1, y1, x2, y2)) return false;
   if(!m_labelTP.Text("利益確定")) return false;
   if(!m_labelTP.Font("MS Pゴシック")) return false;
   if(!Add(m_labelTP)) return false;
   
   return true;
}

bool CEntryDialog::CreateLabelSL(){
   int x1 = 15;
   int y1 = 66;
   int x2 = 150;
   int y2 = 81;
   
   if(!m_labelSL.Create(m_chart_id, m_name+"Label_SL", m_subwin, x1, y1, x2, y2)) return false;
   if(!m_labelSL.Text("損切")) return false;
   if(!m_labelSL.Font("MS Pゴシック")) return false;
   if(!Add(m_labelSL)) return false;
   
   return true;
}

bool CEntryDialog::CreateLabelStop(){
   int x1 = 45;
   int y1 = 154;
   int x2 = 170;
   int y2 = 169;
   
   if(!m_labelStop.Create(m_chart_id, m_name+"Label_Stop", m_subwin, x1, y1, x2, y2)) return false;
   if(!m_labelStop.Text("到達価格")) return false;
   if(!m_labelStop.Font("MS Pゴシック")) return false;
   if(!Add(m_labelStop)) return false;
   
   return true;
}

bool CEntryDialog::CreateLabelStopLimit(){
   int x1 = 45;
   int y1 = 176;
   int x2 = 170;
   int y2 = 181;
   
   if(!m_labelStopLimit.Create(m_chart_id, m_name+"Label_StopLimit", m_subwin, x1, y1, x2, y2)) return false;
   if(!m_labelStopLimit.Text("エントリー価格")) return false;
   if(!m_labelStopLimit.Font("MS Pゴシック")) return false;
   if(!Add(m_labelStopLimit)) return false;
   
   return true;
}

bool CEntryDialog::CreateRBtnStream(){
   int x1 = 15;
   int y1 = 88;
   int x2 = 150;
   int y2 = 108;
   
   if(!m_rbtnStream.Create(m_chart_id, m_name+"RadioButton_Stream", m_subwin, x1, y1, x2,y2)) return false;
   if(!Add(m_rbtnStream)) return false;
   if(!m_rbtnStream.Text("成行")) return false;
   
   return true;
}

bool CEntryDialog::CreateRBtnPending(){
   int x1 = 15;
   int y1 = 110;
   int x2 = 150;
   int y2 = 130;
   
   if(!m_rbtnPending.Create(m_chart_id, m_name+"RadioButton_Pending", m_subwin, x1, y1, x2,y2)) return false;
   if(!Add(m_rbtnPending)) return false;
   if(!m_rbtnPending.Text("指値(逆指値)")) return false;
   return true;
}

bool CEntryDialog::CreateRBtnStopLimit(){
   int x1 = 15;
   int y1 = 132;
   int x2 = 150;
   int y2 = 152;
   
   if(!m_rbtnStopLimit.Create(m_chart_id, m_name+"RadioButton_StopLimit", m_subwin, x1, y1, x2,y2)) return false;
   if(!Add(m_rbtnStopLimit)) return false;
   if(!m_rbtnStopLimit.Text("StopLimit")) return false;
   return true;
}

bool CEntryDialog::CreateEditLots(){
   int x1 = 170;
   int y1 = 22;
   int x2 = 240;
   int y2 = 42;
   
   if(!m_editLots.Create(m_chart_id, m_name+"Edit_Lots", m_subwin, x1, y1, x2,y2)) return false;
   if(!Add(m_editLots)) return false;
   m_editLots.Font("Arial");
   m_editLots.FontSize(9);
   m_editLots.Text("0.1");
   return true;
}
bool CEntryDialog::CreateEditTP(){
   int x1 = 170;
   int y1 = 44;
   int x2 = 240;
   int y2 = 64;
   
   if(!m_editTP.Create(m_chart_id, m_name+"Edit_TP", m_subwin, x1, y1, x2,y2)) return false;
   if(!Add(m_editTP)) return false;
   m_editTP.Font("Arial");
   m_editTP.FontSize(9);
   return true;
}

bool CEntryDialog::CreateEditSL(){
   int x1 = 170;
   int y1 = 66;
   int x2 = 240;
   int y2 = 86;
   
   if(!m_editSL.Create(m_chart_id, m_name+"Edit_SL", m_subwin, x1, y1, x2,y2)) return false;
   if(!Add(m_editSL)) return false;
   m_editSL.Font("Arial");
   m_editSL.FontSize(9);
   return true;
}

bool CEntryDialog::CreateEditPO(){
   int x1 = 170;
   int y1 = 110;
   int x2 = 240;
   int y2 = 130;
   
   if(!m_editPO.Create(m_chart_id, m_name+"Edit_PO", m_subwin, x1, y1, x2,y2)) return false;
   if(!Add(m_editPO)) return false;
   m_editPO.Font("Arial");
   m_editPO.FontSize(9);
   return true;
}

bool CEntryDialog::CreateEditStop(){
   int x1 = 170;
   int y1 = 154;
   int x2 = 240;
   int y2 = 174;
   
   if(!m_editStop.Create(m_chart_id, m_name+"Edit_Stop", m_subwin, x1, y1, x2,y2)) return false;
   if(!Add(m_editStop)) return false;
   m_editStop.Font("Arial");
   m_editStop.FontSize(9);
   return true;
}

bool CEntryDialog::CreateEditLimit(){
   int x1 = 170;
   int y1 = 176;
   int x2 = 240;
   int y2 = 196;
   
   if(!m_editLimit.Create(m_chart_id, m_name+"Edit_Limit", m_subwin, x1, y1, x2,y2)) return false;
   if(!Add(m_editLimit)) return false;
   m_editLimit.Font("Arial");
   m_editLimit.FontSize(9);
   return true;
}

bool CEntryDialog::CreateBtnSell(){
   int x1 = 20;
   int y1 = 210;
   int x2 = 120;
   int y2 = 250;
   
   if(!m_btnSell.Create(m_chart_id, m_name+"Btn_Sell", m_subwin, x1, y1, x2,y2)) return false;
   if(!Add(m_btnSell)) return false;
   m_btnSell.Text("Sell");
   m_btnSell.FontSize(20);
   m_btnSell.ColorBackground(clrAqua);
   return true;
}

bool CEntryDialog::CreateBtnBuy(){
   int x1 = 140;
   int y1 = 210;
   int x2 = 240;
   int y2 = 250;
   
   if(!m_btnBuy.Create(m_chart_id, m_name+"Btn_Buy", m_subwin, x1, y1, x2,y2)) return false;
   if(!Add(m_btnBuy)) return false;
   m_btnBuy.Text("Buy");
   m_btnBuy.FontSize(20);
   m_btnBuy.ColorBackground(clrMagenta);
   return true;
}


先に設計した通りに部品を配置しましょう。部品の左上の座標や右上の座標を意識すると記述しやすいです。

これでダイアログの作成は完了です。

作成したダイアログ

では、実際に出来上がったダイアログを表示してみます。

元の設計通りに表示されました。

ただラジオボタンは排他処理がされていないので、現時点では3つとも押すことができます。他のボタンの動作も記述していないので押しても動作しません。

これらはの本体プログラムのOnChartEventで実装する予定です。

本記事を書くにあたって以下のページを参考にしました。興味のある方は読んでみてください。

ここまでお付き合いいただき、ありがとうございました。

次回は残りのダイアログを作る予定です。

コメント

  1. アバター ジョー より:

    こんにちは。参考にさせていただいております。

    if(objName==prefix+”RadioButton_StreamLabel”){}

    のRadioButton_StreamLabelはどこかで宣言されているのでしょうか? コード内を検索しても、ここの1箇所しかヒットしないので教えてください。

    • 返信が遅くなり申し訳ありません。
      “RadioButton_StreamLabel”は、エントリー用ダイアログの中にある
      「成行」と書かれたラベルのオブジェクト名です。
      このオブジェクトはCEntryDialog::CreateRBtnStream()の中で作成しています。

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