MQL4 bad math issues

 

The following simple math calculation results in the following 2 intermittent problems.

The Calculation is highlighted in the routine below marked exhibit A.:

The incorrect results of this calculation presents two different variation:

Variation 1.

The result of this subtraction calculation is printed on the journal/log; it prints incorrectly even though the field appears to be correct as it triggers the SELL open (below exhibit A.).

Log excerpt 1.

18:50:38 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: ma_fast1 = 2.0381 ma_fast2 = 2.0377 ma_fast3 = 2.0371

18:50:38 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: ma_slow1 = 2.0317 ma_slow2 = 2.0312 ma_slow3 = 2.0307

18:50:38 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: ma_D1 = 0.0064 ma_D2 = 0.0064 ma_D3 = 0.0064

18:50:38 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: open #1 sell 0. 10 GBPUSD at 2.0560 sl: 2.0760 tp: 2.0160

Variation 2.

The result of the subtraction calculations print the correct value but the when the value is interrogated by the open trigger logic it appears to get a "false" answer when it should get a true, causing the SELL open not to be triggered.

Log excerpt 2.

18:50:38 2007.08.03 08:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: CFO FIRST TICK

18:50:38 2007.08.03 08:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: CHECK FOR OPEN

18:50:38 2007.08.03 08:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: ma_fast1 = 2.0358 ma_fast2 = 2.0358 ma_fast3 = 2.0358

18:50:38 2007.08.03 08:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: ma_slow1 = 2.0333 ma_slow2 = 2.0332 ma_slow3 = 2.0332

18:50:38 2007.08.03 08:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: ma_D1 = 0.0025 ma_D2 = 0.0026 ma_D3 = 0.0026

Obviously variation 2 is a more critical situation because it acts on the result incorrectly. The incorrect printing I can live with, the incorrect action I can not.

Although I have 25 years experience in software programming and analysis, this is my first time using this particular language and it is possible I am overlooking something I should or should not be doing. Possibly I am not correctly comprehending the data types, formats and their uses but I have read through the documentation and have not found error with the code.

I logged this problem on to the MetaQuotes website a week ago as suggested by Rosh and have heard no feedback on the issues.

Please advise me ASAP as to when I may reasonably expect to get some feedback on these two issues. As you might expect I am a bit ambivalent about putting any EA into production with these kind of issues outstanding.

Please feel free to call me at anytime at 404-386-9831

Thanks

K

Kevin R. Vibert

404-386-9831

Exhibit A.

//+------------------------------------------------------------------+

//| START - Check for open order conditions PROGRAM 3

//| PRINT("START - Check for open order conditions - PROGRAM 3");

//+------------------------------------------------------------------+

void CheckForOpen()

{

double ma_fast1=0.0000;

double ma_fast2=0.0000;

double ma_fast3=0.0000;

double ma_slow1=0.0000;

double ma_slow2=0.0000;

double ma_slow3=0.0000;

double ma_D1=0.0000;

double ma_D2=0.0000;

double ma_D3=0.0000;

int res;

//---- go trading only for first tiks of new bar

if(Volume[0]>1) return;

Print(" CFO FIRST TICK ");

//---- get Moving Average

ma_fast1=iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,1);

ma_fast2=iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,2);

ma_fast3=iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,3);

ma_slow1=iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,1);

ma_slow2=iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,2);

ma_slow3=iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,3);

Print(" CHECK FOR OPEN ");

Print(" ma_fast1 = ", ma_fast1,

" ma_fast2 = ", ma_fast2,

" ma_fast3 = ", ma_fast3);

Print(" ma_slow1 = ", ma_slow1,

" ma_slow2 = ", ma_slow2,

" ma_slow3 = ", ma_slow3);

ma_D1 = ma_fast1-ma_slow1;

ma_D2 = ma_fast2-ma_slow2;

ma_D3 = ma_fast3-ma_slow3;

Print(" ma_D1 = ", ma_D1,

" ma_D2 = ", ma_D2,

" ma_D3 = ", ma_D3);

//---- sell conditions

{

if(MathAbs(ma_D1) > ev_FlatTradeDif

&& ma_fast1 > ma_slow1

&& ma_fast2 > ma_slow2

&& ma_D1 < ma_D2

&& ma_D2 >= ma_D3)

{

{

if(ev_InitialStop==0)

res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),

Bid,3,0,Bid-ev_TakeProfit*Point,"",MAGICMA,0,Red);

else

res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),

