システムの質を高める

システムの質を高める

 前回までに作ったシステムに手を加えて、実際の取引の時に使いやすいものにしていきましょう。

  1. パラメータを作る
  2. 売買制限を設ける
  3. 他の取引(手動での取引や他のシステムでの取引)の邪魔をしないようにする

の順にやってみます。

1.パラメータを作る方法

パラメータとは、外部から設定できる値のことで、これを設けることでシステムに融通性が出てきます。

今回は、

  • 損切り幅
  • 利食い幅
  • ロット数
  • 移動平均の計算期間

を、設定可能にしていきましょうか。

書く場所は、#property ・・・ の下あたりに書きましょう。

書き方は、

extern int     StopLoss    = 40;
extern int     TakeProfit  = 20;
extern double  lots        = 0.1;
extern int     MaPeriod    = 12;

という感じです。

変数の宣言の前に extern を付け加えるだけです。
宣言の後に = ** と付け加えると、最初は**を入れておいてくださいといった意味になります。

さて、この変数たちをシステム内に忍ばせるわけですが、
まずはOrderSend の()内の損切り値に入れたいと思います。

その前に、パラメータで扱う変数は、『損切り幅』ですから、これを『損切り値』に変えてあげなければなりません。

Ask - (StopLoss * Point)

と書けば損切り値に変わります。
Point とは、このチャートの1ピプスの桁のことで、例えば、USDJPYの通貨ペアだったら、0.01になります。
(小数点以下3桁まで表示されている場合は、0.001になります)

これは、
買値 - ( 損切り幅 * ピプスの桁 )

といった感じです。

利食い値も同様に

Ask + (TakeProfit * Point)

となります。

ロット数はlotsのままで大丈夫そうですね。

これを、OrderSend の()内にそれぞれ入れてあげましょう。

   OrderSend(Symbol(), OP_BUY, lots, Ask, 3, Ask-(StopLoss*Point),
                      Ask+(TakeProfit*Point), "Buy", 10, 0, Blue);

といった具合です。

同じように移動平均の関数 iMA の()内にも MaPeriod を入れてあげましょうか。

   ma = iMA(NULL, 0, MaPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);

というように、10のかわりに MaPeriod を入れましょう。

さて、これでパラメータを設定できる環境になりました。

コンパイルして、一度、MT4で作動させてみましょう。
やり方は、使い方を覚えるの記事の中で紹介しましたね。

最初にプロパティウィンドウが開きました。
その中のパラメータータブをクリックすると、設定した4つのパラメータが並んでいます。
Value の欄の数字をダブルクリックするとパラメータを入力し直すことができます。

これで、システムの幅が広がったわけです。

2.売買制限を設ける方法

今回は、一つのバーの中では1回しか注文を出さないという制限を付け加えましょう。

ここで、バーとは、ロウソク足の一本一本のことです。
そして、Bars という変数は、現在あるバーの数です。

このバーの数が変化していないうちは、まだ新たにバーが現れていないということがわかります。

この条件を付け加えると、注文したバーの中で、損切りや利食いが発生したとき、次のバーが現れるまで注文をしないといった意味になります。

まずは、バーの数を記憶させる変数を nowbar としておきましょうか。

これを、パラメータを設置した下あたりに宣言します。

int nowbar;

としましょう。
これを、int start() の{}内に書いてしまうと start() の動作が終わるたびにリセットされてしまうので、記憶しておいてもらえません。
気をつけましょう。

この変数 nowbar に、取引したときのバーの数を記憶させましょう。

やり方は、OrderSend 文の下の段に

      nowbar = Bars;

と、書きます。
nowbar に現在のバーの数を代入するといった意味です。

次に、nowbar と Bars が違うときだけ取引するという条件を加えましょう。

やり方は、OrderSend 文の上のif文の()内を

   nowbar != Bars && Close[1] > ma

とするのです。

これは、
nowbar が Bars と同じでない時、かつ、1本前の終値が ma より大きい時、
という意味です。

!= はノットイコール(~ではない)の意味です。

これで一つのバーの中では、1回しか注文を出さないようになりました。

3.他の取引の邪魔をしないようにする

他の邪魔をしないようにするには、このシステム特有の暗号を作ってあげましょう。

これは、OrderSend のマジックナンバーを使います。

まずは、ポジション無しの場合に使った

   if(OrdersTotal() < 1)

の代わりに

