Discussion of article "The Prototype of Trade Robot" - page 2

 

I recommend to avoid this design

//------------------------------------------------------------------ CheckNewBar
bool CExpertAdvisor::CheckNewBar()          // function of checking if a new bar appears
  {
   MqlRates rt[2];
   if(CopyRates(m_smb,m_tf,0,2,rt)!=2)      // copy the bars
     { Print("CopyRates of ",m_smb," failed, no history"); return(false); }
   if(rt[1].tick_volume>1) return(false);   // check the volume 
   return(true);
  }

as processing of the previous tick may take enough time to miss the arrival of the first tick of the new bar.

respectively, it is possible to miss the opening.

It is better to bind to the time of bar opening, but for this you need to save the previous time of the zero bar for example, to compare it with the current time of the zero bar.

If it is the same, there is no new bar

If it is different, then at least a new (next) bar is opened, after which we initialise the stored time of the zero bar with the current time of the zero bar.

This construction is more reliable.

Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Свойства позиций
Документация по MQL5: Стандартные константы, перечисления и структуры / Торговые константы / Свойства позиций
  • www.mql5.com
Стандартные константы, перечисления и структуры / Торговые константы / Свойства позиций - Документация по MQL5
 

Address this in a future article:

  • *robust* (as in server-side) per-trade different-level stop-loss and take-profit orders; these are *required* to avoid issues associated with network and client program outages (prolonged network disconnects, network lag-induced slippage (and requotes), client program or operating system quits, restarts, crashes (prolonged absence of client-side software) etc); so called "virtual" orders just don't cut it and neither do non-OCO substitutes (no, it's *not* negotiable, if robustness is a requirement stop-loss and take-profit orders *must* be server-side, and if one is hit the other one *must* be removed *by the server* at the same time)
  • *robust* per-trade state recovery in case of crash; in other words, if the client/OS crashes (and automatically restarts) I want the EA to know exactly what happened with outstanding individual trades and orders in the meantime: filled, closed, still active, which associated s/l and t/p orders belong to which trade/order etc (no, writing state to disk *doesn't* cut it because there's a race condition between opening a trade and writing state to disk and client program can crash at exactly the inappropriate time; server-side order comments might do, *if* they were modifiable)

As far as I can tell MT5 only supports *1* (one) server-side s/l and t/p order *per instrument* (not per trade) and no OCO orders (OCO orders can be used to simulate per-trade s/l and t/p orders, but there's a race condition there too). Unless the above is addressed I wouldn't commit any more than $100 to trading via MT5 (simplistic single-order single-timeframe single-direction MA cross type EAs). And I'm not even sure about the $100.

 
olyakish:

I recommend to avoid this design

as processing of the previous tick may take enough time to miss the arrival of the first tick of the new bar.

respectively, it is possible to miss the opening.

It is better to bind to the time of bar opening, but for this you need to save the previous time of the zero bar for example, to compare it with the current time of the zero bar.

If it is the same, there is no new bar

If it is different, then at least a new (next) bar is opened, after which we initialise the stored time of the zero bar with the current time of the zero bar.

This design is more reliable.

I have done it this way:

bool CUniexp::checkNewBar(void)
{
   static datetime prevTime[1];
   datetime currentTime[0];
   CopyTime(_Symbol,_Period,0,1,currentTime);
   if (currentTime[0]==prevTime[0])
   {return (false);}
   else
   {
      prevTime[0] = currentTime[0];
      return (true);
   }
}
 
isNewBar
isNewBar
  • votes: 7
  • 2010.05.07
  • Prival
  • www.mql5.com
Функция анализа появления нового бара на заданном таймфрейме.
 

Compiles but debugger fails.

 loading of C:\Program Files\MetaTrader 5\MQL5\Experts\Examples\eMyEA.ex5 failed

 
Rosh:

New article The Prototype of Trade Robot is published:

Author: Алексей Сергеев


Thanks for the great article! I'm a newbie but I have a question about the code.


In the function void CExpertAdvisor::TrailingPosition(long dir,int TS), there is one line:

sl=NormalSL(dir,apr,apr,TS,StopLvl);                     // calculate Stop Loss


Should we use apr for both the second and the third argument when calling NormalSL? I thought it should be:

sl=NormalSL(dir,op,apr,TS,StopLvl);

since the second argument should be the bid/ask price for "specified" direction (i.e., the variable op) rather than the "reverse" direction (i.e., the variable apr).


Thanks!

 
echostate:


In the function void CExpertAdvisor::TrailingPosition(long dir,int TS), there is one line:

sl=NormalSL(dir,apr,apr,TS,StopLvl);                     // calculate Stop Loss


Should we use apr for both the second and the third argument when calling NormalSL? I thought it should be:

sl=NormalSL(dir,op,apr,TS,StopLvl);

no.
the second and third argument must be apr.

because the calculation of tral is derived from the price at which the position will be closed. Bid for the Buy and Ask for Sell.  function is correct.

since the second argument should be the bid/ask price for "specified" direction (i.e., the variable op) rather than the "reverse" direction (i.e., the variable apr).

should be calculated from the "reverse" direction. In this case, apr.
 
sergeev:

no.
the second and third argument must be apr.

because the calculation of tral is derived from the price at which the position will be closed. Bid for the Buy and Ask for Sell.  function is correct.

should be calculated from the "reverse" direction. In this case, apr.


Thanks for the quick reply! I thought I must be wrong.


Can I also ask in the function

double CExpertAdvisor::CountLotByRisk(int dist,double risk,double lot) // calculate lot by size of risk
  {
   if(dist==0 || risk==0) return(lot);
   m_smbinf.Refresh();
   return(NormalLot(AccountInfoDouble(ACCOUNT_BALANCE)*risk/(dist*10*m_smbinf.TickValue())));
  }

why we have a "10" between "dist" and "m_smbinf.TickValue()" in the return value? I guess "dist" is the stop loss (in terms of pips), and "m_smbinf.TickValue()" is the US dollar value per pip per lot for the currency pair. So I'm not sure why we multiply another "10" in between them.

Thanks!

 
Thanks a million.
 

Very useful article. Thanks a lot!