ロット数をNormalizeDouble(lots, 2)で丸めているのに、
発注時にエラーが出た、または思っていたロット数と違う発注になった。
そんな経験はないでしょうか。
原因は、NormalizeDoubleが「小数点以下の桁数」を丸める関数であり、
ブローカーが指定する「ロットの刻み値(0.1や0.01)の倍数」に
揃えてくれる関数ではないことにあります。
この記事では、MathRound(四捨五入)とMathAbs(絶対値)という
基礎的な数学関数の使い方と、この2つを組み合わせて
「刻み値の倍数」に丸める方法まで解説します。
・MathRound/MathAbsのシグネチャと戻り値の型
・NormalizeDoubleとの役割の違い
・ロット数を刻み値の倍数に丸める計算式
・損切り幅や損失額で絶対値が必要になる理由
MathRound・MathAbsが必要になる場面
まず、この2つの関数がどんな場面で必要になるか確認します。
四捨五入が必要な場面
ロット数の計算結果や、表示用の数値を
扱いやすい形に丸めたいときにMathRoundを使います。
絶対値が必要な場面
売買方向によってプラスとマイナスが入れ替わる数値
(損切り幅や損失額など)を、方向に関係なく扱いたいときにMathAbsを使います。
この記事で扱う内容の概要
| 関数 | 役割 | 戻り値の型 |
|---|---|---|
| MathRound(value) | 最も近い整数に四捨五入する | double |
| MathAbs(value) | 符号を外した絶対値を返す | double |
戻り値がどちらもdouble型である点は、
後の章で説明する落とし穴に関係してきます。
MathRoundの使い方
MathRoundの具体的な使い方を見ていきます。
シグネチャと戻り値がdouble型である点
double MathRound(double value);
引数・戻り値ともにdouble型です。
四捨五入しても「整数」にはなりますが、型は整数(int)ではありません。
整数が欲しい場合のキャスト
int rounded = (int)MathRound(value);
int型の変数へ代入したい場合は、
このように明示的にキャスト(型変換)するか、代入時の暗黙変換に任せます。
0.5の丸め方向は要注意
・MQL4公式リファレンスには「最も近い整数に丸める」としか書かれていません
・0.5のような境界値をどちら方向に丸めるかは明記されていません
・境界値が結果に影響するロジックでは、丸め後の値を必ずPrint()で確認してください
MathAbsの使い方
MathAbsの具体的な使い方を見ていきます。
シグネチャ
double MathAbs(double value);
符号がプラスでもマイナスでも、必ずゼロ以上の値が返ります。
損切り幅の計算での使用例
double slDistance = MathAbs(OrderOpenPrice() - OrderStopLoss());
買い注文か売り注文かによって、
エントリー価格と損切り価格の大小関係は逆になります。
MathAbsを使えば、方向を気にせず「距離」だけを取り出せます。
損失額を絶対値で扱う例
Print("損失額: ", DoubleToString(MathAbs(profit), 2));
含み損はマイナスの数値で表されるため、
ログやアラートの文言として「損失額◯◯円」のように
分かりやすく表示したいときにMathAbsが役立ちます。
NormalizeDoubleとの違いという落とし穴
ここが、この記事で最も伝えたい実務的な落とし穴です。
役割の違いの表
| 関数 | 丸める基準 | 用途 |
|---|---|---|
| NormalizeDouble | 小数点以下の桁数 | 価格・ロットの表示桁数を整える |
| MathRound+刻み値計算 | 任意の数値の倍数 | ロットを刻み値の倍数に揃える |
NormalizeDoubleは「桁数」を揃えるだけで、
「0.1刻み」のような倍数のルールまでは揃えてくれません。
混同するとどうなるか
・刻み値0.1でNormalizeDouble(0.15,1)を使うと結果があいまいです
・0.15自体が刻み値0.1の倍数ではないため、丸めた後も不正なロットになることがあります
・エラー131(不正なロット)の原因がここにあると気づきにくいです
ロット数計算での正しい組み合わせ方
double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP); double lots = MathRound(rawLots / lotStep) * lotStep;
生のロット数(rawLots)を刻み値で割ってMathRoundし、
もう一度刻み値を掛け直すことで、必ず刻み値の倍数になります。
実際に動くコード全体
ロット計算と損切り幅の表示をまとめたスクリプトです。
//+------------------------------------------------------------------+
//| MathRoundAbsDemo.mq4 |
//| Copyright 2026, FX-EA System Project Creator |
//| https://creator.fx-ea-system-project.com/ |
//+------------------------------------------------------------------+
#property strict
#property script_show_inputs
input double InpRawLots = 0.17;
void OnStart()
{
double lotStep = MarketInfo(Symbol(), MODE_LOTSTEP);
double minLot = MarketInfo(Symbol(), MODE_MINLOT);
double maxLot = MarketInfo(Symbol(), MODE_MAXLOT);
double rounded = MathRound(InpRawLots / lotStep) * lotStep;
if(rounded < minLot)
rounded = minLot;
if(rounded > maxLot)
rounded = maxLot;
Print("刻み値: ", lotStep, " 丸め前: ", InpRawLots, " 丸め後: ", rounded);
double entryPrice = Ask;
double stopPrice = Ask - 100 * Point;
double slDistance = MathAbs(entryPrice - stopPrice);
Print("損切り幅(絶対値): ", DoubleToString(slDistance, Digits));
double dummyProfit = -1234.5;
Print("損失額の表示: ", DoubleToString(MathAbs(dummyProfit), 2), "円");
}
MetaEditorでのコンパイル・実行手順
- MetaEditorで新規スクリプト「MathRoundAbsDemo」を作成し、上のコードを貼り付けてコンパイルする
- MT4のナビゲーターからチャートへドラッグ&ドロップして実行する
- 「エキスパート」タブで刻み値・丸め前・丸め後のロット数が表示されることを確認する
- 損切り幅・損失額の表示が両方ゼロ以上の値になっていることを確認する
よくあるエラーと注意点
実際に使うときにつまずきやすいポイントをまとめます。
int型への代入で起きる誤解
MathRoundの戻り値はdouble型なので、
int型の変数へ代入すると自動的に小数部が切り捨てられます。
丸めた後の値をPrint()で確認する習慣をつけてください。
MathAbsとfabsの違い
・MQL4公式リファレンスはfabs()を代替として挙げています
・MathAbs・fabsどちらも同じ結果になるため、既存コードとの統一性で選べば十分です
・このサイトの既存記事はMathAbsの表記で統一しています
MQL5での違い
MQL5にもMathRound・MathAbsは同じシグネチャで存在するため、
この記事の考え方はMQL4・MQL5どちらでもそのまま使えます。
よくある質問
MathRound・MathAbsについて、よく検索される疑問に回答します。
MathRoundとMathFloor・MathCeilの違いは何ですか?
MathRoundは四捨五入、MathFloorは小数部を切り捨て、
MathCeilは小数部を切り上げます。
ロットを刻み値の倍数に揃える場面では、
意図的に切り捨てたい場合はMathFloorを使う設計もあります。
NormalizeDoubleはもう使わなくていいですか?
いいえ、価格やロットの表示桁数を整える用途では
NormalizeDoubleは引き続き必要です。
この記事が指摘しているのは、
「桁数を整える」ことと「倍数に揃える」ことは別の処理だという点です。
エラー131(不正なロット)が出たらまず何を確認しますか?
MarketInfo(Symbol(), MODE_LOTSTEP)で刻み値を取得し、
発注直前のロット数がその倍数になっているかをPrint()で確認してください。
【MQL4】MathRound・MathAbsの使い方とロット数を『刻み値の倍数』に丸める応用についてわかりやすく解説してみた:まとめ
MathRoundは四捨五入、MathAbsは絶対値を返す基礎的な関数ですが、
NormalizeDoubleと役割を混同すると、
ロットが刻み値の倍数からズレるという実害につながります。
生のロット数を刻み値で割ってMathRoundし、
もう一度刻み値を掛け直すという組み合わせを覚えておけば、
エラー131のような不正なロットのトラブルを避けやすくなります。
コメント