A couple questions from BugReport

 
I have received the letter of the following maintenance and have decided to answer it at a forum.

Hi,

I found 2 bugs and I am pretty sure they are bugs:

1. When you have:
double x = 0.0003/Point;
int y = x;
sometimes you get 2 and sometimes 3! Cannot convert double into int variable even with the NormalizeDouble().

2. When you use:
double margin_used_per_lot = AccountFreeMargin() - AccountFreeMarginCheck(Symbol(), OP_BUY, 1.0)
sometimes you get correct i.e. 2495.23 and sometimes you get -0.28!!!!! Which means AccountFreeMarginCheck resulting sometimes values greater than AccountFreeMargin which shoud be impossible!!!


1. I have written a special script which should reveal this mistake. This endless lopped script worked within all day, but and has not given out any mistake. Please, try it at itself.

//+------------------------------------------------------------------+
//|                                         CheckNormalizeDouble.mq4 |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                        https://www.metaquotes.net/ru/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net/ru/"
 
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
  int prevValue,currValue,counter;
  double x=0.0003;
//----
   while (!IsStopped())
      {
      currValue=x/Point;
      if (currValue!=prevValue)
         {
         Alert("currValue=",currValue,"    prevValue=",prevValue,"   counter=",counter);
         Print("currValue=",currValue,"    prevValue=",prevValue,"   counter=",counter);
         prevValue=currValue;
         }
      counter++;
      Sleep(300);   
      }   
//----
   return(0);
  }
//+------------------------------------------------------------------+
 
2. I think that you have the same number of orders for sale when you checked.
The free margin required for open one BUY order, and free margin required for open one BUY order and one SELL order(hedged both) are considered differently.
The required level for open hedged oder is show in the Contract specification/




Here is shown property for EURUSD on MQ-demo server. Value "0" means thats two hedged positions required less then 2*margin .
Run my script on the new demo account, and all can see the difference.

//+------------------------------------------------------------------+
//|                                       CheckAccountFreeMargin.mq4 |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                        https://www.metaquotes.net/ru/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net/ru/"
 
 
//+------------------------------------------------------------------+
//| return time of last time of openong or closing operation         |
//+------------------------------------------------------------------+
datetime lastTradeTime()
   {
   datetime res=0;
   int i;
   for (i=0;i<OrdersTotal();i++)
      {
      if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
         {
         if (OrderOpenTime()>res) res=OrderOpenTime();
         }
      }
 
   for (i=0;i<OrdersHistoryTotal();i++)
      {
      if (OrderSelect(i,SELECT_BY_POS,MODE_HISTORY))
         {
         if (OrderCloseTime()>res) res=OrderOpenTime();
         }
      }
   return(res);
   }
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
   int maxTrades=10,ordersCounter;
//----
   double curr_margin_used_per_lot,prev_margin_used_per_lot;
   int ticket;
   bool res;
      
   datetime delayTime=60; // 60 seconds delay between open and close
 
   if (!IsDemo()) 
      {
      Alert("This is real account!!!");
      return;
      }
   while (!IsStopped())
      {
      curr_margin_used_per_lot=AccountFreeMargin()-AccountFreeMarginCheck(Symbol(), OP_BUY, 1.0);
      if (prev_margin_used_per_lot==0) prev_margin_used_per_lot=curr_margin_used_per_lot;
      if (MathAbs(1-curr_margin_used_per_lot/prev_margin_used_per_lot)>0.2) 
         {
         Print("We have ",OrdersTotal(),": required curr margin=",curr_margin_used_per_lot,"  prev margin=",prev_margin_used_per_lot);
         }
      if (OrdersTotal()==0 && TimeCurrent()-lastTradeTime()>delayTime)
         {
         RefreshRates();
         ticket=OrderSend(Symbol(),OP_SELL,1,Bid,5,0,0,"need hedge",12345,0,Red);
         if (ticket<0) Print("Order SELL fails witt error code=",GetLastError());
         else 
            {
            ordersCounter++;
            Print("ordersCounter=",ordersCounter,"   maxTrades=",maxTrades);
            }
         }
      else
         {
         if (OrdersTotal()>0 &&TimeCurrent()-lastTradeTime()>delayTime)
            {
            for (int i=OrdersTotal()-1;i>=0;i--)
               {
               if (OrderSelect(i,SELECT_BY_POS,MODE_TRADES))
                  {
                  if (OrderType()==OP_SELL && OrderSymbol()==Symbol())
                     {
                     RefreshRates();
                     res=OrderClose(OrderTicket(),OrderLots(),Ask,5,Green);
                     }
                  }
               }
            }
         }   
      Sleep(10000);
      prev_margin_used_per_lot=curr_margin_used_per_lot;
      if (ordersCounter>=maxTrades) 
         {
         Print("Test finished");
         break;
         }
      } 
//----
   return(0);
  }
//+------------------------------------------------------------------+



 
Hi Rosh

This guy probably forgot to mention that this error only happens in tester.

