MetaTrader 4 プログラム中級編

リミットとストップロスを計算で設定する




 今回は「リミットとストップロスを計算で設定する」についてお話したいと思います。


 よくあるシステムはリミットとストップロスを最初に設定しておけば、ポジションを取得した後に毎回同じリミットとストップロスを設定してくれます。今回は、そのリミットとストップロスを毎回違う値で設定するような方法を紹介します。
毎回同じリミットとストップロスにするのではなく、違った値で設定することが可能になります。

サンプルプログラムはこちらです。
http://jidoubaibai.com/Samples/Sample%20TPSL2.mq4


サンプルプログラムの使い方は、こちらで説明しています。
http://jidoubaibai.com/burogu11.html




 今回はレートとボリンジャーバンドの中央線のクロスでポジションを取得し、TPSLはボリンジャーバンドの±2σの位置に設定してみます。 ボリンジャーバンドの中央線は移動平均線なので、ソース内の関数ではMAとのクロスで処理していますので注意してください。



 では、MetaEditorを起動して下さい。

 NameはTPSL2などにして下さい。

 では、まとめてコードを書きますので、同じようにコードを半角英数で書いていってください。



int start()
{
   //変数の宣言
   int cnt, CurrentPosition;
   int Ticket;   
   
   double BuyTP,BuySL;
   double SellTP,SellSL;
   
   
   // オーダーチェック(ポジションなどのデータ)
   CurrentPosition=-1;
   for(cnt=0;cnt < OrdersTotal();cnt++)
   {
      OrderSelect(cnt,SELECT_BY_POS);
   
      if(OrderSymbol() == Symbol()) 
      {
         CurrentPosition=cnt;
      }
   }




   // ポジションチェック ポジション無し
   if(CurrentPosition == -1)
   {   
      //もし終値がMAを上に抜けたら
      if( CrossMA(20) == 1 )      
      {
         //買いポジションを取る  
         Ticket = OrderSend(Symbol(), OP_BUY, 1, Ask, 3, 0, 0, "Buy", 0, 0, Red);
      }  
      
      //もし終値がMAを下に抜けたら
      if( CrossMA(20) == 2)     
      {
         //売りポジションを取る  
         Ticket = OrderSend(Symbol(), OP_SELL, 1, Bid, 3, 0, 0, "Sell", 0, 0, Blue);
      }  
         
           
   
   }
   // ポジション有り
   else 
   {
      
      //ポジションの選択
      OrderSelect(CurrentPosition,SELECT_BY_POS);
      
      //通貨ペアの確認
      if(Symbol() == OrderSymbol())
      {
         //もし買いポジションだったら
         if(OrderType()==OP_BUY)    
         {
            if(OrderStopLoss() == NULL || OrderTakeProfit() == NULL)
            {
          
               //TPSLの値を算出
               BuyTP = NormalizeDouble(iBands(NULL,0,20,2,0,PRICE_CLOSE,MODE_UPPER,0),Digits);
               BuySL = NormalizeDouble(iBands(NULL,0,20,2,0,PRICE_CLOSE,MODE_LOWER,0),Digits);
            
               //ストップロス更新
               OrderModify(OrderTicket(), OrderOpenPrice(), BuySL,BuyTP, 0, MediumSeaGreen);
            
            }
         }
         //もし売りポジションだったら
         else if(OrderType()==OP_SELL)
         {
            if(OrderStopLoss() == NULL || OrderTakeProfit() == NULL)
            {
          
               //TPSLの値を算出
               SellTP = NormalizeDouble(iBands(NULL,0,20,2,0,PRICE_CLOSE,MODE_LOWER,0),Digits);
               SellSL = NormalizeDouble(iBands(NULL,0,20,2,0,PRICE_CLOSE,MODE_UPPER,0),Digits);
               
               //ストップロス更新
               OrderModify(OrderTicket(), OrderOpenPrice(), SellSL,SellTP, 0, MediumSeaGreen);
            
            }
         }
      }
   }
   return(0);
}



