Abstracting away the OrderSelect for loop

 

This is just some brain storming, I'm hoping for the community to chime in.

I feel like I've soon written this code a 1000 times in different formats, mostly with nested if statements.

int Total = OrdersTotal()-1;
for(int i = Total; i >= 0; i--)
  {
   if(OrderSelect(i, SELECT_BY_POS))
     {
      if(OrderSymbol() == Symbol_ && OrderMagicNumber() == MagicNumber_)
        {
         // Do Some Logic
        }
     }  
  }


Even tough it's only 4 active lines, the typing will add up over the years.

What would be the most elegant way to abstract it away?

So that we could focus more on the logic instead.. I'm thinking about something that looks like this:

int ProfitSum=0;
while(LoopPositions())
{
  ProfitSum += OrderProfit() + OrderSwap() + OrderCommission(); // Example code
}


The closest I can come up with right now, without spending too much time on this, is:


class CPosLoop
  {
   int               CurrentPosition;
   int               MagicNumber_;
   string            Symbol_;
   void              CPosLoop(string Symbol__, int MagicNumber__)
     {
      this.CurrentPosition = OrdersTotal()-1;     
      this.Symbol_ = Symbol__;
      this.MagicNumber_ = MagicNumber__;
     }
   bool              Loop()
     {
      while(CurrentPosition-- >= 0)
        {
         if(OrderSelect(CurrentPosition, SELECT_BY_POS))
           {
            if(OrderSymbol() == Symbol_ && OrderMagicNumber() == MagicNumber_)
              {
               return true;
              }
           }     
        }
      return false;
     }
  };



And it would be called like this in the code:

CPosLoop PosLoop(Symbol(),MagicNumber);

while(PosLoop.Loop())
{
  // Do some position logic
}


At least now it's only 2 lines and a lot less typing, depending on what variable names are chosen.

What do you guys think about this solution, do you have a more elegant way?




 
  1. Cristian Eriksson: What do you guys think about this solution, do you have a more elegant way?
    Not tested, not compiled, just typed.
    class PerOrder{ Public: virtual bool doOrder(void)=0; }
    class EachOrder
      {
    public:
       EachOrder(PerOrder& predicate, int mn=EMPTY, string sym=""){
         for(int iPos=OrdersTotal()-1; iPos >= 0; --iPos) if(
           OrderSelect(iPos, SELECT_BY_POS)
         &&(OrderMagicNumber() == mn  || MN==EMPTY)
         &&(OrderSymbol()      == sym || sym=="")
         && !predicate.doOrder() 
         ) break;
       );  // Ctor
      } // EachOrder
    class Profit public PerOrder{ 
      public:    
        double sum;   
        Profit() : sum(0){}     
        bool doOrder(){ sum += OrderProfit() + OrderSwap() + OrderCommission(); return true; }
     } // Profit 
    
    Profit totalProfit; EachOrder orders(totalProfit); PrintFormat("Total profit=%d", totalProfit.sum);
    Not tested, not compiled, just typed.
  2. Always prefer positive logic over negative.
          if(!OrderSelect(i, SELECT_BY_POS))     continue;
          if(OrderSymbol() != Symbol_)           continue;
          if(OrderMagicNumber() != MagicNumber_) continue; 
  3. OrderProfit() + OrderSwap() + OrderCommission()
    Some brokers don't use the Commission/Swap fields. Instead, they add balance entries. (Maybe related to Government required accounting/tax laws.)
              "balance" orders in account history - Day Trading Techniques - MQL4 programming forum (2017)

    Broker History
    FXCM Commission - «TICKET»
    Rollover - «TICKET»
    ? >R/O - 1,000 EUR/USD @0.52
    ? #«ticket»  N/A
    OANDA Balance update
    Financing (Swap: One entry for all open orders.)

 
William Roeder #:
  1. Not tested, not compiled, just typed. Not tested, not compiled, just typed.
  2. Always prefer positive logic over negative.

  3. Some brokers don't use the Commission/Swap fields. Instead, they add balance entries. (Maybe related to Government required accounting/tax laws.)
              "balance" orders in account history - Day Trading Techniques - MQL4 programming forum (2017)

    Broker History
    FXCM Commission - «TICKET»
    Rollover - «TICKET»
    ? >R/O - 1,000 EUR/USD @0.52
    ? #«ticket»  N/A
    OANDA Balance update
    Financing (Swap: One entry for all open orders.)

I updated my first post with some of your suggestions.

The profit calculation was just example code. But good to know that it's not always covering all brokers.

Maybe I'm missunderstanding, but I think adding a class for every kind of position logic might just add to the typing?

 
I came up with a way to make the loop reusable.
class CPosLoop
  {
   int               CurrentPosition;
   int               MagicNumber_;
   string            Symbol_;
   bool              LoopCompleted;
   void              CPosLoop(string Symbol__, int MagicNumber__)
     {
      this.CurrentPosition = OrdersTotal()-1;
      this.Symbol_ = Symbol__;
      this.MagicNumber_ = MagicNumber__;
      this.LoopCompleted = false;
     }
   bool              Loop()
     {
      if(LoopCompleted)
        {
         LoopCompleted = false;
         CurrentPosition = OrdersTotal()-1;
        }
      while(CurrentPosition-- >= 0)
        {
         if(OrderSelect(CurrentPosition, SELECT_BY_POS))
           {
            if(OrderSymbol() == Symbol_ && OrderMagicNumber() == MagicNumber_)
              {
               return true;
              }
           }
        }
      LoopCompleted = true;
      return false;
     }
  };


// Example of usage

// At the beginning of the program 
CPosLoop PosLoop(Symbol(),MagicNumber);

// Count long positions
int nLongPos = 0;
while(PosLoop.Loop())
   if(OrderType() == OP_BUY)
     nLongPos++;

// Sum total volume
double VolTot = 0;
while(PosLoop.Loop())  
  VolTot+=OrderVolume();  
  

 
Cristian Eriksson #:

...
Maybe I'm missunderstanding, but I think adding a class for every kind of position logic might just add to the typing?

Not only the loop can be generic, but also the "position" logic.