The problem, I think, is that AccountFreeMargin, AccountFreeMarginCheck and MarketInfo(Symbol(), MODE_MARGINREQUIRED) use the current (today's!) rates for their calculations, which is wrong. Please see for yourself - I ran my expert a few minutes ago (see picture). As you can see these functions caculate the free margin amount, based on the real-time Bid/Ask values, which is wrong. When running in the tester they must use the simulated values for the tested period:

Files:
 
//+------------------------------------------------------------------+
//|                                        CheckAccountFunctions.mq4 |
//|                      Copyright © 2007, MetaQuotes Software Corp. |
//|                                        https://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2007, MetaQuotes Software Corp."
#property link      "https://www.metaquotes.net/"
 
//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start()
  {
//----
   string MarginLevel;
   string CommentString=StringConcatenate("Account Number = ",AccountNumber(),"n");
   CommentString=StringConcatenate(CommentString,"AccountCurrency=",AccountCurrency(),"n");
   CommentString=StringConcatenate(CommentString,"AccountCompany=",AccountCompany(),"n");
   CommentString=StringConcatenate(CommentString,"AccountName=",AccountName(),"n");
   CommentString=StringConcatenate(CommentString,"AccountServer=",AccountServer(),"n");
   CommentString=StringConcatenate(CommentString,"AccountStopoutLevel=",AccountStopoutLevel(),"n");
   CommentString=StringConcatenate(CommentString,"AccountStopoutMode=",AccountStopoutMode(),"n");
   CommentString=StringConcatenate(CommentString,"AccountBalance()=",AccountBalance(),"n");
   CommentString=StringConcatenate(CommentString,"AccountMargin=",AccountMargin(),"n");
   CommentString=StringConcatenate(CommentString,"AccountEquity=",AccountEquity(),"n");
   
   if (AccountMargin()>0) MarginLevel=StringConcatenate("MarginLevel=",DoubleToStr(AccountEquity()/AccountMargin()*100,2),"% ");
   else MarginLevel="MarginLevel=N/A";
 
   CommentString=StringConcatenate(CommentString,MarginLevel);
   Comment(CommentString);
//----
   return(0);
  }
//+------------------------------------------------------------------+

This script helps to explain Account... functions .
Drag & Drop it on a chart with opened orders.

 
Another question from beginner on MQL4

program=MetaTrader
type=0
version=4.00

when you have 40 objects & want to delete them one by one with this instruction, it cannot find the object.

int obj_total=ObjectsTotal();
string name;

for(int f=0;f<obj_total;f++)
{
name=ObjectName(f);
Print(" name ",name, " f ",f);
ObjectDelete(name);
int err=GetLastError();
if(err!=0)
{
Print("error(",err,"): ",ErrorDescription(err));
}
}

Please inform me if this is really a bug
Thank You


It is an example will work correctly if to change the order of detour of objects in a cycle from the maximal index to zero.

 
         int    obj_total=ObjectsTotal();
         string name;
 
         for(int f=obj_total-1;f>=0;f--)
         {
         name=ObjectName(f);
            Print(" name ",name, " f ",f);
            ObjectDelete(name);
            int err=GetLastError();
            if(err!=0)
            {
            Print("error(",err,"): ",ErrorDescription(err));
            }
         }

Pay attention for(int f=obj_total-1;f>=0;f--)
 
I added a several arrows to picture for more complete explain.

 
Rosh wrote >>
I added a several arrows to picture for more complete explain.

Hi,

What happen to this code? I have a working EA but when I insert the following code, my EA will not opening any position.

double MarginLevel;

MarginLevel=(AccountEquity()/(AccountMargin())*100);

Any idea?

 
azizan8:

sorry,

double MarginLevel;

MarginLevel=(AccountEquity()/(AccountMargin())*100);

You can check AccountMargin() for zero value before divding. For example:

double MarginLevel;
 
if (AccountMargin()>0) MarginLevel=(AccountEquity()/(AccountMargin())*100);
else MarginLevel = 100; // you can write another number great than zero.

Dividing by zero will stop an EA.

 
Rosh wrote >>

You can check AccountMargin() for zero value before divding. For example:


Dividing by zero will stop an EA.

Thanks. Its work fine. However, I tailor to my own EA and test it on real account and it doing well. Do you or anyone here any comment on my code? I willing to accept any comment.

if (AccountMargin()>AccountBalance()*0.30) MarginLevel=(AccountEquity()/(AccountMargin())*100);
else MarginLevel=180;
if (MarginLevel<180) EnableTrading=false;

For EnableTrading, I inserted it on open sell/buy as the following:-

//Declaration ---

bool EnableTrading=true;

//--Open Sell / Buy

if (OpenBuy && EnableTrading)
{
//------------
// Open Position Code Here
//------------
}

The main purpose of this code is to control your account from burst. However, if you feel that 180% of Margin Level is risky, you can set it on your own preference.

The coder/trader need to know what is the setback of the code when embededd into your EA. As far I noticed, you have to wait for the signal to recover maybe in a few days if your are using M30, or maybe several hours if you are using M1. However, not all EA can accept M1.

Note: This code is partial of account security.

Reason: