【MQL4】数学関数の使い方を完全解説!MathAbs・MathRound・MathMax・MathMin・MathSqrtなど一覧付き

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

MQL4でEA(自動売買)やインジケーターを開発していると、「価格の差を絶対値で取りたい」「ロット数を適切に丸めたい」「2つの値のうち大きい方を使いたい」といった場面に頻繁に出会います。

こうした計算処理を簡単に実現してくれるのが数学関数(Math系関数)です。この記事では、EA開発で特に使用頻度の高いMathAbs・MathRound・MathMax・MathMin・MathSqrtを中心に、MQL4の数学関数を一覧付きで完全解説します。

MQL4の主要な数学関数一覧

まずは全体像を把握しましょう。MQL4で使える主要な数学関数を早見表にまとめました。

関数名 機能 使用例 結果
MathAbs() 絶対値を返す MathAbs(-1.5) 1.5
MathRound() 四捨五入(整数に丸める) MathRound(2.6) 3.0
MathFloor() 切り捨て(小さい方の整数) MathFloor(2.9) 2.0
MathCeil() 切り上げ(大きい方の整数) MathCeil(2.1) 3.0
MathMax() 2つの値のうち大きい方を返す MathMax(3, 7) 7
MathMin() 2つの値のうち小さい方を返す MathMin(3, 7) 3
MathSqrt() 平方根を返す MathSqrt(9.0) 3.0
MathPow() べき乗を返す MathPow(2, 3) 8.0
MathMod() 割り算の余りを返す MathMod(10, 3) 1.0
MathLog() 自然対数を返す MathLog(2.718) ≒1.0
MathExp() eのべき乗を返す MathExp(1.0) ≒2.718
MathRand() 0〜32767の乱数を返す MathRand() ランダム値

それでは、特に重要な関数を一つずつ詳しく見ていきましょう。

MathAbs() — 絶対値を求める

MathAbs()は、渡された値の絶対値(符号を取り除いた値)を返す関数です。負の数を正の数に変換したいときに使います。

double MathAbs(double value);

基本的な使い方

double val1 = MathAbs(-3.14);   // 結果: 3.14
double val2 = MathAbs(5.0);     // 結果: 5.0(正の値はそのまま)
double val3 = MathAbs(0.0);     // 結果: 0.0

実践例:2つの価格の差(pips)を計算する

EA開発でよくある場面が、エントリー価格と現在価格の差をpipsで計算するケースです。買い・売りどちらのポジションでも正の値で差を取得できるので便利です。

double openPrice  = 150.500;
double closePrice = 150.320;

// 方向に関係なく価格差をpipsで取得
double diffPips = MathAbs(closePrice - openPrice) / Point;
// 結果: 18.0 pips(3桁通貨の場合)

Print("価格差: ", diffPips, " pips");

MathAbs()を使わないと、買いポジションなら close - open、売りポジションなら open - close と場合分けが必要になります。絶対値を使えばこのような場合分けが不要になり、コードがシンプルになります。

MathRound() — 四捨五入する

MathRound()は、小数点以下を四捨五入して最も近い整数値を返します。戻り値の型はdoubleですが、値としては整数になります。

double MathRound(double value);

基本的な使い方

double val1 = MathRound(2.3);   // 結果: 2.0
double val2 = MathRound(2.5);   // 結果: 3.0
double val3 = MathRound(2.8);   // 結果: 3.0
double val4 = MathRound(-1.6);  // 結果: -2.0

MathRound・MathCeil・MathFloorの比較

「丸める」系の関数は3つあり、混同しやすいのでまとめて比較します。

入力値 MathRound()(四捨五入) MathCeil()(切り上げ) MathFloor()(切り捨て)
2.3 2.0 3.0 2.0
2.5 3.0 3.0 2.0
2.8 3.0 3.0 2.0
-1.3 -1.0 -1.0 -2.0
-1.8 -2.0 -1.0 -2.0

負の数の扱いに注意してください。MathFloor()は「数直線上で左方向(小さい方)」の整数を返すため、MathFloor(-1.3)-2.0 になります。

MathRound()とNormalizeDouble()の違い

MQL4初心者がよく迷うポイントが、MathRound()とNormalizeDouble()の使い分けです。

  • MathRound() — 常に整数に丸める。小数点以下の桁数は指定できない
  • NormalizeDouble()指定した小数点桁数で四捨五入する
double price = 1.23456;

// MathRound: 整数に丸める
double rounded = MathRound(price);               // 結果: 1.0

// NormalizeDouble: 小数点以下の桁数を指定して丸める
double normalized = NormalizeDouble(price, 3);    // 結果: 1.235(小数第3位まで)
double normalized2 = NormalizeDouble(price, 2);   // 結果: 1.23(小数第2位まで)

EA開発では、価格やロット数の丸めにはNormalizeDouble()を使うのが基本です。MathRound()は「個数」や「回数」など整数値が必要な場面で使います。

MathMax() / MathMin() — 2つの値を比較する

MathMax()は2つの値のうち大きい方を、MathMin()は小さい方を返します。if文を使った比較処理を1行で書けるのが魅力です。

double MathMax(double value1, double value2);
double MathMin(double value1, double value2);

基本的な使い方

double bigger  = MathMax(10.5, 20.3);   // 結果: 20.3
double smaller = MathMin(10.5, 20.3);   // 結果: 10.5

実践例:ロット数を最小値・最大値の範囲内に制限する(クランプ処理)

EA開発で非常によく使うパターンが、計算結果を一定の範囲内に収めるクランプ処理です。MathMax()とMathMin()を組み合わせて実現します。

double CalcLot = 0.03;  // 計算で求めたロット数

double minLot = MarketInfo(Symbol(), MODE_MINLOT);  // 例: 0.01
double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);  // 例: 100.0

// クランプ処理:minLot以上、maxLot以下に制限
double lot = MathMin(MathMax(CalcLot, minLot), maxLot);
// 内側から読む:まずMathMaxでminLot以上を保証 → MathMinでmaxLot以下を保証

この処理を分解すると次のようになります。

  1. MathMax(CalcLot, minLot) → CalcLotが最小ロットより小さい場合、最小ロットに引き上げる
  2. MathMin(結果, maxLot) → 結果が最大ロットより大きい場合、最大ロットに引き下げる

if文で書くと4〜5行必要な処理が、1行で完結するのがポイントです。

ネストして3つ以上の値から最大・最小を求める

MathMax()・MathMin()は2つの値しか比較できませんが、ネスト(入れ子)にすれば3つ以上の値にも対応できます。

// 3つの値から最大値を求める
double high1 = 150.800;
double high2 = 151.200;
double high3 = 150.950;

double highest = MathMax(MathMax(high1, high2), high3);
// 結果: 151.200

MathSqrt() — 平方根を求める

MathSqrt()は、引数の平方根(ルート)を返す関数です。統計的な指標計算で活躍します。

double MathSqrt(double value);

基本的な使い方

double val1 = MathSqrt(9.0);    // 結果: 3.0
double val2 = MathSqrt(2.0);    // 結果: 1.41421356...
double val3 = MathSqrt(0.0);    // 結果: 0.0
// MathSqrt(-1.0) は不正な値になるので注意

実践例:標準偏差の計算

ボリンジャーバンドなどで使われる標準偏差の計算にMathSqrt()が登場します。「分散の平方根 = 標準偏差」という関係です。

// 直近N本の終値から標準偏差を計算する関数
double CalcStdDev(int period)
{
    double sum = 0.0;
    // 平均を計算
    for(int i = 0; i < period; i++)
    {
        sum += Close[i];
    }
    double mean = sum / period;
    
    // 分散を計算
    double variance = 0.0;
    for(int i = 0; i < period; i++)
    {
        double diff = Close[i] - mean;
        variance += diff * diff;       // MathPow(diff, 2) でもOK
    }
    variance /= period;
    
    // 標準偏差 = 分散の平方根
    return MathSqrt(variance);
}

負の値をMathSqrt()に渡すとNaN(非数)が返ってくるため、引数が0以上であることを事前にチェックすると安全です。

その他の便利な数学関数

MathPow() — べき乗

MathPow(base, exponent)は「baseのexponent乗」を計算します。複利計算やボラティリティの2乗計算などで使います。

