MQL4 MathMax() / MathMin() with NormalizeDouble() anomaly
MQL4 MathMax() / MathMin() with NormalizeDouble() anomaly
Loading saved threads...
Bill Ritzel · External communityPost link
External question — Stack Overflow Stack Exchange
Author: Bill Ritzel
Original post: https://stackoverflow.com/questions/75838993
License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/
Adaptation: HTML converted to plain text; contact email addresses removed.
In an MQL4 EA, using a calculated moving average for a stoploss, I used
MathMax()
and
MathMin()
to make sure I wasn't too close. The results were a bit off, so I put in a
Print()
to get me details:
stoploss=MathMax(NormalizeDouble(Ask+(minstoplevel*Point),Digits),NormalizeDouble(MA_Line,Digits));
Print("Sell SLCalc = "+NormalizeDouble(Ask+(minstoplevel*Point),Digits)+", MA_Line = "+NormalizeDouble(MA_Line,Digits),", Max is ",MathMax(NormalizeDouble(Ask+(minstoplevel*Point),Digits),NormalizeDouble(MA_Line,Digits)));
The result:
2023.03.24 16:46:36.607 2022.07.18 03:14:29 MA1 GBPUSD,M1: Sell SLCalc = 1.18836, MA_Line = 1.18835, Max is 1.1884
I was expecting the Max to have the same 5-digit precision. Why is the
MathMax()
function rounding the result, when I've specified the point to the function, rather than the pip?
It may seem like a small difference, but that's the world of Forex, and a small rounding error could stop me out or keep me in a long trend. Besides, I just want things to work as advertised, or understand why they don't.
Quote
Report
PaulB · External communityPost link
External answer — Stack Overflow Stack Exchange
Author: PaulB
Original post: https://stackoverflow.com/a/75867890
License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/
Adaptation: HTML converted to plain text; contact email addresses removed.
There is nothing inherently wrong with your code, however by printing the values you are casting them to a
string
. You should use
DoubleToString()
around your printed functions as follows:
Print("Sell SLCalc = "+DoubleToString(Ask+(minstoplevel*Point),Digits)+", MA_Line = "+DoubleToString(MA_Line,Digits),", Max is ",DoubleToString(MathMax(NormalizeDouble(Ask+(minstoplevel*Point),Digits),NormalizeDouble(MA_Line,Digits)),Digits));
Quote
Report
user3666197 · External communityPost link
External answer — Stack Overflow Stack Exchange
Author: user3666197
Original post: https://stackoverflow.com/a/79749560
License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/
Adaptation: HTML converted to plain text; contact email addresses removed.
I just want things to work as advertised, or understand why they don't
Glad to hear that - knowing why something happens is infinitely better than just observing that something has just happened.
Let's start with some polishing.
(im)
-
precision
of any amount
is a cardinal, in-separable property of the knowledge about the actual "value" of such amount
number-representation
( using binary-digits: used in most, not all, computing devices; using decimal-digits: used by most, not all, humans as we know ) is on the other hand some attempt, how to efficiently "communicate" some amount to others ( be it computers or humans )
rounding
of any amount is a way of knowingly neglecting some part of the original knowledge about the amount and starting to further use some "other" amount, not much different ( given our circumstances of "communicating" the original amounts ) from the "more" exact original knowledge
comparing
of any amounts
is a method allowing us to decide relations between several amounts ( like greater / smaller / equal / not-equal / smallest-of-all / greatest-of-all )
This said, using a plain
Print()
-command in MQL4 resorts to "show" something, without any care to how the actual
(im)
-precision will look as taking the machine-dependent number-representation.
Using
PrintFormat()
is a way to explicitly setup the presentation format of any output amounts, using a built-in mini-language for explicit formatting of respective ( machine-stored ) amounts :
%[flags][width][.precision][{ h | l | ll | I32 | I64 }]type
Similar is the
DoubleToString()
-conversion utility function, where a "number-of-digits", ranging ( -16 .. +8 ) imperatively declares, how the amount conversion into some ( scientific-notation or plain-decimal-notation ) string-representation of the underlying ( machine-stored ) amounts.
Now comes the "rounding" -- MQL4 advocated since ever to manually enforce any PriceDOMAIN-value for any kind of XTO by using a transformed amount , received from a manual prior call to a
NormalizeDouble( amount,
_Digits
)
-function. This will take
_Symbol
-specific information, how many decimal digits one's broker actually uses in XTO-s accepted onto the FX-Market for that specific
_Symbol
. Not having done so, MT4-Server might reject an XTO, which is a state no one wants to happen ( trading-wise, waiting-time-wise ). That is why all XTO-s are better off to enforce
NormalizeDouble()
-transformed ( I knowingly do not say rounded, as closed source code was not reviewed and one might resort to just run a battery of rounding-revealing test-cases to reverse-engineer the transformation logic from the actual outputs )
For your case, one may use
double
-typed values with care, using rather
PrintFormat()
-specified ( machine-stored ) amounts printing-presentation layouts and defer
NormalizeDouble()
-calls to transform the amounts ALAP to assembling the actual XTO-s
Using
int
-typed, banking alike (with no fractions or rounding artifacts), amounts is doable, if one prefers it.
Last but not least, FX-trading in MQL4/5 exosystems depends ( a lot ) on one's Broker Terms & Conditions.
{ MODE_FREEZELEVEL, MODE_STOPLEVEL, ... }
FX-Broker specific, time-dependent
details
about each
_Symbol
matter, a lot ... Do not hesitate to re-read the T&C and carefully pre-check upon assembling actual XTO the current state of these FX-Market context details and do not hesitate to run FX-Broker scanner, logging these parameters 24/5/365 to learn, if/what tricks to defend your trading strategies from. ( After 20 years of doing so it has taught me to be rather very careful here, not to get rejected XTO-s when one need immediate XTO-execution instead. )
Quote
Report
Post Reply
Quoted from Forex.com.bd-Editorial External answer — Stack Overflow Stack Exchange Author: PaulB Source score (net votes, not local likes): 0 Original post: https://stackoverflow.com/a/75867890 License: CC BY-SA 4.0 — https://creativecommons.org/licenses/by-sa/4.0/ Adaptation: HTML converted to plain text; contact email addresses removed. There is nothing inherently wrong with your code, however by printing the values you are casting them to a string . You should use DoubleToString() around your printed functions as follows: Print("Sell SLCalc = "+DoubleToString(Ask+(minstoplevel*Point),Digits)+", MA_Line = "+DoubleToString(MA_Line,Digits),", Max is ",DoubleToString(MathMax(NormalizeDouble(Ask+(minstoplevel*Point),Digits),NormalizeDouble(MA_Line,Digits)),Digits));
Checking account access…