View Single Post
  #103 (permalink)  
Old 09-20-2008, 09:25 PM
Michel Michel is offline
Senior Member
 
Join Date: Feb 2006
Posts: 587
Michel is on a distinguished road
What's the original problem ?

I didn't check the lastest DerkWehler's version which seems a little complex, but the original version and the Omelette's ones have both the same bug.
The original version has also a recovery bug which was fixed by Omelette, but the code to fix it has itself the same bug.
Also, as Omelette said, it's NOT reliable to backtest EAs which are calling the OrderHistory, because during the backtest the history called is the real history of the account and NOT the pseudo history generated by the backtest itself. MQ is aware of this incredible bug, but don't care about it.
Now the bug itself comes from the fact that even if the History tab of the terminal is sorted by descending CloseTime, there is no guarantee that scanning the history from the last item the first order found is the last closed one. It is always needed to check this.
the initial code is
PHP Code:
int GetLotSizeFactor()
{
   
int histotal OrdersHistoryTotal();
   if (
histotal 0)
   {
      for(
int cnt=histotal-1;cnt>=0;cnt--) // retrieve closed orders counting from the last.
      
{
         if(
OrderSelect(cnt,SELECT_BY_POS,MODE_HISTORY))
         {
            if(
OrderSymbol()==Symbol() && OrderMagicNumber() == EA_MAGIC_NUM)
            {
               if(
OrderProfit() < 0// latest order close was a loss
               
{
                  
LotSizeFactor LotSizeFactor 1;
                  return (
LotSizeFactor);
               }
               else 
// latest order closed was a win
               
{
                  
LotSizeFactor LotSizeFactor 1;
                  if (
LotSizeFactor <= 0)
                  {
                     
LotSizeFactor 1;
                  }
                  return (
LotSizeFactor);
               }
            }
         }
      }
   }
   return (
LotSizeFactor); // no trades recorded in history just return the starting number.

I would sujest to replace this sub by this one:
PHP Code:
int GetLotSizeFactor()
{
   
int histotal OrdersHistoryTotal();
   
datetime LastCloseTime;
   
bool LastIsLoss;
   if (
histotal == 0) return (LotSizeFactor); // no trades recorded in history just return the starting number.       
   
else
   {
      for(
int cnt=histotal-1;cnt>=0;cnt--) // retrieve the last closed order
      
{
         if(
OrderSelect(cnt,SELECT_BY_POS,MODE_HISTORY))
         {
            if(
OrderSymbol()==Symbol() && OrderMagicNumber() == EA_MAGIC_NUM)
            {
               if(
OrderCloseTime() > LastCloseTime)
               {
                  
LastCloseTime OrderCloseTime();
                  
LastIsLoss OrderProfit() < 0;
               }
            }
         }
      }     
      if(
LastCloseTime == 0) return (LotSizeFactor); // no trades recorded in history just return the starting number.               
      
if(LastIsLossLotSizeFactor += 1;// latest order close was a loss
      
else LotSizeFactor -= 1;// latest order closed was a win
      
if (LotSizeFactor <= 0LotSizeFactor 1;
      return (
LotSizeFactor);
   }

And it is still needed to correct the recovery code in the same manner.
The routine I would use is this one, it doesn't need to recover anything as the lot size is based on the last order directly, which I think is more reliable; it doesn't work with a size factor, but with a size unit :
PHP Code:
double GetLotSize()
{
   
datetime LastCloseTime;
   
double NewLots;
   for(
int cnt=OrdersHistoryTotal()-1;cnt>=0;cnt--) // retrieve the last closed order
   
{
      if(
OrderSelect(cnt,SELECT_BY_POS,MODE_HISTORY))
      {
         if(
OrderSymbol()==Symbol() && OrderMagicNumber() == EA_MAGIC_NUM)
         {
            if(
OrderCloseTime() > LastCloseTime)
            {
               
LastCloseTime OrderCloseTime();
               
NewLots OrderLots() - LotsUnit*(2*(OrderProfit() < 0));
            }
         }
      }
   }     
   if (
NewLots <= 0) return(LotsUnit);
   return (
NewLots);


Last edited by Michel; 09-20-2008 at 10:10 PM. Reason: correction: GetLotSize() returns a double, not an int
Reply With Quote