見出し画像

(MQL4)グリッドトレードのコードを書いてみるよ(1)


ソフト上で変更できるようにしよう

 コード上のそのままの数字(「マジックナンバー(固定値)」と言います。取引で使うマジックナンバーと同じ言葉で違う意味なのがややこしい)では実使用できませんので、MT4上で変更できるようにしましょう。

(1)取引コメント
 変更する必要はありません。ただ、仕様を変えて取引したときに「ああ、この仕様の時にエントリーした取引だ」と分かるようにすると取引を振り返ったときに助かったりします。

(2)マジックナンバー
 このマジックナンバーは「固定値」という上の意味ではなく、取引(エントリー)ごとにつけられる番号です。識別用なので、初期は変えない方が良いかと思います。 他のEAと同じ口座で使おうとするときは、そのEAと異なったマジックナンバーにする必要があります。その時以外は変更する必要ナシです。

(3)スリッページ
 前回説明の通りですが、言い換えると利確幅が小さいとこのスリッページが意外に響きます。かと言って0とかにすると約定しなくなったりするんですよね。あまりいじることのない数字かも。

(4)取引上の値(レートとか)
 これを変えられるようにするのが今回の主な目的です。ここはしっかりやっていきます。次の段で改良しましょう。

取引上の値を変えられるようにする

実稼働そっちのけでずっと遊べるw

 (4)についてもう少し。
グリッド幅と利確幅、ストップロス幅を前回設定しました。この各々の幅はSELL側、BUY側で同じで良いと思います?

 FXをやっていると、通貨ペアによるとは思いますがチャートの上昇は緩やかで長期間、下降が急降下で短期間、というように異なった動きをすることってないですか。 グリッドトレードでもそういった動きの違いに対応できるようにしたほうが良さそう、というのが別設定できるようにしたいと思ったきっかけです。まあそれが事実かどうかは意見が分かれるところでしょう。ユーザーサイドで変更できることが多いほうが、稼働させて楽しいしね。理由としてはそっちが大きいかも。

 さて、SELL、BUY側個別に設定できるようにしましょう。結果的に同じ値になるかもしれませんが、それは検討の結果ということで。

まだデモトレード推奨

 以下で変更後の全文を示します。まずはデモトレードで挙動を確認しましょう。

ここまでのコードを公開するよ

 いってみよー!

//+--------------------------------------------------------------------+
//|												GRID_TRADE_2024_2 .mq4 |
//|																	   |
//| マジックナンバー(固有値)をinput関数で指定できるように				|
//||
//+------------------------------------------------------------------+
#property strict
#property copyright	"MAME_Tak Hg"
#property link		""
#property version 	"1.1"

input string ea_comment = "GRID_TRADE_2024";// 取引欄に記載されるコメント
input int MAGIC_NO		= 2024021611; 		// マジックナンバー
input double Lots		=0.1;  				//取引ロット

input double sellupperprice = 1.3825; // SELL側上限レート
input double selllowerprice = 1.3581; // 同下限レート
input double buyupperprice = 1.3497; // BUY側上限レート
input double buylowerprice = 1.3255; // 同下限レート

input double sell_trappoints = 250; // SELL側のグリッド幅(1point=0.1pip)
input double sell_takeprofit = 200; // SELL側の利確幅(1point=0.1pip)
input double sell_Stoploss = 3000; // SELL側のストップロス幅(1point=0.1pip)

input double buy_trappoints = 250; // BUY側のグリッド幅(1point=0.1pip)
input double buy_takeprofit = 200; // BUY側の利確幅(1point=0.1pip)
input double buy_Stoploss = 3000; // BUY側のストップロス幅(1point=0.1pip)

double FirstBuyPrice;
double FirstSellPrice;

//+------------------------------------------------------------------+
void OnTick(void){
   int cnt; 	// forループ用カウンタ変数
   int ticket; 	// チケットNo.
   int total;	// オーダー済注文数

   total = OrdersTotal();
   
   // エントリーがまだないとき
   if ( total < 1 ){

      if ( Ask < buyupperprice && Ask > buylowerprice ){
        
         ticket = OrderSend( _Symbol,OP_BUY,Lots,Ask,5,buy_Stoploss,Ask+buy_takeprofit*_Point,ea_comment,MAGIC_NO,0,clrBlue);
         if(ticket>0){
           
            FirstBuyPrice = Ask; 
            if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
               Print("BUY order opened : ",OrderOpenPrice());
           }
         else
            Print("Error opening BUY order : ",GetLastError());
         return;
        }
      if ( Bid < sellupperprice && Bid > selllowerprice ){
        
         ticket = OrderSend( _Symbol,OP_SELL,Lots,Bid,5,sell_Stoploss,Bid-sell_takeprofit*_Point,ea_comment,MAGIC_NO,0,clrRed);
         if(ticket>0){
           
            FirstSellPrice = Bid;
            if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
               Print("SELL order opened : ",OrderOpenPrice());
           }
         else
            Print("Error opening SELL order : ",GetLastError());
         return;
         }
      }
   
   // エントリーがある場合

   for ( cnt=0; cnt < total; cnt ++ ){
     
      if(!OrderSelect(cnt,SELECT_BY_POS,MODE_TRADES))
         continue;
         
      if(OrderType()<=OP_SELL && OrderSymbol()==_Symbol){
      
         if(OrderType()==OP_BUY){
         
            if(Ask < FirstBuyPrice-buy_trappoints*total*_Point)
              {
               ticket = OrderSend( _Symbol,OP_BUY,Lots,Ask,5,buy_Stoploss,Ask+buy_takeprofit*_Point,ea_comment,MAGIC_NO,0,clrBlue);
               if(ticket > 1)
                 {
                  if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
                     Print("BUY order opened :",OrderOpenPrice());
                  else Print("Error opening BUY order :",GetLastError());
                  return;
                 }
              }
           }

         if(OrderType()==OP_SELL)
           {
            if(Bid > FirstSellPrice+sell_trappoints*total*_Point)
              {
               ticket = OrderSend(_Symbol,OP_SELL,Lots,Bid,5,sell_Stoploss,Bid-sell_takeprofit*_Point,ea_comment,MAGIC_NO,0,clrRed);
               if(ticket > 1)
                 {
                  if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
                     Print("SELL order opened :",OrderOpenPrice());
                  else Print("Error opening SELL order :",GetLastError());
                     return;
                 }
              }
           }
    	}
	}
}

 どうでしょうか。コンパイルできました?

 input関数を使用すると、チャートに適用するとソフト上で変更可能になります。今回でより実用的になりましたが、それぞれの初期値の妥当性については現状、ユーザーサイドで考える必要があります。

 

その手助けになるのがストラテジーテスターの利用です。ストラテジーテスターによる大まかな妥当性の確認 → デモトレードによるフォワードテスト → 実運用 という流れです。

トレード前の全ティックでの確認は必須

今回のコードで実運用できるの?

 そう書くからには、そうです。実運用可能です。
しかしながら、先回お伝えしたとおり、まだ不安定な部分があります(注文周りなど)。また、エントリー幅の設定によっては挙動がおかしくなります(これについては、デモトレードで確認しながら進めれば回避可能です)。

 次回からはそのあたりを具体的に改良しながら安全に運用できるEAを作っていきたいと思います。

この記事が気に入ったらサポートをしてみませんか?