double val1 = MathPow(2, 10);    // 2の10乗 = 1024.0
double val2 = MathPow(1.01, 12); // 月利1%の年間複利 ≒ 1.1268

MathMod() — 剰余(余り)

MathMod(value, divider)は割り算の余りを返します。「N回に1回だけ処理する」といったカウンター制御に便利です。

// 5本に1回だけログを出力する例
static int barCount = 0;
barCount++;

if(MathMod(barCount, 5) == 0)
{
    Print("5本ごとのチェックポイント: ", barCount);
}

MathRand() / MathSrand() — 乱数

MathRand()は0〜32767のランダムな整数を返します。使用前にMathSrand()で乱数のシード(種)を初期化するのがポイントです。

// OnInit()で乱数を初期化
int OnInit()
{
    MathSrand(GetTickCount());  // 現在時刻をシードに設定
    return(INIT_SUCCEEDED);
}

// 1〜100のランダムな整数を生成
int randomNum = MathRand() % 100 + 1;

MathSrand()を呼ばないと毎回同じ乱数列が生成されてしまうので、必ずOnInit()内で初期化しましょう。

実践テクニック:リスクベースのロット計算

最後に、ここまで紹介した数学関数を組み合わせた実践的なロット計算関数を紹介します。口座残高の一定割合をリスクとしてロット数を算出する、EA開発の定番パターンです。

//+------------------------------------------------------------------+
//| リスクベースでロット数を計算する関数                                |
//| riskPercent : リスク割合(例: 2.0 = 口座残高の2%)                 |
//| slPips      : ストップロス幅(pips単位)                           |
//+------------------------------------------------------------------+
double CalcLotByRisk(double riskPercent, double slPips)
{
    // 1. リスク金額を計算
    double balance   = AccountBalance();
    double riskMoney = balance * riskPercent / 100.0;
    
    // 2. 1ロットあたりの1pipsの価値を取得
    double tickValue = MarketInfo(Symbol(), MODE_TICKVALUE);
    double tickSize  = MarketInfo(Symbol(), MODE_TICKSIZE);
    double pipValue  = tickValue * (Point / tickSize);
    
    // 3. ロット数を計算(MathAbsでslPipsの符号ミスを防止)
    double lots = riskMoney / (MathAbs(slPips) * pipValue);
    
    // 4. ロットステップに合わせて切り捨て
    double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
    lots = MathFloor(lots / lotStep) * lotStep;
    
    // 5. NormalizeDoubleで小数点を整える
    lots = NormalizeDouble(lots, 2);
    
    // 6. 最小・最大ロットの範囲にクランプ(MathMax + MathMin)
    double minLot = MarketInfo(Symbol(), MODE_MINLOT);
    double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);
    lots = MathMin(MathMax(lots, minLot), maxLot);
    
    return lots;
}

この関数の中で使っている数学関数をまとめると次の通りです。

  • MathAbs() — slPipsが負の値で渡された場合でも正しく計算できるように絶対値化
  • MathFloor() — ロットステップに合わせた切り捨て(余分な端数を除去)
  • MathMax() + MathMin() — 最小ロット以上・最大ロット以下のクランプ処理

このように、複数の数学関数を組み合わせることで、堅牢なロット計算ロジックが実現できます。

まとめ

この記事では、MQL4の数学関数について主要なものを一覧付きで解説しました。最後にポイントを整理しておきます。

  • MathAbs() — 絶対値。価格差の計算やマイナス値の防止に活躍
  • MathRound() — 整数への四捨五入。小数桁を指定したい場合はNormalizeDouble()を使う
  • MathMax() / MathMin() — 2値の比較。組み合わせてクランプ処理ができる万能関数
  • MathSqrt() — 平方根。標準偏差などの統計計算に必須
  • MathPow() / MathMod() / MathRand() — べき乗・剰余・乱数で応用範囲が広がる

数学関数は一つ一つは単純ですが、組み合わせることでEA開発に欠かせない計算ロジックを構築できます。特にMathMax/MathMinによるクランプ処理とMathAbsによる絶対値化は、ほぼすべてのEAで使うパターンなので、ぜひ身につけてください。