システムトレード研究所 〜FXで完全自動売買〜

このサイトでは、FXで完全自動売買を行うために必要な情報を書いていこうと思っています。システムを自分で作りたい方、システムトレードをやってみたい方は御覧になっていって下さい。
<< 色々な決済の仕方 | main | OrderSelectについて >>
リミットとストップロスを計算で設定する
こんばんはDCです。


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

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



サンプルプログラムはこちらです。

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を計算により算出した時、稀に現在のレートに近すぎるため指値を入れることが出来ない場合がありますので注意してください。

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



システムトレード研究所〜FXで完全自動売買〜INDEXへ
自動売買システム制作のオーダーシステム|FXでオリジナルのシステムトレード

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

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


| 小松 | MetaTrader4 プログラム中級編 | 16:07 | comments(2) | - |
MT4での自動売買で検索してこのブログにやってきました。
まだ自動売買に関して知識が全くない状態ですが、入門編は非常にわかりやすいくありがたいです。
最近はあまり更新がないようですが勉強させて頂きますね。
| 爺 | 2011/08/07 4:40 AM |
>爺さん

難しい場面もあるかもしれませんが、がんばってください。
これからもなるべく分かりやすくプログラムの組み方を解説していこうと思います。
| DC | 2011/08/08 10:27 AM |









1234567
891011121314
15161718192021
22232425262728
293031    
<< October 2017 >>



このページの先頭へ