システムの質を高める
前回までに作ったシステムに手を加えて、実際の取引の時に使いやすいものにしていきましょう。
- パラメータを作る
- 売買制限を設ける
- 他の取引(手動での取引や他のシステムでの取引)の邪魔をしないようにする
の順にやってみます。
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日|
カテゴリー:完全自動売買