/*------------------------------------------------------
関数名   CrossMA
内容     MAとレートのクロスを判断する関数

引数     int Kikan   MAの期間設定
         
戻り値   0:何も出来ていない 1:上抜け
         2:下抜け
-------------------------------------------------------*/
int CrossMA(int Kikan)
{
   double kakoa,gennzaia;
   double kakob,gennzaib;
     

   //一つ前の終値
   kakoa = iClose(NULL,0,1);
   //一つ前のMAの値
   kakob = iMA(NULL,0,Kikan,0,0,PRICE_CLOSE,1);

   //現在の終値
   gennzaia = iClose(NULL,0,0);
   //現在のMAの値
   gennzaib = iMA(NULL,0,Kikan,0,0,PRICE_CLOSE,0);



   //もし終値がMAを上に抜けたら
   if( kakoa < kakob && gennzaia >= gennzaib)      
   {
      return(1);
   }  
   
   //もし終値がMAを下に抜けたら
   if( kakoa > kakob && gennzaia <= gennzaib)     
   {
      return(2);
   }  


   return(0);
}

 書けましたか?


 今回は以前こちら で説明したオリジナル関数を使い、レートの終値とMAのゴールデンクロスとデッドクロスでポジションをとり、 その後にポジションを持っていて、リミットとストップロスが設定されていない場合に、 ボリンジャーバンドの位置を算出してリミットとストップロスを入れるプログラムになっています。


先ず下記のポジションを取るプログラムの説明です。

   // ポジションチェック ポジション無し
   if(CurrentPosition == -1)
   {
      //もし終値がMAを上に抜けたら
      if( CrossMA(20) == 1 )
      {
         //買いポジションを取る
         Ticket = OrderSend(Symbol(), OP_BUY, 1, Ask, 3, 0, 0, "Buy", 0, 0, Red);
      }
      
      //もし終値がMAを下に抜けたら
      if( CrossMA(20) == 2)
      {
         //売りポジションを取る
         Ticket = OrderSend(Symbol(), OP_SELL, 1, Bid, 3, 0, 0, "Sell", 0, 0, Blue);
      }


 ここでは、ポジションを持っていないとき、関数内で計算された内容で終値とMAがゴールデンクロス、 またはデッドクロスと判定された時にポジションを取るようになっています。
今回もポジション取得時にリミットとストップロスを入れていると注文がキャンセルされる仕様のブローカーに合わせて、 リミットとストップロスは0でポジションを取得しています。


次に、取得しているポジションのリミットとストップロスが0の場合にボリンジャーバンドの±2σを算出し、 その位置にリミットとストップロスを新たに設定する為のプログラムです。


   // ポジション有り
   else 
   {
      
      //ポジションの選択
      OrderSelect(CurrentPosition,SELECT_BY_POS);
      
      //通貨ペアの確認
      if(Symbol() == OrderSymbol())
      {
         //もし買いポジションだったら
         if(OrderType()==OP_BUY)    
         {
            if(OrderStopLoss() == NULL || OrderTakeProfit() == NULL)
            {
          
               //TPSLの値を算出
               BuyTP = NormalizeDouble(iBands(NULL,0,20,2,0,PRICE_CLOSE,MODE_UPPER,0),Digits);
               BuySL = NormalizeDouble(iBands(NULL,0,20,2,0,PRICE_CLOSE,MODE_LOWER,0),Digits);
            
               //ストップロス更新
               OrderModify(OrderTicket(), OrderOpenPrice(), BuySL,BuyTP, 0, MediumSeaGreen);
            
            }
         }
         //もし売りポジションだったら
         else if(OrderType()==OP_SELL)
         {
            if(OrderStopLoss() == NULL || OrderTakeProfit() == NULL)
            {
          
               //TPSLの値を算出
               SellTP = NormalizeDouble(iBands(NULL,0,20,2,0,PRICE_CLOSE,MODE_LOWER,0),Digits);
               SellSL = NormalizeDouble(iBands(NULL,0,20,2,0,PRICE_CLOSE,MODE_UPPER,0),Digits);
               
               //ストップロス更新
               OrderModify(OrderTicket(), OrderOpenPrice(), SellSL,SellTP, 0, MediumSeaGreen);
            
            }
         }
      }
   }
   return(0);
}


 今回ここで初めて登場するのはiBands関数NormalizeDouble関数です。


iBands関数(通貨ペア,タイムフレーム(時間足),期間,偏差,バンドのシフト,値を取る時間(始値、終値など),モード,シフト)

