The application of the for loop in conjunction with ChartButtons

 

Intro.

So I have a setup whereby a chart button is displayed on the chart only from which the order was executed from.

Within the button, there is text which displays the ticket number, as well as the running profit. 

The button comes in two parts, the Static Attributes and the Fluid Attributes: the latter being the dimension and the co-ordinates of the button, with the former being the running profit/loss which will change on every tick.

The Fluid Attributes are within a for loop. This means that it should loop through all the open orders within the ledger and display the running profit/loss on every tick - so this is placed in the `OnTick` code block.

Running a test on this, it works perfectly with one open order. Upon clicking the button, it will close the order as expected.

The issue.

However, upon testing this with more than one open order -  the code only provides the position details for only one order.

I don't understand why both charts are only display the position data for one order when a for loop is supposed to run through ALL the open orders. 

See example for explanation:

Example:

I have an open order on the `EURAUD` and an open order on the `EURUSD` chart.

Both charts correctly display the button, however, the button on both charts only displays the ticket information for the `EURAUD` chart, and a random running profit/loss figure.*

*The profit figure has been calculated taking into account commissions and swap charges - but for ease of replication, I have only used the `OrderProfit()` function. 

Setup

#property copyright "Copyright 2022, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#include <ChartButtonStaticAttrs.mqh>
#include <ChartButtonFluidAttrs.mqh>

int TotalOpenOrders               =  OrdersTotal();
extern   string                           ChartID_CloseButton              =     "Liquidate";                                                   // Close Button Chart Object
extern   string                           ChartID_Breakeven                =     "Breakeven";                                                   // Breakeven Chart Object
extern   string                           ChartID_ModifyTakeProfit         =     "ChangeTPPrice";                                               // Modify TakeProfit Chart Object
extern   string                           ChartID_PipDisplayFluid          =     "FluidPipDisplay";                                             // PipDisplayFluid Chart Object        
extern   string                           ChartID_PipDisplayStatic         =     "StaticPipDisplay";                                            // PipDisplayStatic Chart Object
extern   string                           ChartID_SpreadDisplay            =     "SpreadDisplay";  

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//---
if(TotalOpenOrders > 0){
      
         for(int i = TotalOpenOrders - 1; i >=0; i--){
         
            if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)){
            
               if(OrderSymbol() == Symbol()){
               
                  if(OrderMagicNumber() == Period()){
                  
                     ChartButtonStaticAttributes();
                  
                  } else {
                  
                     continue;
                  
                  }
               
               } else {
               
                  continue;
               
               }
            
            } else {
            
               break;
            
            }
         
         }
      
      } else {
      
         //….DeleteButton
      
      }
   
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---
   
  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
//---

for(int i = TotalOpenOrders - 1; i >= 0; i--){
      
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES)){
            
         if(OrderSymbol() == Symbol()){
            
            ChartButtonFluidAttributes(clrGreen,clrCrimson,clrGray);
         
         } else {
         
            break;
         
         }
         
      } else {
                  
        break;
      
      }
      
   }
   
  } 

#ChartButtonFluidAttributes
#property copyright "Copyright 2020, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"

void ChartButtonFluidAttributes(color ProfitColor, color LossColor, color ButtonUnavailable){     
      
      ObjectSetString(0,ChartID_CloseButton, OBJPROP_TEXT,"Close Ticket #"+string(OrderTicket())+" with a "+(OrderProfit() > 0.01 ? "profit" : "loss")+" of "+AccountCurrency()+DoubleToString(OrderProfit(),2));
    
}
#ChartButtonStaticAttributes.mqh
void ChartButtonStaticAttributes(){
               
   if(ObjectFind(ChartID_CloseButton) < 0){
   
      if(!ObjectCreate(0,ChartID_CloseButton,OBJ_BUTTON,0,0,0 )){
                 
         DiagnosticMessaging("Object Draw Error","There was unfortunately an error when attempting to draw the chart object "+ChartID_CloseButton);
      
            ResetLastError();
   
      } else {
   
         ObjectSetInteger(0,ChartID_CloseButton, OBJPROP_XDISTANCE, 20);
     
            ObjectSetInteger(0,ChartID_CloseButton, OBJPROP_XSIZE, 400);
     
               ObjectSetInteger(0,ChartID_CloseButton, OBJPROP_YDISTANCE, 40);
     
                  ObjectSetInteger(0,ChartID_CloseButton, OBJPROP_YSIZE, 50);
     
                     ObjectSetInteger(0,ChartID_CloseButton, OBJPROP_CORNER,CORNER_LEFT_UPPER);
      
                        ObjectSetInteger(0,ChartID_CloseButton, OBJPROP_COLOR,clrWhite);
                                                                        
                           ObjectSetInteger(0,ChartID_CloseButton, OBJPROP_FONTSIZE,10);
   
      }
   
   } //ObjectFind
         
}

