簡単そうだけど、ちょっとした工夫が必要
決済したローソク足では仕掛けない機能をご紹介します。方法は色々ありそうですが、口座履歴は参照しない方法で作りました。
ポジションに設定したSLないしTPで決済した場合を想定しています。OrderCloseを使って自前で決済する場合は、あえて記事にするほどでもないかなと思っています。
cATraderだとポジション決済イベントが用意されているのでスマートに書けるのですが、MT4だとそれが存在しないため、小細工が必要です。
//+------------------------------------------------------------------+ //| Sample.mq4 | //| Copyright (c) 2017, りゅーき | //| https://autofx100.com/ | //+------------------------------------------------------------------+ #property copyright "Copyright (c) 2017, りゅーき" #property link "https://autofx100.com/" #property version "1.0" #property strict //+------------------------------------------------------------------+ //| ライブラリ | //+------------------------------------------------------------------+ #include <stderror.mqh> #include <stdlib.mqh> #include <WinUser32.mqh> #include <Original/Application.mqh> #include <Original/Basic.mqh> #include <Original/DateAndTime.mqh> #include <Original/LotSizing.mqh> #include <Original/OrderHandle.mqh> #include <Original/OrderReliable.mqh> //+------------------------------------------------------------------+ //| 定数 | //+------------------------------------------------------------------+ //+------------------------------------------------------------------+ //| EAパラメータ設定情報 | //+------------------------------------------------------------------+ extern int MagicNumber = 20171203; //+------------------------------------------------------------------+ //| グローバル変数 | //+------------------------------------------------------------------+ // 共通 double gPipsPoint = 0.0; int gSlippage = 0; color gArrowColor[6] = {Blue, Red, Blue, Red, Blue, Red}; //BUY: Blue, SELL: Red int gSumPos = 0; datetime gOpenTimeOfClosedPosition = 0; //+------------------------------------------------------------------+ //| Expert initialization function | //+------------------------------------------------------------------+ int OnInit() { return(INIT_SUCCEEDED); } //+------------------------------------------------------------------+ //| Expert deinitialization function | //+------------------------------------------------------------------+ void OnDeinit(const int reason) { } //+------------------------------------------------------------------+ //| Expert tick function | //+------------------------------------------------------------------+ void OnTick() { // ----------------------------------------------------------------- // 仕掛けフィルター // ----------------------------------------------------------------- int sumPosL = 0; int sumPosS = 0; // ロングとショートの各合計ポジション数取得 sumPositionNumber(MagicNumber, sumPosL, sumPosS); // 決済したローソク足では仕掛けない -------------------------------- // 決済したか? if(sumPosL + sumPosS < gSumPos){ if(gOpenTimeOfClosedPosition == 0){ gOpenTimeOfClosedPosition = Time[0]; } // 現在のローソク足は決済したローソク足か? if(Time[0] == gOpenTimeOfClosedPosition){ return; }else{ // 初期化 gOpenTimeOfClosedPosition = 0; } } gSumPos = sumPosL + sumPosS; } //+------------------------------------------------------------------+ //|【関数】ロングとショートの各合計ポジション数取得 | //| | //|【引数】 IN OUT 引数名 説明 | //| --------------------------------------------------------- | //| ○ aMagic マジックナンバー | //| ○ aSumPosL ロングの合計ポジション数 | //| ○ aSumPosS ショートの合計ポジション数 | //| | //|【戻値】なし | //| | //|【備考】なし | //+------------------------------------------------------------------+ void sumPositionNumber(int aMagic, int &aSumPosL, int &aSumPosS) { aSumPosL = 0; aSumPosS = 0; for(int i = 0; i < OrdersTotal(); i++){ if(OrderSelect(i, SELECT_BY_POS) == false){ break; } if(OrderSymbol() != Symbol() || OrderMagicNumber() != aMagic){ continue; } int type = OrderType(); if(type == OP_BUY){ aSumPosL += 1; }else if(type == OP_SELL){ aSumPosS += 1; } } }
本機能に関係ある部分のみを抜粋したプログラムなので、必要に応じて加工してお使いください。
上記プログラムで最も重要なのは以下の部分です。
// 決済したローソク足では仕掛けない -------------------------------- // 決済したか? if(sumPosL + sumPosS < gSumPos){ if(gOpenTimeOfClosedPosition == 0){ gOpenTimeOfClosedPosition = Time[0]; } // 現在のローソク足は決済したローソク足か? if(Time[0] == gOpenTimeOfClosedPosition){ return; }else{ // 初期化 gOpenTimeOfClosedPosition = 0; } } gSumPos = sumPosL + sumPosS;
最初のif文は、現ティックでのポジション数と1ティック前のポジション数(gSumPos)を比較し、現ティックでのポジション数の方が少なければ、ポジションが決済されたと解釈して、以降のプログラムを実行することを意味します。
1ティック前のポジション数をグローバル変数で作成している点がポイントです。
このif文ではEAの実行よりも先に決済(ポジションに設定したSLないしTP)の判定と実行が行われるMT4の性質を使っていることに注目してください。
gOpenTimeOfClosedPositionは決済時のローソク足のオープン時間を表しています。
それが初期化されている状態なら、現在のローソク足のオープン時間をセットします。
現在のローソク足のオープン時間とgOpenTimeOfClosedPositionが一致している、つまり、現在のローソク足と決済したローソク足が同じ間は、returnで後続処理をスキップさせています。
そして、最後に現在のポジション数をgSumPosに格納して完了です。
決済イベント、実装してくれないかなぁ。