Bid,3,Bid+ev_InitialStop*Point,

Bid-ev_TakeProfit*Point,"",MAGICMA,0,Red);

}

return(0);

}

}

//---- buy conditions

{

if(MathAbs(ma_D1) > ev_FlatTradeDif

&& ma_fast1 < ma_slow1

&& ma_fast2 < ma_slow2

&& ma_D1 > ma_D2

&& ma_D2 <= ma_D3)

{

{

if(ev_InitialStop==0)

res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),

Ask,3,0,Ask+ev_TakeProfit*Point,"",MAGICMA,0,Blue);

else

res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),

Ask,3,Ask-ev_InitialStop*Point,

Ask+ev_TakeProfit*Point,"",MAGICMA,0,Blue);

}

return;

}

}

}

//+------------------------------------------------------------------+

//| END - Check for open order conditions - PROGRAM 3

//| PRINT("END - Check for open order conditions - PROGRAM 3");

//+------------------------------------------------------------------+

 
What's the problem exactly? Could you use a bit less words to describe it please?
I mean the problem itself, not the consequences whatever crucial they are.
MQL code tag (via MQL button in the toolbar) might help too.
 
Irtron:
What's the problem exactly? Could you use a bit less words to describe it please?
I mean the problem itself, not the consequences whatever crucial they are.
MQL code tag (via MQL button in the toolbar) might help too.


Sure, the problem is it comes up with the wrong answer when it subtracts 2 moving average prices.

Sorry I have no idea what you mean by "MQL code tag (via MQL button in the toolbar)".

good bad - should be 0.0065

18:50:38 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: ma_fast1 = 2.0381 ma_fast2 = 2.0377 ma_fast3 = 2.0371

18:50:38 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: ma_slow1 = 2.0317 ma_slow2 = 2.0312 ma_slow3 = 2.0307

18:50:38 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: ma_D1 = 0.0064 ma_D2 = 0.0064 ma_D3 = 0.0064

18:50:38 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: open #1 sell 0. 10 GBPUSD at 2.0560 sl: 2.0760 tp: 2.0160

and the execution of the sell suggests it was in fact correct enven though it printed wrong

the other case is the opisite. It pronted right but failed to execute based on compare.

 
kvibert:

Sorry I have no idea what you mean by "MQL code tag (via MQL button in the toolbar)".

It's on the top of the window that you're in when you're typing a comment.




Ok, I'll do this for you.

/+------------------------------------------------------------------+
 
//| START - Check for open order conditions PROGRAM 3
//| PRINT("START - Check for open order conditions - PROGRAM 3");
//+------------------------------------------------------------------+
void CheckForOpen()
{
    double ma_fast1=0.0000;
    double ma_fast2=0.0000;
    double ma_fast3=0.0000;
    double ma_slow1=0.0000;
    double ma_slow2=0.0000;
    double ma_slow3=0.0000;
    double ma_D1=0.0000;
    double ma_D2=0.0000;
    double ma_D3=0.0000;
 
    int res;
 
//---- go trading only for first tiks of new bar
    
    if (Volume[0]>1) return;
    
    Print(" CFO FIRST TICK ");
 
//---- get Moving Average
    
    ma_fast1=iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,1);
    ma_fast2=iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,2);
    ma_fast3=iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,3);
    ma_slow1=iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,1);
    ma_slow2=iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,2);
    ma_slow3=iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,3);
    
    Print(" CHECK FOR OPEN ");
    Print(" ma_fast1 = ", ma_fast1, " ma_fast2 = ", ma_fast2, " ma_fast3 = ", ma_fast3);
    Print(" ma_slow1 = ", ma_slow1, " ma_slow2 = ", ma_slow2, " ma_slow3 = ", ma_slow3);
    
    ma_D1 = ma_fast1-ma_slow1;
    ma_D2 = ma_fast2-ma_slow2;
    ma_D3 = ma_fast3-ma_slow3;
    
    Print(" ma_D1 = ", ma_D1, " ma_D2 = ", ma_D2, " ma_D3 = ", ma_D3);
 
