簡単そうだけど、ちょっとした工夫が必要
決済したローソク足では仕掛けない機能をご紹介します。方法は色々ありそうですが、口座履歴は参照しない方法で作りました。
ポジションに設定した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に格納して完了です。
決済イベント、実装してくれないかなぁ。
