ブログタイトルを「FX自動売買システム開発部」から「autoFX」に変更しました!

決済したローソク足では仕掛けない機能

簡単そうだけど、ちょっとした工夫が必要

決済したローソク足では仕掛けない機能をご紹介します。方法は色々ありそうですが、口座履歴は参照しない方法で作りました。

ポジションに設定した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に格納して完了です。

決済イベント、実装してくれないかなぁ。

MQL4プログラミングの最新記事8件

>完全放ったらかしEA 「AutoEndlessCatchRange」

完全放ったらかしEA 「AutoEndlessCatchRange」

「本業が忙しい!」「でも資産運用したい!」そんなあなたに最適なEAです。兼業トレーダーの方はチャートを毎日みて分析してトレードする時間はなかなか確保できないものです。トレードは本EAに任せて、本業やプライベートの時間をもっと増やしませんか?元々は自分自身のために開発したEAですので、手抜き無しのガチものです。

CTR IMG