【MQL4】知っておきたいユーティリティ関数6選!Sleep・RefreshRates・IsTradeAllowed・IsConnected・IsTesting・IsOptimizationの使い方

【中級編】MQLプログラムの読み方・書き方

EA(自動売買プログラム)を作っていると、「注文を出す前にサーバーと接続できているか確認したい」「バックテスト中は処理を軽くしたい」といった場面に必ず出くわします。こうした場面で活躍するのが、MQL4に用意されたユーティリティ関数たちです。

今回は、EA開発で特に使用頻度が高い以下の6つのユーティリティ関数をまとめて解説します。

  • Sleep() — 処理の一時停止
  • RefreshRates() — 価格データの最新化
  • IsTradeAllowed() — 自動売買の許可状態を確認
  • IsConnected() — サーバー接続の確認
  • IsTesting() — バックテスト中かどうかの判定
  • IsOptimization() — 最適化モードかどうかの判定

それぞれの基本的な使い方から、最後に6つすべてを組み合わせた実践テンプレートまで紹介しますので、ぜひ最後までお読みください。

Sleep() — ミリ秒単位で処理を一時停止する

基本構文

void Sleep(int milliseconds);

Sleep()は、指定したミリ秒(1000ミリ秒=1秒)だけEAの処理を一時停止する関数です。注文のリトライ処理やサーバーとの通信待ちなどで頻繁に使われます。

使用例:注文失敗時のリトライ

注文送信が失敗した場合、少し間をおいてからリトライするのが一般的なパターンです。

int ticket = -1;
int retryCount = 3;

for(int i = 0; i < retryCount; i++)
{
    ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0, "Buy Order", 0, 0, clrBlue);

    if(ticket > 0)
    {
        Print("注文成功! チケット番号: ", ticket);
        break;
    }
    else
    {
        int err = GetLastError();
        Print("注文失敗(", i + 1, "回目) エラー: ", err);
        Sleep(1000);  // 1秒待ってからリトライ
    }
}

Sleep()の注意点

  • ストラテジーテスターでは無視されます。バックテスト中にSleep()を呼んでも、実際には一時停止しません。テスト速度に影響を与えないための仕様です。
  • Sleep()の内部では約0.1秒ごとにEAの停止フラグがチェックされています。そのため、Sleep(10000)(10秒停止)を実行中でも、ユーザーがEAを停止すれば比較的すぐに処理が終了します。
  • カスタムインジケーターの中では使用できません。EAおよびスクリプト専用の関数です。

RefreshRates() — 価格データを最新の状態に更新する

基本構文

bool RefreshRates();

RefreshRates()は、Bid、Ask、Volumeなどの定義済み変数を最新のサーバーデータに更新する関数です。更新に成功するとtrueを返します。

なぜRefreshRates()が必要なのか

EAのOnTick()が呼び出された瞬間に、BidやAskには最新の値がセットされます。しかし、その後にSleep()で待機したり、重い計算処理を行ったりすると、BidやAskの値が古くなってしまう可能性があります。

つまり、Sleep()の後にはRefreshRates()を呼ぶのが鉄則です。

使用例:Sleep()とRefreshRates()のセット

// 注文失敗 → 待機 → 価格を更新してリトライ
Sleep(1000);
RefreshRates();  // Bid/Askを最新に更新

// 更新後のAskで再度注文
ticket = OrderSend(Symbol(), OP_BUY, 0.1, Ask, 3, 0, 0, "Retry Order", 0, 0, clrBlue);

RefreshRates()を呼ばずに古いAsk値で注文を出すと、「Off quotes(無効な価格)」エラーが発生する原因になります。注意しましょう。

IsTradeAllowed() — 自動売買が許可されているか確認する

基本構文

bool IsTradeAllowed();

IsTradeAllowed()は、EAによる自動売買が許可されている場合にtrueを返す関数です。具体的には、以下の2つの条件を確認しています。

  • MetaTraderのツールバーにある「自動売買」ボタンがONになっているか
  • 他のEAやスクリプトが取引コンテキストを使用中(ビジー状態)でないか

使用例:注文前の安全チェック

void OnTick()
{
    // 自動売買が許可されていなければ何もしない
    if(!IsTradeAllowed())
    {
        Print("自動売買が無効です。ツールバーの自動売買ボタンを確認してください。");
        return;
    }

    // ここから注文ロジック
    // ...
}

取引コンテキストのビジー状態に対処する

同一のMetaTrader上で複数のEAが動作している場合、1つのEAが注文処理を行っている間は他のEAの取引がブロックされます。このような場合は、少し待ってから再確認するのが有効です。

// 取引コンテキストが空くまで待機(最大5秒)
for(int i = 0; i < 10; i++)
{
    if(IsTradeAllowed())
        break;

    Print("取引コンテキストがビジー状態です。待機中...");
    Sleep(500);
}

IsConnected() — サーバーとの接続状態を確認する

基本構文

bool IsConnected();

IsConnected()は、MetaTraderクライアントがブローカーのサーバーと接続されている場合にtrueを返す関数です。

使用例:接続チェック

void OnTick()
{
    if(!IsConnected())
    {
        Print("サーバーに接続されていません! 注文処理をスキップします。");
        return;
    }

    // 接続確認OK → 通常の処理へ
}

VPS運用時に特に重要

VPS(仮想専用サーバー)でEAを24時間稼働させている場合、ネットワークの一時的な切断は避けられません。IsConnected()で接続状態をチェックし、切断時にはアラートを出すなどの処理を組み込んでおくと安心です。

static datetime lastAlertTime = 0;

if(!IsConnected())
{
    // 5分に1回だけアラート
    if(TimeCurrent() - lastAlertTime > 300)
    {
        Alert("サーバー接続が切断されています!");
        lastAlertTime = TimeCurrent();
    }
    return;
}

IsTesting() — バックテスト中かどうかを判定する

基本構文

bool IsTesting();

IsTesting()は、EAがストラテジーテスター上で動作しているときにtrueを返す関数です。ライブ口座やデモ口座で動かしている場合はfalseになります。

使用例:テスト時にGUI処理をスキップして高速化

バックテスト(特にビジュアルモードではない通常テスト)では、画面への描画処理は不要です。Comment()やObjectCreate()といった描画関数をスキップすることで、テスト速度を大幅に向上できます。

// グローバル変数としてフラグを用意
bool gIsTesting = false;

int OnInit()
{
    // init()内で1度だけ判定すれば十分
    gIsTesting = IsTesting();
    return(INIT_SUCCEEDED);
}

void OnTick()
{
    // テスト中でなければ画面に情報を表示
    if(!gIsTesting)
    {
        Comment("Bid: ", Bid, "  Ask: ", Ask, "  Spread: ", MarketInfo(Symbol(), MODE_SPREAD));
    }

    // 売買ロジック...
}

ポイント:IsTesting()の戻り値はEAの実行中に変わることはありません。そのため、OnInit()内で一度だけ判定してグローバル変数に保存すれば十分です。OnTick()のたびに呼び出す必要はなく、わずかですがパフォーマンスの改善につながります。

IsOptimization() — 最適化モードかどうかを判定する

基本構文

bool IsOptimization();

IsOptimization()は、ストラテジーテスターの最適化モードで実行されているときにtrueを返す関数です。最適化モードでは、パラメータの組み合わせを大量にテストするため、不要な処理を極力省くことが重要になります。

使用例:最適化中はPrint()を抑制する

最適化モードでは、Print()による出力がログに記録されません。つまり、Print()を呼んでもデバッグの役に立たないだけでなく、処理のオーバーヘッドだけが残ります。

bool gIsOptimization = false;

int OnInit()
{
    gIsOptimization = IsOptimization();
    return(INIT_SUCCEEDED);
}

void OnTick()
{
    // 最適化中はデバッグ出力をスキップ
    if(!gIsOptimization)
    {
        Print("現在のBid: ", Bid, " Ask: ", Ask);
    }

    // 売買ロジック...
}

IsTesting()との使い分け

IsTesting()とIsOptimization()の関係を整理しておきましょう。

状態 IsTesting() IsOptimization()
ライブ口座 / デモ口座 false false
バックテスト(通常) true false
バックテスト(ビジュアルモード) true false
最適化モード true true

最適化モードのときはIsTesting()もtrueになります。つまり「IsTesting()がtrueかつIsOptimization()がfalse」であれば通常のバックテスト、「両方ともtrue」であれば最適化中ということになります。

実践テンプレート:6つの関数を組み合わせた安全な注文処理

ここまで紹介した6つの関数をすべて組み合わせた、実践的な注文処理テンプレートを紹介します。実際のEA開発でそのまま活用できる構成です。

//--- グローバル変数
bool gIsTesting      = false;
bool gIsOptimization = false;