Many thanks in advance

 
TheFlyingPrussian:


The issue.

However, upon testing this with more than one open order -  the code only provides the position details for only one order.

I don't understand why both charts are only display the position data for one order when a for loop is supposed to run through ALL the open orders. 

See example for explanation:

Example:

I have an open order on the `EURAUD` and an open order on the `EURUSD` chart.

Both charts correctly display the button, however, the button on both charts only displays the ticket information for the `EURAUD` chart, and a random running profit/loss figure.*

*The profit figure has been calculated taking into account commissions and swap charges - but for ease of replication, I have only used the `OrderProfit()` function. 

Setup


Many thanks in advance

this is the same as your other thread!  

you need to supply all the code, picking at the bits you supply is making this a very long winded process...   where are you defining the object names?  have you messed up there and got duplicates? which might explain your issue for instance...

you could also add more print statements and check for errors to help you prove what is going on, in what order...

 
TheFlyingPrussian:

Many thanks in advance

lots of issues in the code above:

1) you are only creating the objects in OnInit and if there is an order, so if there is no order at that time it will fail to create the button and so everything fails after.

2) The function you call to update the button data from the orders is used a loop based upon a fixed total order count from when the OnInit was run...

 
Paul Anscombe #:

this is the same as your other thread!  

you need to supply all the code, picking at the bits you supply is making this a very long winded process...   where are you defining the object names?  have you messed up there and got duplicates? which might explain your issue for instance...

you could also add more print statements and check for errors to help you prove what is going on, in what order...

Well observed Paul - it is the same as my other tread. Is that a problem?

  1. I have supplied all the relevant code,
  2. Yes, its a long-winded process
  3. Where am I defining objects? Look above where it says "Expert Initialization Function".
  4. No, I have not "messed up and got duplicates"
  5. No, I am not only creating objects in the OnInit, however, the StaticAttributes is called from the the point in the code where the order is executed. Since this part is not relevant, it was not included because its an issue with the for loop.
  6. Your second point is not true, if you look on the OnInit section, it will check to see if there are any orders, if there are none, it will clear any buttons that are previously on the chart. The reason why I have set it up like that is if I want to reinitialise the EA onto the chart, it will continue to show the buttons as long as there is at least one open order.
  7. I have created a printed text function, and it prints all the orders, it its like it chooses when it wants to work properly

I know how my EA works, & I have done the minimal reproducible example.

Also, without doing it all for me (as this would be going into the realms of hiring a freelancer) point out to me specifically where I have gone wrong. 

 
TheFlyingPrussian #:

Well observed Paul - it is the same as my other tread. Is that a problem?

  1. I have supplied all the relevant code,
  2. Yes, its a long-winded process
  3. Where am I defining objects? Look above where it says "Expert Initialization Function".
  4. No, I have not "messed up and got duplicates"
  5. No, I am not only creating objects in the OnInit, however, the StaticAttributes is called from the the point in the code where the order is executed. Since this part is not relevant, it was not included because its an issue with the for loop.
  6. Your second point is not true, if you look on the OnInit section, it will check to see if there are any orders, if there are none, it will clear any buttons that are previously on the chart. The reason why I have set it up like that is if I want to reinitialise the EA onto the chart, it will continue to show the buttons as long as there is at least one open order.
  7. I have created a printed text function, and it prints all the orders, it its like it chooses when it wants to work properly

I know how my EA works, & I have done the minimal reproducible example.

I got to be honest, you are hard to help....  you supply bits of code and expect others to assemble include files, you say it prints diagnostic comments but it doesn't etc. in future best if you present a single executable file that shows the error without people having to assemble it.

Additionally, and this applies to many that come here, if you present code in a tidy and readable format it is a lot easier to spot the problem.

I have tided the code and the problem presents itself, you are breaking the for loop when the symbol does not match the chart....

   for(int i = TotalOpenOrders - 1; i >= 0; i--)
   {
      if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
      {
         Print("Index: " + i + "  Ticket: " + OrderTicket() + "  Symbol: " + OrderSymbol());   // I added this for clarity
         if(OrderSymbol() == Symbol())
         {
//            ChartButtonFluidAttributes(clrGreen,clrCrimson,clrGray);
            
         } 
         else
         {
            Print("Stop");    // I added this for you to understand the issue
            break;		// <---- your problem you are stopping the for loop if the symbol does not match
         }
       } 
       else 
       {
         break;  // <---- not required as the loop will end anyway
       }  
    }

so now you can get to:

for(int i = TotalOpenOrders - 1; i >= 0; i--)
{
   if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))
   {
      if(OrderSymbol() == Symbol())
      {
         ChartButtonFluidAttributes(clrGreen,clrCrimson,clrGray);
      }
   }
}