MetaTrader 4のバージョンアップにより仕様が変わってきた部分がありますので、 記事を新しい仕様で書き直しております。この注意書きが書かれていないページは 旧仕様の記事になります。旧仕様の記事でも一部を除き基本的にはシステムの制作に問題はありません。
今回の記事は、「足確定での売買」についてです。正確には次の足の始値での売買になります。
今までシグナルが成立したら即エントリーのプログラムばかりでしたが、今回は即エントリーと足が確定した時点でシグナルを判定してエントリーをパラメーターで分ける内容になります。
サンプルプログラムはこちらです。Zip圧縮していますので解凍してご利用ください。
サンプルプログラムの使い方は、以下の記事で説明しています。
足確定での売買
では、MetaEditorを起動して下さい。
NameはOpenPricesModeにして置いて下さい。
では、まとめてコードを書きますので、同じようにコードを半角英数で書いていってください。
//パラメーター input bool OpenPricesMode = true; //グローバル変数 int GlobalBar = NULL; void OnTick() { //変数の宣言 int cnt, CurrentPosition; int Ticket; int order_close = NULL; // オーダーチェック(ポジションなどのデータ) CurrentPosition=-1; for(cnt=0;cnt < OrdersTotal();cnt++) { if( OrderSelect(cnt,SELECT_BY_POS) == true ) { if(OrderSymbol() == Symbol()) { CurrentPosition=cnt; } } } //OpenPricesModeのチェック if( OpenPricesMode == false || ( GlobalBar != NULL && GlobalBar != Bars )) { // ポジションチェック ポジション無し if(CurrentPosition == -1) { //もしメインがシグナルを下から上にクロスしたら if( CrossMACD(12,26,9,OpenPricesMode) == 1 ) { //買いポジションを取る Ticket = OrderSend(Symbol(), OP_BUY, 1, Ask, 30, 0, 0, "Buy", 0, 0,clrBlue); } //もしメインがシグナルを上から下にクロスしたら if( CrossMACD(12,26,9,OpenPricesMode) == 2) { //売りポジションを取る Ticket = OrderSend(Symbol(), OP_SELL, 1, Bid, 30, 0,0, "Sell", 0, 0, clrRed); } } // ポジション有り else { //ポジションの選択 if( OrderSelect(CurrentPosition,SELECT_BY_POS) == true ) { //通貨ペアの確認 if(Symbol() == OrderSymbol()) { //もし買いポジションだったら if(OrderType()==OP_BUY) { //もしメインがシグナルを上から下にクロスしたら if( CrossMACD(12,26,9,OpenPricesMode) == 2) { //手仕舞い order_close = OrderClose(OrderTicket(),OrderLots(),Bid,30,Green); //売りポジションを取る Ticket = OrderSend(Symbol(), OP_SELL, 1, Bid, 30, 0,0, "Sell", 0, 0, clrRed); } } //もし売りポジションだったら else if(OrderType()==OP_SELL) { //もしメインがシグナルを下から上にクロスしたら if( CrossMACD(12,26,9,OpenPricesMode) == 1) { //手仕舞い order_close = OrderClose(OrderTicket(),OrderLots(),Ask,3,Green); //買いポジションを取る Ticket = OrderSend(Symbol(), OP_BUY, 1, Ask, 30, 0, 0, "Buy", 0, 0,clrBlue); } } } } } } GlobalBar = Bars; } /*------------------------------------------------------ 関数名 CrossMACD 内容 MACDのゴールデンクロスとデッドクロスを判断する関数 引数 int fast 短期EMA int slow 長期EMA int signal シグナル bool shift OpenPricesMode 戻り値 0:何も出来ていない 1:ゴールデンクロス 2:デッドクロス -------------------------------------------------------*/ int CrossMACD(int fast,int slow,int signal,bool shift) { double old_main,now_main; double old_signal,now_signal; //一つ前のMACDのメイン old_main = iMACD(NULL,0,fast,slow,signal,PRICE_CLOSE,MODE_MAIN,1+shift); //一つ前のMACDのシグナル old_signal = iMACD(NULL,0,fast,slow,signal,PRICE_CLOSE,MODE_SIGNAL,1+shift); //現在のMACDのメイン now_main = iMACD(NULL,0,fast,slow,signal,PRICE_CLOSE,MODE_MAIN,0+shift); //現在のMACDのシグナル now_signal = iMACD(NULL,0,fast,slow,signal,PRICE_CLOSE,MODE_SIGNAL,0+shift); //もしメインがシグナルを下から上にクロスしたら if( old_main < old_signal && now_main >= now_signal) { return(1); } //もしメインがシグナルを上から下にクロスしたら if( old_main > old_signal && now_main <= now_signal) { return(2); } return(0); }
書けましたか?今回はOpenPricesModeのパラメーターがfalseだとシグナルが出た瞬間に売買、trueだと足が確定した時のシグナルで判定して次の足の始値で売買という内容になっています。
前回のオリジナルの関数の作り方の内容に上記の処理を付け加えたものになります。
では、内容の説明をして行きます。
パラメーターとグローバル変数
まず、 void OnTick() の上に下記のコードを書きます。
//パラメーター input bool OpenPricesMode = true; //グローバル変数 int GlobalBar = NULL;
input bool OpenPricesMode = true; はパラメーターになります。inputをつけるとパラメーターとなり、今回の場合ですとbool型の OpenPricesMode という名前のパラメーターを制作ということになります。bool型は
trueとfalseの二種類を選択出来ます。
int GlobalBar = NULL;はグローバル変数です。グローバル変数は全ての関数の中で使えて、プログラムが一巡しても数値が初期化されません。
void OnTick()の中ですが、オリジナルの関数の作り方と同じ部分は省略します。
先に、 void OnTick() の一番最後の下記の部分ですが、
GlobalBar = Bars;
Barsは現在のバーの数を取得出来るものになります。グローバル変数のGlobalBarの中に現在のバーの数を入れています。
確定、未確定の分岐
//OpenPricesModeのチェック if( OpenPricesMode == false || ( GlobalBar != NULL && GlobalBar != Bars ) ) { }
次に少し戻って上記の部分になります。 上記のif文では、パラメーターのOpenPricesModeがfalse、もしくはGlobalBarがNULLではなく、GlobalBarがBarsの数値と異なる場合のみOKという内容になっています。Barsの値が変更されるのはバーが確定して次の足になった時になりますので、この内容で足が確定して次の足の始値の時だけif文が通るようにすることが可能です。
あとは void OnTick() の下にあるオリジナル関数のCrossMACD関数の変更についてになります。
オリジナル関数への対応
int CrossMACD(int fast,int slow,int signal,bool shift) { double old_main,now_main; double old_signal,now_signal; //一つ前のMACDのメイン old_main = iMACD(NULL,0,fast,slow,signal,PRICE_CLOSE,MODE_MAIN,1+shift); //一つ前のMACDのシグナル old_signal = iMACD(NULL,0,fast,slow,signal,PRICE_CLOSE,MODE_SIGNAL,1+shift); //現在のMACDのメイン now_main = iMACD(NULL,0,fast,slow,signal,PRICE_CLOSE,MODE_MAIN,0+shift); //現在のMACDのシグナル now_signal = iMACD(NULL,0,fast,slow,signal,PRICE_CLOSE,MODE_SIGNAL,0+shift);
引数にbool shiftを追加しました。この引数にはOpenPricesModeを入れます。使用例はCrossMACD(12,26,9,OpenPricesMode)このようになります。
このshiftの数値をiMACDのシフトの引数にいれます。falseは0、trueは1と同じ内容になりますので、
0+shiftはOpenPricesModeがfalseなら0+0で0、trueなら0+1で1になります。
1の場合調べているのは1本前のiMACDの数値です。1本前の理由ですが、足が確定してから次の足の始値でシグナルを判断しますので、現在の足を調べていると出来たばかりの始値のMACDの数値を調べることになりますので、確定していない数値を調べることになります。1本前のMACDの数値ですと、足が確定したMACDの数値になります。
足が確定前のシグナルと足が確定した時のシグナルは上記のように調べる足が異なりますので気をつけてください。またバックテストのモデルが全Tickの場合ではOpenPricesModeがfalse、trueともに大丈夫ですが、始値のみの場合はOpenPricesModeがtrueの場合しか正常に売買されなくなります。こちらも上記と同じ理由になります。
余談ですが、今回の内容でも基本的には動きますが、
//もしメインがシグナルを上から下にクロスしたら if( CrossMACD(12,26,9,OpenPricesMode) == 2) { //手仕舞い order_close = OrderClose(OrderTicket(),OrderLots(),Bid,30,Green); //売りポジションを取る Ticket = OrderSend(Symbol(), OP_SELL, 1, Bid, 30, 0,0, "Sell", 0, 0, clrRed); }
上記のドテンの処理はOpenPricesModeがtrueの場合の足確定時のみの売買の場合、1つの足で一度しか通りませんので、手仕舞いの処理の後、エントリーの処理も行っております。ただこの内容はエラーが出た場合に弱いです。クローズのオーダーが通らずにエントリーだけが行われるケースなどがあるため、シグナルの判定と実際の処理は分けたほうが良いのです。またの機会にこの処理を分ける内容を書いていきたいと思います。
今回はこれで終了です。
足の確定、未確定の処理は頻繁に使うことになると思いますので頑張って下さい。
内容には注意を払っていますが、保障は出来ません。
実際に運用する場合は、自己責任でお願いします。