//+------------------------------------------------------------------+
//| 初期化関数                                                         |
//+------------------------------------------------------------------+
int OnInit()
{
    // 実行環境フラグを初期化時に1度だけ判定
    gIsTesting      = IsTesting();
    gIsOptimization = IsOptimization();

    if(!gIsOptimization)
        Print("EA初期化完了 テストモード: ", gIsTesting);

    return(INIT_SUCCEEDED);
}

//+------------------------------------------------------------------+
//| 安全な買い注文関数                                                  |
//+------------------------------------------------------------------+
int SafeBuyOrder(double lots, int slippage, double sl, double tp, string comment)
{
    int maxRetry = 3;
    int ticket   = -1;

    //--- 1. サーバー接続チェック(テスト時はスキップ)
    if(!gIsTesting && !IsConnected())
    {
        Print("エラー: サーバーに接続されていません");
        return(-1);
    }

    //--- 2. 自動売買許可チェック
    if(!IsTradeAllowed())
    {
        Print("エラー: 自動売買が許可されていません");
        return(-1);
    }

    //--- 3. リトライループ
    for(int i = 0; i < maxRetry; i++)
    {
        // 価格データを最新に更新
        RefreshRates();

        // 注文送信
        ticket = OrderSend(Symbol(), OP_BUY, lots, Ask, slippage, sl, tp, comment, 0, 0, clrBlue);

        if(ticket > 0)
        {
            if(!gIsOptimization)
                Print("買い注文成功! チケット: ", ticket, " 価格: ", Ask);
            break;
        }
        else
        {
            int err = GetLastError();
            if(!gIsOptimization)
                Print("買い注文失敗(", i + 1, "/", maxRetry, ") エラーコード: ", err);

            // 最後のリトライでなければ待機
            if(i < maxRetry - 1)
            {
                Sleep(1000);  // 1秒待機(テスターでは無視される)
            }
        }
    }

    return(ticket);
}

//+------------------------------------------------------------------+
//| ティックごとの処理                                                  |
//+------------------------------------------------------------------+
void OnTick()
{
    //--- 画面表示(通常バックテスト・最適化時はスキップ)
    if(!gIsTesting)
    {
        Comment("EA稼働中 | Bid: ", Bid, " | Ask: ", Ask,
                " | 接続: ", (IsConnected() ? "OK" : "NG"),
                " | 自動売買: ", (IsTradeAllowed() ? "許可" : "不可"));
    }

    //--- ここに売買条件を記述 ---
    // 例: 買い条件を満たしたら注文
    // int ticket = SafeBuyOrder(0.1, 3, 0, 0, "Sample EA");
}

//+------------------------------------------------------------------+
//| 終了処理                                                          |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
    if(!gIsOptimization)
        Print("EA停止 理由コード: ", reason);

    // テスト時でなければコメントをクリア
    if(!gIsTesting)
        Comment("");
}

このテンプレートでは、以下のポイントを押さえています。

  • OnInit()で環境フラグを一度だけ判定 — IsTesting()やIsOptimization()を毎ティック呼ぶ無駄を排除
  • 注文前にIsConnected()とIsTradeAllowed()をチェック — 接続切れや自動売買無効時のエラーを未然に防止
  • リトライ時にSleep() + RefreshRates()をセットで使用 — 待機後に最新価格を取得してから再注文
  • 最適化中はPrint()をスキップ — 不要な処理のオーバーヘッドを削減
  • テスト中はComment()による画面描画をスキップ — バックテストの高速化

まとめ

今回紹介した6つのユーティリティ関数を一覧表で振り返りましょう。

関数名 用途 主な使いどころ
Sleep() 処理の一時停止 注文リトライ時の待機
RefreshRates() 価格データの更新 Sleep()の後、重い計算の後
IsTradeAllowed() 自動売買許可の確認 注文送信前のチェック
IsConnected() サーバー接続の確認 注文送信前、VPS運用時
IsTesting() バックテスト判定 GUI処理のスキップ
IsOptimization() 最適化モード判定 Print()の抑制

これらの関数は単体で使うだけでなく、組み合わせて使うことで真価を発揮します。特に「Sleep() → RefreshRates()」のセットや、「IsTesting() / IsOptimization()による処理の出し分け」は、EA開発における定番テクニックです。

今回紹介した実践テンプレートをベースに、ご自身のEAに安全で効率的な処理を組み込んでみてください。堅牢なEAを作る第一歩になるはずです。