OrdersTotal()のなかで、マジックナンバーが 10 のものがあればそのインデックスを、変数 CurrentPosition に代入する

というプログラムを書き、代入されなかった場合は、ポジション無しとみなす、といった文にしていきましょう。

ここでは、新たに cnt と CurrentPosition という変数をつくりますので、int start() の{}内の ma を宣言した下あたりに

   int cnt, CurrentPosition = -1;

と変数の宣言をしてあげましょう。

ここで、CurrentPosition = -1 としたのは、
ポジションのインデックスが 0 から始まるので、変数をそのまま宣言したときのデフォルトの 0 とカブらないようにするためです。

そして、オーダーの条件文の前に

   for(cnt = 0; cnt < OrdersTotal(); cnt++)
   {
      OrderSelect(cnt, SELECT_BY_POS);
      if(OrderMagicNumber() == 10) CurrentPosition = cnt;
   }

という文を書いてあげます。

ここで、
for(*1; *2; *3){***}
は、繰り返すときに使う構文で

*1から開始して***する。*2のうちは*3を行い、***する。また、*2のうちは*3を行い、***する。また、・・・。

という感じに繰り返していきます。

また、cnt++ とは、cnt=cnt+1 という意味で、cnt に 1 をたして、cnt に代入するといった意味です。

全体では、

cnt が 0 のとき、
0 よりポジションの合計が多いなら続けてください。
持っているポジションのうちインデックス 0 のものを選択してください。
もし、そのマジックナンバーが 10 であるならば、CurrentPosition に 0 を代入してください。
cnt に 1 を足してください。
cnt が 1 のとき、・・・

と続きます。
もし、ポジションの合計が 0 より多くない(0の)とき、{}内の処理はされないので、CurrentPosition には、何も代入されることが無く、デフォルトの -1 になるということになります。

ですので、
if(OrdersTotal() < 1) の代わりに

   if(CurrentPosition == -1)

と書いてあげましょう。
if(CurrentPosition < 0) としてもいいですね。

さらに、ポジション有りの場合のOrderSelect のインデックスの部分には、
0 の代わりに
CurrentPosition
と入力しましょう。

これで、このシステム特有のマジックナンバー 10 だけを選んで取引できるようになりました。
コンパイルを忘れずにしましょう。

int init() や int deinit() は今のところ使わないので消しても大丈夫です。

コード全体をコピペしてみます。

//+------------------------------------------------------------------+
//|                                                 HeikinSample.mq4 |
//|                                                            keiji |
//|                                  http://www.dr-ea.com/meta-blog/ |
//+------------------------------------------------------------------+
#property copyright "keiji"
#property link      "http://www.dr-ea.com/meta-blog/"

//パラメータ用の変数
extern int     StopLoss    = 40;
extern int     TakeProfit  = 20;
extern double  lots        = 0.1;
extern int     MaPeriod    = 12;

//記憶用の変数
int nowbar;

//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
{
//----
   //変数の宣言
   double ma;
   int cnt, CurrentPosition = -1 ;
   
   //移動平均値の算出  
   ma = iMA(NULL, 0, MaPeriod, 0, MODE_SMA, PRICE_CLOSE, 1);
   
   //オーダー
   for(cnt = 0; cnt > OrdersTotal(); cnt++)
   {
      OrderSelect(cnt, SELECT_BY_POS);
      if(OrderMagicNumber() == 10) CurrentPosition = cnt;
   }

   // ポジション無しの場合
   if(CurrentPosition == -1)
   {
      //もし1本前の終値が移動平均より上ならば
      if(nowbar != Bars && Close[1] > ma)
      {                          
         //ポジションを取る。
         OrderSend(Symbol(), OP_BUY, lots, Ask, 3, Ask-(StopLoss*Point), 
                                                      Ask+(TakeProfit*Point), "Buy", 10, 0, Blue);
         nowbar = Bars;
      }
   } 
   // ポジション有りの場合
   else 
   {
      //ポジションのデータを取得。
      OrderSelect(CurrentPosition, SELECT_BY_POS);
      //もし1本前の終値が移動平均より下ならば
      if(Close[1] < ma)
      {
         //ポジション決済
         OrderClose(OrderTicket(), OrderLots(), Bid, 3, Green);
      }
   }
//----
   return(0);
}
//+------------------------------------------------------------------+

こんな感じになりましたか?
今回はこのへんで。

完全自動売買への道のり

タグ

2007年10月14日|

カテゴリー:完全自動売買