ボリンジャーバンドの数値を出す関数です。
他のインディケーターで使われる関数に似ている部分が多いので簡単に説明していきます。


 通貨ペア

 どの通過ペアなのかを表すシンボルです。
 基本的に選択された通過ペアで行うNULLを入れておけば問題ありません。


 タイムフレーム(時間足)

 時間足等のタイムフレームです。
 基本的に0を入れておけば問題ないです。
 選択されたタイムフレームで行ってくれます。


 期間

 ボリンジャーバンドの期間です。
 20期間のボリンジャーバンドにしたい場合は20と入力します。


 偏差

 ボリンジャーバンドの偏差です。
 2σのボリンジャーバンドにしたい場合は2と入力します。


 バンドのシフト

 ボリンジャーバンドをシフトする値を入れます
 ここに入力した数字の数だけ右側にシフトします。
 よく分からない場合は0と入力しておけば問題ないです。


  値を取る時間(始値、終値など)

 始値、高値、安値、終値など、どのデータを使用してボリンジャーバンドを作るかです。
 PRICE_CLOSE
 PRICE_OPEN
 PRICE_HIGH
 PRICE_LOW
 PRICE_MEDIAN
 PRICE_TYPICAL
 PRICE_WEIGHTEDの7種類あります。


 モード

 ボリンジャーバンドの上下のラインのうちどれを使うかの設定です。
 MODE_UPPER
 MODE_LOWERの2種類があります。
 MODE_UPPERが上のライン、MODE_LOWERが下のラインになります。


  シフト

 ボリンジャーバンドの時間をシフトする数値です。
 0なら現在のボリンジャーバンド、1なら一つ前の足のボリンジャーバンドのデータが入ります。
 1時間足なら、一時間前の移動平均のデータが入ります。




NormalizeDouble関数(値,位)

この関数は数字の小数点以下を第何位までにするかを制御する関数です。 この関数でボリンジャーバンドの値を通貨ペアで使用されている小数点の位に合わせています。

 

 ここに入力された値を処理します。
 今回はここでボリンジャーバンドの値を処理しています。


 

 ここに入力された数字分、小数点以下を使用します。
 2と入力すると、小数第二位までという形になります。
 今回はチャートの位と合わせるので、Digitsと入力しています。
 これにより自動的にチャートの位に合います



 プログラムの内容は、ポジションを持っている時で尚且つストップロスかリミットに0が入っていた場合、 ボリンジャーバンドの±2σの値を算出してその値にストップロスとリミットの値を変更するという内容です。
基本的な動き方は以前にこちらで説明したとおりです。



 //TPSLの値を算出
 BuyTP = NormalizeDouble(iBands(NULL,0,20,2,0,PRICE_CLOSE,MODE_UPPER,0),Digits);
 BuySL = NormalizeDouble(iBands(NULL,0,20,2,0,PRICE_CLOSE,MODE_LOWER,0),Digits);

 //ストップロス更新
 OrderModify(OrderTicket(), OrderOpenPrice(), BuySL,BuyTP, 0, MediumSeaGreen);



こちらが今回追加、または修正された内容です。


NormalizeDoubleの場所にiBands関数 が入っています。つまり、iBands関数で算出した値をチャートの小数点にあわせている形になります。それを変数に入れています

後は、OrderModify関数で、リミットとストップロスの値を先ほど算出した値で設定しています。



/*------------------------------------------------------
関数名   CrossMA
内容     MAとレートのクロスを判断する関数

引数     int Kikan   MAの期間設定
         
戻り値   0:何も出来ていない 1:上抜け
         2:下抜け
-------------------------------------------------------*/
int CrossMA(int Kikan)
{
   double kakoa,gennzaia;
   double kakob,gennzaib;
     

   //一つ前の終値
   kakoa = iClose(NULL,0,1);
   //一つ前のMAの値
   kakob = iMA(NULL,0,Kikan,0,0,PRICE_CLOSE,1);

   //現在の終値
   gennzaia = iClose(NULL,0,0);
   //現在のMAの値
   gennzaib = iMA(NULL,0,Kikan,0,0,PRICE_CLOSE,0);



   //もし終値がMAを上に抜けたら
   if( kakoa < kakob && gennzaia >= gennzaib)      
   {
      return(1);
   }  
   
   //もし終値がMAを下に抜けたら
   if( kakoa > kakob && gennzaia <= gennzaib)     
   {
      return(2);
   }  


   return(0);
}


 上記の内容はMAのオリジナル関数です。
ここでレートの終値とMAのクロスの判定を行っています。
詳しくは、オリジナル関数の作り方で説明しています。


 今回はこれで終了ですが、一点だけ注意点があります。
TPSLを計算により算出した時、稀に現在のレートに近すぎるため指値を入れることが出来ない場合がありますので注意してください。

今回のような方法で、リミットとストップロスを毎回違う値で設定することが可能になります。 いろいろと応用が出来る方法ですので、ぜひマスターしてください。



--------------------------------------注意--------------------------------------

 内容には注意を払っていますが、保障は出来ません。
 実際に運用する場合は、自己責任でお願いします。

<< MetaTrader4 Proactiveへの対応 | TOP | OrderSelectについて >>

トップページ プロフィール ブログ リンク オーダーシステム 利用規約 問い合わせ