どうも、てつです。
EAで自動売買プログラムを買いているときに、以前どうしても書けなくて苦労していたのが、「1つの時間足上で、売買回数を制限する」というものでした。
例えば、「4時間足一本に対して、ある条件で買い注文を実行したら、次の4時間足が出現するまで同じ買い条件が発生しても、待機させる」という時なんかに使います。
これができるようになると、4時間に一度や日足なら1日に一度、エンベロープの外にはみ出すなどして、価格が平均よりも乖離したタイミングでコツコツと買い付けしていくプログラムを組むことができます。
その書き方がやっとわかったので、この場でシェアしておきたいと思います。
ちょっと説明するのが難しくて、ごちゃごちゃになってしまっているので汗w先に要点だけ書くと、
MQLに定義済み変数として用意されているSeconds()とMinute()関数を使います。
「0秒」や「0分」でのオーダーは出さないようにOrderSend()の時のif文に条件として5分足などの場合はSeconds()>0、1時間〜4時間足の場合はMinute()>0と書いておきます。
と同時に、注文を出した時点以降の秒数なり、分数なりをSeconds()とMinute()関数で取得しておき、ティックごとにそれに「1」を掛け続けたものを「TicketTime」などと名前をつけて変数として用意しておく。
で、分や時間の単位が変わるタイミングで「0秒」や「0分」と1を掛けることになるので、TicketTimeの値がその時だけ「0」になります。
そのゼロをトリガーにして売買を制限したり、解除したりするいうものです。
うん、こうしてまとめて書いても、伝わっているかよくわかりませんが….汗。
さらに詳しく話していきます…..。
ゼロに1を掛けてもゼロという特性を利用する
プログラミングに詳しい人ならもっとスマートな書き方ができるのでしょうが、僕の場合は以下のような感じで、同じ足で注文は一度だけのプログラムを書きました。
テスト用にすぐに結果が試せる5分足で説明します。
まず、1つ目の注文約定時間を取得します。
例えばある日の8時8分に最初の注文を出す買いシグナルが発生したとします。
8時5分からはじまる5分足の上で注文が執行され、約定。
OrderSend関数の戻り値をTicket1に代入します。
Ticket1=OrderSend();
約定すると、Ticket1には注文番号が自動的に入っているので、注文のコードの下あたりに
if(Ticket1>0)
{Ticket1Time=Second();
Lock=1;
}
と買いておきます。
これで、約定した秒数以降の数字が取得できます。
(下のLock=1;というのは今はとりあえず流しておいてください、あとで出てきます。)
ここから先がミソで、
このTicket1Timeに1を掛けます。
仮に先ほどの注文の約定した時間が8時8分15秒だとしたら、
Ticket1Timeには「15」が代入されているはずです。
なので、15x1=15です。
Ticket1Time*(アスタリスクで掛けるという意味)1==15ですね。
このTiket1Timeは8時8分59秒まで、ティックが動くたびに変動します。
というのも、
if(Ticket1>0)
{Ticket1Time=Second();}
ということなので、Ticket1のポジションを解消しない限り、ティックが動くたびにひたすら現在の秒数をカウントし続けるのです。
で、8時9分0秒になったとします。
どうなるでしょうか?
そう、Ticket1Timeは0になり1を掛けるので、
Ticket1Time*1==0
ですね。
1にゼロを掛けてもゼロですからね。
足の出現タイミングで売買を制御する変数を用意する
ちょっと話が前後してしまいますが、最初のOrderSend注文の時にエンベロープの乖離率の買いシグナルなどと一緒に、
if(Seconds()>0)
の記述をしておけば、ゼロ秒時には注文を出さないので、注文が約定した時に取得するTicket1Timeの秒数は、必ず「1以上59秒以下」になるのです。
で、今回は5分足なので、プログラムの初めの方に0、5、10、15、20、25……という感じで足が出現する特定の分にだけ、買い付けを実行する「Key」と、買い付けを制限する「Lock」いう変数を用意して、記述しておきます。
if(Minute()==0)
{Key=1;Lock=0;}
if(Minute()==5)
{Key=1;Lock=0;}
if(Minute()==10)
{Key=1;Lock=0;}
……………….
という具合に55分まで、書いておきます。
すると、先ほどの場合、8時8分15秒に約定してから8時8分59秒までは、
Ticket1Time*1>0
ですが、
8時9分0秒になると、
Ticket1Time*1==0
になります。
で、Ticket1Time*1が0になったら、Lockを解除させて、Keyに0を代入させればOK。
if(Ticket1Time*1==0)
{Lock=0;Key=0;}
9分になったタイミングと同時にLockを解除しても、Keyは次の五分足が現れる8時10分0秒にならないと1にならないので、立て続けの売買を制限できるというわけです。
まとめ
まとめると、
注文した時以降の秒数や分数をSeconds()やMinute()というMQLの定義済みの変数を使って取得しておき、常に1を掛けておく。
時間が経過し、次の「0」時点で0*1==0となるので、その「0」をトリガーにして新規注文のロックを解除。
さらにロックとは別に、Keyという変数も用意しておき、最初の注文と同時にKey=0;と代入。
5分足なら5分ごと、4時間足なら4時間ごとにKey=1;とする。
秒や分は0〜59までの整数ですが、これに1を掛け続けると、0の時だけ値が「0」になるという特性を利用してみました。
ちょっとかなりわかりずらかったですかね、、今回の説明記事….汗。
この「時間足に対する注文の制限」というのは、
コツコツ分散拾い集め型のEAを作る際には必ず必要になると思います。
そもそも相場が閑散としていて、0秒にきちんとティックが動いてくれないと、いけないという弱点もあるし、分散して買うので、その分
KeyforTicket1,LockforTicket1,KeyforTicket2,LockforTicket2,KeyforTicket3,LockforTicket3……….
という感じで、実際には重複しないようにKeyもLockという変数も、それぞれの注文ごとに用意しないといけないので、プログラムの記述がかなりコピペの嵐になります…..汗w
もっとスマートな書き方知ってるぞ〜という方がいましたら、是非ご教授いただけると嬉しいです….。w