//---- sell conditions
    if (MathAbs(ma_D1) > ev_FlatTradeDif
        && ma_fast1 > ma_slow1
        && ma_fast2 > ma_slow2
        && ma_D1 < ma_D2
        && ma_D2 >= ma_D3)
    {
        
        if (ev_InitialStop==0)
            res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),
                          Bid,3,0,Bid-ev_TakeProfit*Point,"",MAGICMA,0,Red);
        else
            res=OrderSend(Symbol(),OP_SELL,LotsOptimized(),
                          Bid,3,Bid+ev_InitialStop*Point,
                          Bid-ev_TakeProfit*Point,"",MAGICMA,0,Red);
        return(0);
    }
 
    //---- buy conditions
    if (MathAbs(ma_D1) > ev_FlatTradeDif
        && ma_fast1 < ma_slow1
        && ma_fast2 < ma_slow2
        && ma_D1 > ma_D2
        && ma_D2 <= ma_D3)
    {
        
        if (ev_InitialStop==0)
            res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),
                          Ask,3,0,Ask+ev_TakeProfit*Point,"",MAGICMA,0,Blue);
        else
            res=OrderSend(Symbol(),OP_BUY,LotsOptimized(),
                          Ask,3,Ask-ev_InitialStop*Point,
                          Ask+ev_TakeProfit*Point,"",MAGICMA,0,Blue);
    }
    
    return (0);
}
//+------------------------------------------------------------------+
//| END - Check for open order conditions - PROGRAM 3
//| PRINT("END - Check for open order conditions - PROGRAM 3");
//+------------------------------------------------------------------+
 
kvibert:

good bad - should be 0.0065

18:50:38 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: ma_fast1 = 2.0381 ma_fast2 = 2.0377 ma_fast3 = 2.0371

18:50:38 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: ma_slow1 = 2.0317 ma_slow2 = 2.0312 ma_slow3 = 2.0307

18:50:38 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: ma_D1 = 0.0064 ma_D2 = 0.0064 ma_D3 = 0.0064

18:50:38 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: open #1 sell 0. 10 GBPUSD at 2.0560 sl: 2.0760 tp: 2.0160


Oh, I see.
Don't panic. This is a mere rounding error. Definitely not a mistake.

Try to use DoubleToStrMorePrecision() from stdlib.mqh in Print. 
 

If it is a rounding problem, try this.

    ma_fast1=NormalizeDouble(iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,1),Digits);
    ma_fast2=NormalizeDouble(iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,2),Digits);
    ma_fast3=NormalizeDouble(iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,3),Digits);
    ma_slow1=NormalizeDouble(iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,1),Digits);
    ma_slow2=NormalizeDouble(iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,2),Digits);
    ma_slow3=NormalizeDouble(iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,3),Digits);
 
wackena:

If it is a rounding problem, try this.

    ma_fast1=NormalizeDouble(iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,1),Digits);
    ma_fast2=NormalizeDouble(iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,2),Digits);
    ma_fast3=NormalizeDouble(iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,3),Digits);
    ma_slow1=NormalizeDouble(iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,1),Digits);
    ma_slow2=NormalizeDouble(iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,2),Digits);
    ma_slow3=NormalizeDouble(iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,3),Digits);


I'll give both these suggestions a try and get back to you.

Thanks Loads.

K

 
kvibert:
wackena:

If it is a rounding problem, try this.

    ma_fast1=NormalizeDouble(iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,1),Digits);
    ma_fast2=NormalizeDouble(iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,2),Digits);
    ma_fast3=NormalizeDouble(iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,3),Digits);
    ma_slow1=NormalizeDouble(iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,1),Digits);
    ma_slow2=NormalizeDouble(iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,2),Digits);
    ma_slow3=NormalizeDouble(iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,3),Digits);


I'll give both these suggestions a try and get back to you.

Thanks Loads.

K

 
Irtron:
kvibert:

good bad - should be 0.0065

18:50:38 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: ma_fast1 = 2.0381 ma_fast2 = 2.0377 ma_fast3 = 2.0371

18:50:38 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: ma_slow1 = 2.0317 ma_slow2 = 2.0312 ma_slow3 = 2.0307

18:50:38 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: ma_D1 = 0.0064 ma_D2 = 0.0064 ma_D3 = 0.0064

18:50:38 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.0D GBPUSD,H4: open #1 sell 0. 10 GBPUSD at 2.0560 sl: 2.0760 tp: 2.0160


