23/09/22追記
note購入者はDMして下されば続きが読めます!
https://note.com/iceseeds/n/nfdae2c5ac2ef
はじめに
ここでは、GUIでストップ狩りを回避するラインを実装します。
前回までの記事を理解しているのが前提です。
【MQL4 : MT4】GUI で 全決済、個別決済 を実装した EA を作る。
作成手順としては、以下の通りです。
- ComboBoxにライン作成Listを追加
- 2本のライン作成処理
- GUIを拡張(横スクロールできる予定)
- ライン情報( pips, 損益, RR )を表示
- 仕掛けに対して、ラインで決済できる処理
- 細かい修正etc...
 今回は、1 と 2 を実装します。
 既存のファイルは、ほとんど修正がありません。
 また、今後も様々な機能を追加していく予定なので、
 Errorなどを別ファイルに分けました。
 ※ネーミングセンスはありません。なるだけ分かりやすくしているつもりです!
 いろいろと初心者な為、至らない部分もありますが、宜しくお願いします。
 フォルダ構造のアドバイスなどを頂けると助かります。
- Experts/
- Sample/
- Common/
- CMD.mqh ←コマンドファイル。エラー、時間取得 ( new )
- Common.mqh ←変数ファイル? ( new )
 
- Plugin/        
- ExitCurrency.mqh
- LineOrder.mqh ←今回のメインファイルです。( new )
 
- guiwindow.mq4
- AppWindow.mqh
- Event.mqh
 
- Common/
 
- Sample/
実行結果

LineOrderを選択し、Pushをすると、2本のラインが表示されます。
Commonフォルダ
CMD.mqh
#include <stderror.mqh>    // --- 1
#include <stdlib.mqh>
class CCMD
{
   public:
      string   GetTimes();
      void     Error( string str_place );
};
string CCMD::GetTimes()    //  --- 2
{
   MqlDateTime times ;
   TimeToStruct( TimeLocal(), times );
   
   return (string)times.year + (string)times.mon + (string)times.day + (string)times.hour + (string)times.min + (string)times.sec;
}
void CCMD::Error( string str_place )   // --- 3
{
   if( GetLastError() != ERR_NO_ERROR && ERR_OBJECT_ALREADY_EXISTS )
      Alert( "Place : " + str_place + "\nErrorCode : " + (string)GetLastError() + "\nDetails : " + ErrorDescription( GetLastError() ) );
}
CMD.mqh の ソースコード詳細
1. Include文
エラーメッセージを詳しく表示させるための標準ファイルです。
#include <stderror.mqh>
#include <stdlib.mqh>
2. GetTimes関数
現在時刻を取得するための関数です。
string CCMD::GetTimes()
{
   MqlDateTime times ;
   TimeToStruct( TimeLocal(), times );
   return (string)times.year + (string)times.mon + (string)times.day + (string)times.hour + (string)times.min + (string)times.sec;
}
今回は、オブジェクトの名前に使用します。
戻り値の例「20203212213」
MqlDateTime times ;
datetime型で現在時刻を取得します。
TimeToStruct( TimeLocal(), times );
datetime型の値をMqlDateTime構造体変数に変換してます。
2. Error関数
Errorを表示させる関数です。
void CCMD::Error( string str_place )
{
   if( GetLastError() != ERR_NO_ERROR && ERR_OBJECT_ALREADY_EXISTS )
      Alert( "Place : " + str_place + "\nErrorCode : " + (string)GetLastError() + "\nDetails : " + ErrorDescription( GetLastError() ) );
}
引数で、エラー箇所を受け取ります。
if( GetLastError() != ERR_NO_ERROR && ERR_OBJECT_ALREADY_EXISTS )
不明なエラー 且つ 既に存在してるオブジェクト なら
エラー場所、エラーコード、エラー内容 を表示します。
Common.mqh
#include "../AppWindow.mqh"
#include "CMD.mqh"
#include "../Plugin/ExitCurrency.mqh"
#include "../Plugin/LineOrder.mqh"
CPanelDialog   AppWindow;
CCMD           CMD;
CExitCurrency  ExitCurrency;
CLineOrder     LineOrder;
Common.mqh の ソースコード詳細
今後追加する際は、ここにinclude文を書きこみます。
このファイルは、ためしでやってみたので、
使い勝手が悪かったら、改造するかもです。
なにかいいアイデアがあれば教えてください。
2本のラインを!
AppWindow.mqh
修正部分の周辺のみ記載します。
~略~
bool CPanelDialog::CreateCombCreate()
{
   int widths = ClientAreaWidth() / 5;
   int x1 = 0;
   int y1 = ClientAreaHeight() - 20;
   int x2 = widths * 4;
   int y2 = ClientAreaHeight();
   
   if( !m_combCreate.Create( m_chart_id, m_name + "comboCreate", m_subwin, x1, y1, x2, y2 ) ) return false;
   m_combCreate.AddItem( "All Exit", 0 );
   m_combCreate.AddItem( "This Exit", 1 );
   m_combCreate.AddItem( "Line Order", 2 );           // --- 1
   
   if( !Add( m_combCreate ) ) return false;
   
   return true;
}
~略~
AppWindo.mqh の ソースコード詳細
1. AddItem
ラインを表示するItemを追加しました。
m_combCreate.AddItem( "Line Order", 2 );
Event.mqh
修正部分の周辺のみ記載します。
#include "Common/Common.mqh"
~略~
bool CEvent::combSelect( const int id, const long lparam, const double dparam, const string sparam )
{
   if( ( StringFind( sparam, "btnComb", 4 ) != -1 ) && id == CHARTEVENT_OBJECT_CLICK ) 
   {
      switch( (int)AppWindow.m_combCreate.Value() )
      {
         case 0: // to All Exit
            if( !ExitCurrency.exit() )
               CMD.Error( "combSelect : All Exit" );
            break;
         case 1: // to This Exit
            if( !ExitCurrency.exit( Symbol() ) )
               CMD.Error( "combSelect : This Exit" );
            break;
         case 2: // to Line Order
            if( !LineOrder.lineOrder( CMD.GetTimes() ) )    // --- 2
               CMD.Error( "LineOrder" );
            break;
         default:
            Alert( "not select" );
      }
   }
   
   return true;
}
~略~
Event.mqh の ソースコード詳細
2. combBoxでのswitch文
前回同様、LineOrderを2番に設定したので、その際にLineOrderを呼び出します。
引数には、水平ラインの名前が被らない様に、現在時刻を入れてます。
if( !LineOrder.lineOrder( CMD.GetTimes() ) )
   CMD.Error( "LineOrder" );
