EA開発 Part3 条件分岐(if文)
前回は単純に「買って売るだけ」という簡単な自動売買プログラムを作りました。
後はこれに「オープン条件」と「クローズ条件」を加えるだけで基本的なEAは完成します。
さっそく、前回作成したEAに条件を加えてみましょう。
条件分岐(if文)
前回説明しました発注関数OrderSendに条件を加えます。
if(Hour() == 9) { OrderSend(Symbol(),OP_BUY,0.1,Ask,2,0,0,"",123456,0,clrBlue); }
if(Hour() == 9)と{ } という記号を追加しました。
これはif文という基本的な構文で、以下の様な書き方をします。
if(条件)
{
処理
}
if() の中にある「条件」が真(true) であれば「処理」をします。
真(true)は「正しい(一致している)」という意味です。
先ほどの例文の場合、 「Hour() == 9」というのが「条件」になります。
Hour()は時刻を取得する関数、== は イコール(if文では=を2つ書くことで表現)ですので、日本語にすると「現在の時刻が9時」となります。
時刻が9時であれば「処理」に書かれているOrdeSend関数を実行して発注し、9時でなければ「処理」を実行しません。(発注しません)
※Horu()で取得する時刻は「業者サーバー」の時刻です。日本時間ではありません。
if文は真(true)ではない場合の処理も書けます。
if(条件)
{
真の時の処理
}
else
{
偽の時の処理
}
elseと書いて偽(false)の処理を書くと、「条件に一致しない場合」は偽の処理を実行します。
いずれ使いますので覚えておいて下さい。
現在のポジション数を取得する
先ほど追加した文には1つ問題があります。
「9時だったら発注」という条件では1Tick毎に発注を続けてしまいますので、9時になった途端に大量の発注を実行してしまいます。
(時刻しか見ていませんので、9時00分~9時59分59秒までずっと発注を続けます)
「ポジションを持っていなければ発注する」というように書き換えてみましょう。
if(Hour() == 9 && OrdersTotal() == 0) { OrderSend(Symbol(),OP_BUY,0.1,Ask,2,0,0,"",123456,0,clrBlue); }
if文の「条件」に && OrdersTotal() == 0 を加えました。
&& は AND で「かつ」という意味になります。OrdersTotal()は現在のオーダー数のトータルが取得できますから、これで「9時 かつ オーダーが0だったら発注する」という文になります。
ちなみに、OR(または)という条件にしたい場合には || という記号を使います。
例) if( (Hour() == 9 || Horu() == 12) && OrdersTotal() == 0)
→9時または12時で、かつオーダーが0だった場合
これもよく使うので覚えておいて下さい。(普通の四則演算のように()で括ると優先されます)
※OrdersTotal()はこのEAが発注したかどうかは取れない(すべて取ってくる)ので、他にEAが稼働していると誤動作する恐れがあります。複数のEAを稼働させる場合にはこのままでは使えません。これについては今後解説予定です。
クローズ(手仕舞い)にも条件を追加してEA完成
クローズ処理にも以下のようにif文を追加します。
if(Hour() == 18 && OrdersTotal() > 0) { for(int i=0; i<=OrdersTotal()-1; i++) { if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) == false) break; OrderClose(OrderTicket(),OrderLots(),Bid,2,clrBlue); } } }
条件に「Hour() == 18 && OrdersTotal() > 0」を追加しました。
先ほどの応用ですね。「18時で、かつオーダーがあったら」クローズ処理を実行します。
新しくでてきた記号 > は一般的な不等号と同じ意味です。(例の場合、0より大きいという意味)
※一般的な不等号と同様、 < と記述すると「より小さい」という意味になります。
これでプログラムは完成です。(以下に全文を掲載します)
//+------------------------------------------------------------------+ //| ZeroCreatePart2.mq4 | //| | //| | //+------------------------------------------------------------------+ #property copyright "" #property link "" #property version "1.00" #property strict //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { //--- //--- return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { //--- } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { if(Hour() == 9 && OrdersTotal() == 0) { OrderSend(Symbol(),OP_BUY,0.1,Ask,2,0,0,"",123456,0,clrBlue); } if(Hour() == 18 && OrdersTotal() > 0) { for(int i=0; i<=OrdersTotal()-1; i++) { if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES) == false) break; OrderClose(OrderTicket(),OrderLots(),Bid,2,clrBlue); } } } //+------------------------------------------------------------------+
コンパイルしてテストしてみよう
最後にコンパイルしてバックテストしてみましょう。(コンパイルとバックテストについては前回の記事を御覧ください)
F7キーまたは上部のコンパイルボタンを押してコンパイル。下部のErrosに0 error(s)と表示されていればOKです。(warning(s)については、今は無視して下さい。)
バックテストの条件は前回と同じで構いませんが、期間だけは長めにしてください。(数ヶ月程度あればOKです)
前回は負け続けてすぐに破産していましたが、今回は勝ち負けを繰り返しています。
優位性(エッジ)は無いので負けてしまいましたが…EAっぽくなってきたのではないでしょうか。
恐らく勝率は40~50%くらいだと思います。
次回は「時刻」をパラメーターに変えて「最適化」してみましょう!
まとめ
- if文での条件分岐の書き方
- Hour()は時刻を取得(業者サーバー時間)
- OrdersTotal()は現在のオーダー数を取得
- ==はイコール。>や<は不等号。
- &&はAND条件、||はOR条件
一気に詰め込み過ぎたかな…という気もしますが、大丈夫でしょうか。もし不明な点がありましたら当記事のコメントにご質問ください。
※記事に直接関係のないコメントはご遠慮いただきますようお願い致します。
以上、初心者向け自動売買講座「自動売買システムを作ろう!ゼロから始めるEA開発Part3 条件分岐」でした。
コメント
やっと良いサイトに辿り着きました。
今EAを色々作り始めてる初心者なのですが、
OrdersTotal() == 0にするとオーダーが0の場合になりますがこれだと裁量でやってるオーダーも数えちゃいますよね?(その口座でオーダー0だった場合ですよね?)
これを違うEA、裁量でオーダーがあった場合も
稼働させるにはどこを書き換えると良いんでしょうか?
通常、EAで判断する場合には「マジックナンバーが一致するか?」と「通貨ペアが一致するか」をチェックします。
OrderSendで渡したMagicNumber(当記事では123456)とOrderMagicNumber()で取得した値が一致しているかと、稼働しているチャートの通貨ペアとOrderSymbol()が一致しているかをチェックすれば良いです。