ビジュアルモードのバックテストが速過ぎる時の対処法(2)

ポジション数が増減した時だけ一時停止させる

ビジュアルモードのバックテストが速過ぎる時の対処法で、ビジュアルモードでのバックテストのスピードが速すぎる場合のスピードダウンテクニックをお伝えしました。

今回は、さらに一歩進めて、ポジション数が増減した時だけバックテストを一時停止させる関数をお伝えしようと思います。

ネタ元はfaiさんの記事です。

VisualMode でのバックテスト中に、日付が変わる度に一時停止させる。

手前味噌で恐縮ですが、結構便利な関数だと思いますので、良かったらお使いください。

01//+------------------------------------------------------------------+
02//|【関数】ポジション数変動時にバックテスト一時停止                  |
03//|                                                                  |
04//|【引数】 IN OUT  引数名              説明                         |
05//|        --------------------------------------------------------- |
06//|         ○      aOpenOrderNumber    ポジション数                 |
07//|         ○      aPrvOpenOrderNumber 1ティック前のポジション数    |
08//|                                                                  |
09//|【戻値】なし                                                      |
10//|                                                                  |
11//|【備考】なし                                                      |
12//+------------------------------------------------------------------+
13void pauseExecEA(int aOpenOrderNumber, int aPrvOpenOrderNumber)
14{
15  if(aOpenOrderNumber != aPrvOpenOrderNumber){
16    int hwnd = WindowHandle(Symbol(), Period());
17 
18    PostMessageA(hwnd, WM_KEYDOWN, 19, 0); // 19 = Pause
19 
20    string msg      = "Order Number Changed. Tester Stopped.";
21    string boxTitle = "Break Point";
22    int r = MessageBoxW(hwnd, msg, boxTitle, 0);
23 
24    if(r == 1){
25      PostMessageA(hwnd, WM_KEYDOWN, 19, 0); // 19 = Pause
26    }
27  }
28}

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 を記述することです。もう1点は、この関数を呼び出す側で、if(IsVisualMode())により呼び出しを制御することです。IsVisualMode()の条件式を関数内部に持ってきても構いません。その辺はお好みです。

サンプルEA

全体像が分かるように、要所だけ記載したEAを載せておきます。

001//+------------------------------------------------------------------+
002//|                                         AutoEndlessTrap_v2.2.mq4 |
003//|                                     Copyright (c) 2016, りゅーき |
004//|                                            https://autofx100.com/ |
005//+------------------------------------------------------------------+
006#property copyright "Copyright (c) 2016, りゅーき"
007#property link      "https://autofx100.com/"
008#property version   "1.0"
009 
010//+------------------------------------------------------------------+
011//| ライブラリ                                                       |
012//+------------------------------------------------------------------+
013#include <stderror.mqh>
014#include <stdlib.mqh>
015#include <WinUser32.mqh>
016#include <Original/Basic.mqh>
017#include <Original/DateAndTime.mqh>
018#include <Original/LotSizing.mqh>
019#include <Original/OrderHandle.mqh>
020#include <Original/OrderReliable.mqh>
021 
022//+------------------------------------------------------------------+
023//| EAパラメータ設定情報                                             |
024//+------------------------------------------------------------------+
025
026 
027//+------------------------------------------------------------------+
028//| グローバル変数                                                   |
029//+------------------------------------------------------------------+
030
031int gPrvOpenOrderNumber = 0;
032
033 
034//+------------------------------------------------------------------+
035//| Expert initialization function                                   |
036//+------------------------------------------------------------------+
037int OnInit()
038{
039
040}
041 
042//+------------------------------------------------------------------+
043//| Expert deinitialization function                                 |
044//+------------------------------------------------------------------+
045void OnDeinit(const int reason)
046{
047
048}
049 
050//+------------------------------------------------------------------+
051//| Expert tick function                                             |
052//+------------------------------------------------------------------+
053void OnTick()
054{
055
056  if(IsVisualMode()){
057    int openOrderNumber = sumOrderNumberOrLotSize(OP_OPEN, MagicNumber, SUM_ORDER_NUMBER);
058  }else{
059    openOrderNumber = 0;
060  }
061
062  // -----------------------------------------------------------------
063  // ビジュアルモード時、ポジション数が変動したら、バックテスト一時停止
064  // -----------------------------------------------------------------
065  if(IsVisualMode()){
066    pauseExecEA(openOrderNumber, gPrvOpenOrderNumber);
067  }
068 
069  gPrvOpenOrderNumber = openOrderNumber;
070 
071  return;
072}
073 
074//+------------------------------------------------------------------+
075//|【関数】ポジション数変動時にバックテスト一時停止                  |
076//|                                                                  |
077//|【引数】 IN OUT  引数名              説明                         |
078//|        --------------------------------------------------------- |
079//|         ○      aOpenOrderNumber    ポジション数                 |
080//|         ○      aPrvOpenOrderNumber 1ティック前のポジション数    |
081//|                                                                  |
082//|【戻値】なし                                                      |
083//|                                                                  |
084//|【備考】なし                                                      |
085//+------------------------------------------------------------------+
086void pauseExecEA(int aOpenOrderNumber, int aPrvOpenOrderNumber)
087{
088  if(aOpenOrderNumber != aPrvOpenOrderNumber){
089    int hwnd = WindowHandle(Symbol(), Period());
090 
091    PostMessageA(hwnd, WM_KEYDOWN, 19, 0); // 19 = Pause
092 
093    string msg      = "Order Number Changed. Tester Stopped.";
094    string boxTitle = "Break Point";
095    int r = MessageBoxW(hwnd, msg, boxTitle, 0);
096 
097    if(r == 1){
098      PostMessageA(hwnd, WM_KEYDOWN, 19, 0); // 19 = Pause
099    }
100  }
101}

MT4の無料プログラミング講座

メルマガ登録して、MT4のプログラミング講座を無料で受けちゃおう!

超豪華プレゼントも盛りだくさん♪

MT4プログラミングを習得すると、オリジナルEA運用、作成代行、商品販売等、複数の収入源を手に入れられるよ。副業に最適だね!

↓↓↓ 詳細はこちら ↓↓↓

アイキャッチ

>

エターナル・パートナーPRO ~MT4裁量トレード支援ツール~ 「MT4は裁量トレーダーに優しくない」そう思ったことありませんか?もっと快適にトレードするための強力な売買ツールが必要だと考え、開発したのが「エターナル・パートナーPRO」です。元々は自分自身のために開発したツールですので、手抜き無しのガチものです。既に200名近い方に手に取っていただき、喜びの声が続々と届いております。ぜひご覧ください!

CTR IMG