LineOrder.mqh
今回のメインです。
このシリーズは長丁場になりそうなので、無駄なコードがあるかもしれません。
最後の修正で、綺麗にしますのでご了承ください。
class CLineOrder
{
   public:
      bool  lineOrder( string str_name );
      bool  check();
   
   private:
      bool create( string str_name );
};
/* MEMO いらないんじゃない? ....いや使いそうかも??? */ 
bool CLineOrder::lineOrder( string str_name )
{
   if( !create( str_name ) )  return false;
   
   return true;
}
bool CLineOrder::create( string str_name )      // --- 3
{
   if( !ObjectCreate( str_name + "LineOrder0", OBJ_HLINE, 0, Time[0], Close[5] ) ) return false;
   
   if( !ObjectCreate( str_name + "LineOrder1", OBJ_HLINE, 0, Time[0], Close[10] ) ) return false;
   
   
   return true;
}
/* TODO ObjectFindで、特定の文字列が含まれていたら。。。
      全Objectを検索対象にする。
*/
bool CLineOrder::check()
{
   if( ObjectFind( ChartID(), "LineOrder0" ) )  return false;
   if( ObjectFind( ChartID(), "LineOrder1" ) )  return false;
      
   return true;
}
LineOrder.mqh の ソースコード詳細
3. ObjectCreate関数
ObjectCreate関数を使って、水平ラインを作成しています。
if( !ObjectCreate( str_name + "LineOrder0", OBJ_HLINE, 0, Time[0], Close[5] ) ) return false;
if( !ObjectCreate( str_name + "LineOrder1", OBJ_HLINE, 0, Time[0], Close[10] ) ) return false;
オブジェクトの名前が被らない且つLineOrderで作ったラインだよって印を付けるために、LineOrder0,1 と追加しました。
ObjectCreate( ラインの名前, オブジェクトの種類, ウィンド, 作成位置の時間( X軸 ), 作成位置の価格( Y軸 )
水平ラインなので、作成位置の価格( Y軸 ) に適当な価格を入れてます。
さいごに
今回は、1, 2. 2本のライン作成を実装しました。
次回は、3. GUIを拡張(横スクロールできる予定 を実装します。
YoutubeでLive配信しながら作ってます。
https://www.youtube.com/channel/UCcTw_iVgpLfrep9f94KxwLg?sub_confirmation=1
チャンネル登録お願いします
Twitterでは毎日呟いています。
https://twitter.com/IceSeed_bz
フォローお願いします
お疲れ様。
