ポジション数が増減した時だけ一時停止させる
ビジュアルモードのバックテストが速過ぎる時の対処法で、ビジュアルモードでのバックテストのスピードが速すぎる場合のスピードダウンテクニックをお伝えしました。
今回は、さらに一歩進めて、ポジション数が増減した時だけバックテストを一時停止させる関数をお伝えしようと思います。
ネタ元はfaiさんの記事です。
VisualMode でのバックテスト中に、日付が変わる度に一時停止させる。
手前味噌で恐縮ですが、結構便利な関数だと思いますので、良かったらお使いください。
//+------------------------------------------------------------------+
//|【関数】ポジション数変動時にバックテスト一時停止 |
//| |
//|【引数】 IN OUT 引数名 説明 |
//| --------------------------------------------------------- |
//| ○ aOpenOrderNumber ポジション数 |
//| ○ aPrvOpenOrderNumber 1ティック前のポジション数 |
//| |
//|【戻値】なし |
//| |
//|【備考】なし |
//+------------------------------------------------------------------+
void pauseExecEA(int aOpenOrderNumber, int aPrvOpenOrderNumber)
{
if(aOpenOrderNumber != aPrvOpenOrderNumber){
int hwnd = WindowHandle(Symbol(), Period());
PostMessageA(hwnd, WM_KEYDOWN, 19, 0); // 19 = Pause
string msg = "Order Number Changed. Tester Stopped.";
string boxTitle = "Break Point";
int r = MessageBoxW(hwnd, msg, boxTitle, 0);
if(r == 1){
PostMessageA(hwnd, WM_KEYDOWN, 19, 0); // 19 = Pause
}
}
}
PostMessageA()とMessageBoxW()はWindows APIです。MT4の標準関数ではないので、要注意です。PostMessageA()でPauseキーを押す操作を、MessageBoxW()でダイアログ表示を実現しています。
faiさんの記事でも書かれていますが、MT4標準のMessageBox()はバックテストでは無視されてしまうため、Windows APIを使う必要があります。
if(r == 1)は、ダイアログのOKボタンが押されたら、Pauseキーが再度自動的に押されてバックテストが再開するための条件式です。ダイアログが表示されて、Enterキーを押したら、またバックテストが動き出すといった挙動になります。
faiさんの記事ではMessageBoxA()が使われていますが、MessageBoxA()では文字列の引数が正しくやり取りされないため、MessageBoxW()を使っています。MT4内部の文字コードがUTF-8に変わったことによる影響と思われます。
最初のif(aOpenOrderNumber != aPrvOpenOrderNumber)で、どういう時にバックテストを一時停止するかを判断しています。今回はポジション数の変動をトリガーにしていますが、待機注文を含めた注文数の変動で停止させるといった使い方も可能です。
本関数を使うにあたって注意事項が2点あります。1点は、Windows APIを使えるようにするために、EAの冒頭に#include
サンプルEA
全体像が分かるように、要所だけ記載したEAを載せておきます。
//+------------------------------------------------------------------+
//| AutoEndlessTrap_v2.2.mq4 |
//| Copyright (c) 2016, りゅーき |
//| https://autofx100.com/ |
//+------------------------------------------------------------------+
#property copyright "Copyright (c) 2016, りゅーき"
#property link "https://autofx100.com/"
#property version "1.0"
//+------------------------------------------------------------------+
//| ライブラリ |
//+------------------------------------------------------------------+
#include <stderror.mqh>
#include <stdlib.mqh>
#include <WinUser32.mqh>
#include <Original/Basic.mqh>
#include <Original/DateAndTime.mqh>
#include <Original/LotSizing.mqh>
#include <Original/OrderHandle.mqh>
#include <Original/OrderReliable.mqh>
//+------------------------------------------------------------------+
//| EAパラメータ設定情報 |
//+------------------------------------------------------------------+
…
//+------------------------------------------------------------------+
//| グローバル変数 |
//+------------------------------------------------------------------+
…
int gPrvOpenOrderNumber = 0;
…
//+------------------------------------------------------------------+
//| Expert initialization function |
//+------------------------------------------------------------------+
int OnInit()
{
…
}
//+------------------------------------------------------------------+
//| Expert deinitialization function |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
…
}
//+------------------------------------------------------------------+
//| Expert tick function |
//+------------------------------------------------------------------+
void OnTick()
{
…
if(IsVisualMode()){
int openOrderNumber = sumOrderNumberOrLotSize(OP_OPEN, MagicNumber, SUM_ORDER_NUMBER);
}else{
openOrderNumber = 0;
}
…
// -----------------------------------------------------------------
// ビジュアルモード時、ポジション数が変動したら、バックテスト一時停止
// -----------------------------------------------------------------
if(IsVisualMode()){
pauseExecEA(openOrderNumber, gPrvOpenOrderNumber);
}
gPrvOpenOrderNumber = openOrderNumber;
return;
}
//+------------------------------------------------------------------+
//|【関数】ポジション数変動時にバックテスト一時停止 |
//| |
//|【引数】 IN OUT 引数名 説明 |
//| --------------------------------------------------------- |
//| ○ aOpenOrderNumber ポジション数 |
//| ○ aPrvOpenOrderNumber 1ティック前のポジション数 |
//| |
//|【戻値】なし |
//| |
//|【備考】なし |
//+------------------------------------------------------------------+
void pauseExecEA(int aOpenOrderNumber, int aPrvOpenOrderNumber)
{
if(aOpenOrderNumber != aPrvOpenOrderNumber){
int hwnd = WindowHandle(Symbol(), Period());
PostMessageA(hwnd, WM_KEYDOWN, 19, 0); // 19 = Pause
string msg = "Order Number Changed. Tester Stopped.";
string boxTitle = "Break Point";
int r = MessageBoxW(hwnd, msg, boxTitle, 0);
if(r == 1){
PostMessageA(hwnd, WM_KEYDOWN, 19, 0); // 19 = Pause
}
}
}
