【MQL5】MathIsValidNumber関数の使い方と自動売買実装コード

1. MathIsValidNumber関数の概要と実務での活用法

MQL5でEA(エキスパートアドバイザー)やインジケーターを開発していると、計算結果が「nan(非数)」や「inf(無限大)」になってしまう場面に遭遇することがあります。例えば、「ゼロによる除算(0で割る)」や「負の数に対する平方根の計算」などが原因です。

MathIsValidNumberは、渡された数値が有効な数値であるかどうか(nanやinfではないか)を判定する関数です。

実務レベルの開発、特に複雑な数学モデルを用いるクオンツトレードにおいては、このチェックを怠ると深刻なバグに繋がります。もし無効な数値(nan)をそのまま OrderSend 関数(注文処理)の価格やロット数に渡してしまうと、注文が拒絶されるだけでなく、最悪の場合EAが停止したり、予期せぬループに陥ったりするリスクがあります。堅牢なシストレを構築するためには、「計算結果が正しい数値であること」を確認する工程が必須なのです。

2. 構文と戻り値

MathIsValidNumber関数の仕様は非常にシンプルです。

構文

bool MathIsValidNumber(
   double  number      // チェックする数値
);

パラメーター

  • number: 判定したい double 型の数値を指定します。

戻り値

  • true: 数値が有効な場合(通常の数値である場合)。
  • false: 数値が無効な場合(「nan: 非数」または「inf: 無限大」である場合)。

3. 具体的な使い方・実践サンプルコード

以下に、ストップロス(決済指値)の幅からロット数を計算する際、計算ミスや異常値によるエラーを防ぐための実装例を示します。

//+------------------------------------------------------------------+
//| ロット計算時における有効性チェックの例                                     |
//+------------------------------------------------------------------+
double CalculateSafeLot(double riskAmount, double stopLossPoints)
{
    // 1. ゼロ割りを防ぐための事前チェック
    if(stopLossPoints <= 0)
    {
        Print("エラー: ストップロス幅が0以下です。");
        return 0.0;
    }

    // 2. ロット数の計算(例:許容損失額 ÷ ストップ幅 ÷ 1ポイントあたりの価値)
    double tickValue = SymbolInfoDouble(_Symbol, SYMBOL_TRADE_TICK_VALUE);
    double rawLot = riskAmount / (stopLossPoints * tickValue);

    // 3. MathIsValidNumberによる数値の妥当性確認
    // 計算結果が nan (Not a Number) や inf (Infinity) になっていないか判定
    if(!MathIsValidNumber(rawLot))
    {
        Print("警告: ロット計算の結果が不正な値(NaN/Inf)になりました。");
        return 0.0;
    }

    // 4. 有効な数値であれば、適切なロット単位に調整して返す
    double minLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_MIN);
    double stepLot = SymbolInfoDouble(_Symbol, SYMBOL_VOLUME_STEP);
    double finalLot = MathFloor(rawLot / stepLot) * stepLot;

    return (finalLot < minLot) ? 0.0 : finalLot;
}

// EAのオンティックイベントでの使用例
void OnTick()
{
    double myLot = CalculateSafeLot(10000, 500); // 1万円のリスク、500ポイントの損切り幅

    if(myLot > 0)
    {
        // ここで実際の注文処理へ進む
        // Print("計算されたロット数: ", myLot);
    }
}

4. 使用上の注意点とよくあるエラー

「0」は有効な数値として扱われる

初心者が最も混同しやすいのは、「0.0」という数値は MathIsValidNumber では true(有効)と判定されるという点です。
この関数はあくまで「浮動小数点数として定義可能か」をチェックするものであり、「ロジックとして正しいか」を判定するものではありません。ロット数が 0.0 では注文が出せませんので、関数の戻り値とは別に「0より大きいか」のチェックも併せて行うのが定石です。

NormalizeDoubleとの違い

NormalizeDouble は数値を指定した桁数で四捨五入する関数であり、数値の妥当性をチェックする能力はありません。nan に対して NormalizeDouble を実行しても結果は nan のままです。必ず「計算 → 有効性チェック(MathIsValidNumber) → 正規化(NormalizeDouble)」の順序で処理を組み立てましょう。

実行速度への影響

この関数自体の処理負荷は極めて軽微です。ループ内で数千回呼び出したとしても、パフォーマンスへの影響は無視できるレベルです。安全性を優先し、少しでも計算が不安定になる可能性がある箇所には積極的に組み込むべきです。

5. 【重要】自動売買における約定スピードと環境の罠

どれほど完璧なロジックを MathIsValidNumber で守ったとしても、家庭用の一般的なPC環境やWi-Fi環境からの自動売買には、致命的な「物理的限界」が存在します。FXの自動売買において、プログラムが売買を判断してから証券会社のサーバーに注文が届くまでの「ネットワーク遅延(レイテンシ)」は、収益性を左右する最大の要因の一つです。自宅PCでの運用は、予期せぬOSのアップデートや停電、ネット回線の不安定さにより、注文が数秒遅れたり、最悪の場合、約定拒絶(リクオート)を招き、設計上の期待値を大幅に下回る損失を生むリスクがあります。

プロのクオンツや専業トレーダーにとって、トレード専用のVPS(仮想専用サーバー)を利用することは、もはやオプションではなく「必須装備」です。証券会社のデータセンターに近い場所に位置するVPSを利用することで、ネットワーク遅延を1ミリ秒(1000分の1秒)単位まで極限に抑えることが可能になります。このわずかな差が、スリッページを最小限に抑え、バックテスト通りの理想的なパフォーマンスを引き出す鍵となります。本気でシストレでの利益を追求するのであれば、まずは環境の罠を排除し、24時間365日安定した高速約定が約束されたVPS環境を整えることから始めてください。

💡 この記事の内容を実運用で活かすには?

この記事の内容を実運用で活かすには、正しい環境が必要です。
特にVPSを使わないと、このロジックは再現できません。

コメント

タイトルとURLをコピーしました