Oh, I see.
Don't panic. This is a mere rounding error. Definitely not a mistake.

Try to use DoubleToStrMorePrecision() from stdlib.mqh in Print.


I was not able to find this Library to use this function. Please let me know how I should access it. I was able to solve both the pront and compare issues by using the suggest from wakena. please see reply to wakena.

thanks very much for taking up my problem so quickly.

K

 
kvibert:
kvibert:
wackena:

If it is a rounding problem, try this.

    ma_fast1=NormalizeDouble(iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,1),Digits);
    ma_fast2=NormalizeDouble(iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,2),Digits);
    ma_fast3=NormalizeDouble(iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,3),Digits);
    ma_slow1=NormalizeDouble(iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,1),Digits);
    ma_slow2=NormalizeDouble(iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,2),Digits);
    ma_slow3=NormalizeDouble(iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,3),Digits);


I'll give both these suggestions a try and get back to you.

Thanks Loads.

K



I tried your suggestion and it worked like a charm! My faith in MQL4 has been retsored. Actually I had little doubt it would turn out to be a user error.

This change took care of both problems.

new test results

17:44:34 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.1D GBPUSD,H4: CFO FIRST TICK
17:44:34 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.1D GBPUSD,H4: CHECK FOR OPEN
17:44:34 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.1D GBPUSD,H4: ma_fast1 = 2.0381 ma_fast2 = 2.0377 ma_fast3 = 2.0371
17:44:34 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.1D GBPUSD,H4: ma_slow1 = 2.0317 ma_slow2 = 2.0312 ma_slow3 = 2.0307
17:44:34 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.1D GBPUSD,H4: ma_D1 = 0.0064 ma_D2 = 0.0065 ma_D3 = 0.0064
17:44:34 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.1D GBPUSD,H4: CFO - SELL
17:44:34 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.1D GBPUSD,H4: open #8 sell 0. 10 GBPUSD at 2.0560 sl: 2.0760 tp: 2.0160

Wakena, thanks very much for taking up my issue so quickly!

K

 
kvibert:
kvibert:
kvibert:
wackena:

If it is a rounding problem, try this.

    ma_fast1=NormalizeDouble(iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,1),Digits);
    ma_fast2=NormalizeDouble(iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,2),Digits);
    ma_fast3=NormalizeDouble(iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,3),Digits);
    ma_slow1=NormalizeDouble(iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,1),Digits);
    ma_slow2=NormalizeDouble(iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,2),Digits);
    ma_slow3=NormalizeDouble(iMA(NULL,0,ev_SlowMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,3),Digits);




I tried your suggestion and it worked like a charm! My faith in MQL4 has been retsored. Actually I had little doubt it would turn out to be a user error.

This change took care of both problems.

new test results

17:44:34 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.1D GBPUSD,H4: CFO FIRST TICK
17:44:34 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.1D GBPUSD,H4: CHECK FOR OPEN
17:44:34 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.1D GBPUSD,H4: ma_fast1 = 2.0381 ma_fast2 = 2.0377 ma_fast3 = 2.0371
17:44:34 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.1D GBPUSD,H4: ma_slow1 = 2.0317 ma_slow2 = 2.0312 ma_slow3 = 2.0307
17:44:34 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.1D GBPUSD,H4: ma_D1 = 0.0064 ma_D2 = 0.0065 ma_D3 = 0.0064
17:44:34 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.1D GBPUSD,H4: CFO - SELL
17:44:34 2007.07.25 04:00 MA FAST SLOW DEVIATION 1.1D GBPUSD,H4: open #8 sell 0. 10 GBPUSD at 2.0560 sl: 2.0760 tp: 2.0160

Wakena, thanks very much for taking up my issue so quickly!

Great!
Why to get stuck with precision stretched to enormous number of Digits decimals?
You can make it even better - limit it to 0.

ma_fast1=NormalizeDouble(iMA(NULL,0,ev_FastMovingPeriod,0,MODE_SMMA,PRICE_CLOSE,1),0)
The only issue in your initial post was rounding error while printing the results. Print() rounds doubles to 4 digits.
The calculations themselves were perfectly fine.

I have 25 years experience in software programming and analysis.

Wakena, thanks very much for taking up my issue so quickly!

My congratulations.
Reason: