システムの質を高める

システムの質を高める

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

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


では、早速
①のパラメータを作る方法。

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

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

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

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

書き方は、

extern int StopLoss = 50;
extern int TakeProfit = 20;
extern double lots = 0.1;
extern int avePeriod = 12;

という感じです。

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

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

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

Ask-(StopLoss*Point)

と書けば損切り値に変わります。
Point とは、このチャートの1ピプスの桁のことで、例えば、USDJPYの通貨ペアだったら、0.01になります。

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

といった感じです。

利食い値も同様に

Ask+(TakeProfit*Point)

となります。

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

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

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

といった具合です。

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

ave=iMA(NULL,0,avePeriod,0,MODE_SMA,PRICE_CLOSE,1);

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

さて、これでパラメータを設定できる環境になりました。
コンパイルして、一度、MT4で作動させてみましょう。
やり方は、使い方を覚えるという記事の中で紹介しましたね。

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


続いて②の売買制限を設ける方法ですが、
今回は、一つのバーの中では、1回しか注文を出さないという制限を付け加えましょう。
ここで、バーとは、ロウソク足の一本一本のことで、実は内部的に一本一本に番号がついています。それを引き出すのが Bars という変数です。

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

まずは、バーの番号を記憶させる変数を nowbar としておきましょうか。
これを、パラメータを設置した下あたりに宣言します。

int nowbar;

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

この変数に、取引したときのバーの番号を記憶させましょう。
やり方は、OrderSend 文の下の段に

nowbar = Bars;

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

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

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

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

とするのです。 != はノットイコールの意味です。
これは、
nowbar が Bars と同じでない時、かつ、1本前の終値が ave より大きい時、
という意味です。

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


③の他の邪魔をしないようにするには、このシステム特有の暗号を作ってあげましょう。
これは、OrderSend のマジックナンバーを使います。

まずは、ポジション無しの場合に使った
if(OrdersTotal()<1) の代わりに

OrdersTotal()のなかで、マジックナンバーが 10 のものがあればそのインデックスを、変数 CurrentPosition に代入する
というプログラムを書き、代入されなかった場合は、ポジション無しとみなす、といった文にしていきましょう。

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

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)

と書いてあげましょう。

さらに、ポジション有りの場合のOrderSelect のインデックスの部分には、
0 の代わりに
CurrentPosition

と入力しましょう。

これで、このシステム特有のマジックナンバー 10 だけを選んで取引できるようになりました。コンパイルを忘れずにしましょう。
int init() や int deinit() は今のところ使わないので消しても大丈夫です。
全体をコピペしてみます。

//+------------------------------------------------------------------+
//| HeikinSample.mq4 |
//| SAMURAI |
//| http://samuraifx.seesaa.net/ |
//+------------------------------------------------------------------+
#property copyright "SAMURAI"
#property link "http://samuraifx.seesaa.net/"
//パラメータ用の変数
extern int StopLoss =40;
extern int TakeProfit = 20;
extern double lots = 0.1;
extern int avePeriod=12;
//記憶用の変数
int nowbar;

//+------------------------------------------------------------------+
//| expert start function |
//+------------------------------------------------------------------+
int start()
{
//----
//変数の宣言
double ave ;
int cnt, CurrentPosition = -1 ;

//移動平均値の算出
ave=iMA(NULL,0,avePeriod,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]>ave )
{
//ポジションを取る。
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]<ave)
{
//ポジション決済
OrderClose(OrderTicket(),OrderLots(),Bid,3,Green);
}
}
//----
return(0);
}
//+------------------------------------------------------------------+

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

トラックバック(0)

このエントリーのトラックバックURL:
http://www.dr-ea.com/base/mt-tb.cgi/10

コメントを投稿する






画像の中に見える文字を入力してください。

Captchaの認証で入力ミスがありますと、コメントが消えてしまいますのでご注意ください。
コメント欄に(X)HTMLタグやMTタグを記述される場合、「<」は「&lt;」、「>」は「&gt;」と入力してください。