How to number open trades on chart

 

I'm trying to place a number next to all the open trades on a chart.

I've managed to do an EA that does this, but it fails to correct the numbering when an order is closed. The last number on chart seems to be get all screwed up. I can't figure out a way to do this. Any ideas/corrections appreciated. Simple EA attached.

I just want a 1, 2, 3 etc. in sequence for each open trade, and of course, as a new trade opens, that number is added, and as one closes, they all re-number correctly.

//+------------------------------------------------------------------+
//|                                           e-NumberOpenOrders.mq4 |
//|                      Copyright © 2011, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2011, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"

int i,e;

//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
   return(0);
  }
//+------------------------------------------------------------------+
//| expert deinitialization function                                 |
//+------------------------------------------------------------------+
int deinit()
  {
   for (e=0;e<Bars;e++)              
    {
     ObjectDelete("Trade_No"+DoubleToStr(i,0));      // Remove numbers on exit
    }
     return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {

   int TradeNo = 0;

   if (OrdersTotal() > 0) 
    {
     for(i=0; i<OrdersTotal(); i++)
      {
       if(OrderSelect(i, SELECT_BY_POS, MODE_TRADES))        // Open orders only
        {
          TradeNo ++;                                        // Calc trade number
          ObjectDelete  ("T_No" + i);                     
          ObjectCreate  ("T_No" + i, OBJ_TEXT, 0, OrderOpenTime(), OrderOpenPrice());                    
          ObjectSetText ("T_No" + i, DoubleToStr(TradeNo,0), 11, "Arial Black", Khaki);  
         }
       }  
    } 
   WindowRedraw();
   return(0);
  }
 
//+------------------------------------------------------------------+
 

The issue you have is this . . .

You have 5 orders, our EA runs and creates 5 objects . . . great, then a trade is closed at TP or SL . . . now you have 4 trades, your EA deletes 4 Objects for the 4 trades and re-creates the 4 Objects . . . but hey, what about the 5th Object ?

Create an additional loop which counts the number of Objects called "T_No" + i using a while loop . . . if that number is greater than the number of Orders you have then you need to delete the additional objects, this allows your code to be more efficient as you can re-use Objects without having to delete and then re-create them . . . you can simply use ObjectSet and ObjectSetText to re-task them.

 

Here is some constructive criticism ...

int deinit()
  {
   for (e=0;e<Bars;e++)              
    {
     ObjectDelete("Trade_No"+DoubleToStr(i,0));      // Remove numbers on exit
    }
     return(0);
  }

This won't work as you are using an index of "i" in a loop of "e"

What has Bars got to do with the number of Objects you have created?

You are unnecessarily using DoubleToStr since an int will give a string all on its own

You are using a global variable for "e" when all you need is a local variable. This is bad practice as you may do this in a subroutine and screw up another part of the code

So, here is what I would write

int deinit(){
   int end= ObjectsTotal();
   for(int e=0; e<end; e++)              
       ObjectDelete("Trade_No"+e);      // Remove numbers on exit

   return(0);
}
 
RaptorUK:

The issue you have is this . . .

You have 5 orders, our EA runs and creates 5 objects . . . great, then a trade is closed at TP or SL . . . now you have 4 trades, your EA deletes 4 Objects for the 4 trades and re-creates the 4 Objects . . . but hey, what about the 5th Object ?

Create an additional loop which counts the number of Objects called "T_No" + i using a while loop . . . if that number is greater than the number of Orders you have then you need to delete the additional objects, this allows your code to be more efficient as you can re-use Objects without having to delete and then re-create them . . . you can simply use ObjectSet and ObjectSetText to re-task them.


Thanks for your reply RaptorUK. Yea, makes sense. I've tried but failed to get all the syntax right for another loop for finding and counting just Objects with the right name.

Would it not be possible to just get the OrderDelete to look for one more instance than the number of open orders? I still can't work out how to do that either, but its a thought.

 
dabbler:

Here is some constructive criticism ...

This won't work as you are using an index of "i" in a loop of "e"

What has Bars got to do with the number of Objects you have created?

You are unnecessarily using DoubleToStr since an int will give a string all on its own

You are using a global variable for "e" when all you need is a local variable. This is bad practice as you may do this in a subroutine and screw up another part of the code

So, here is what I would write


Thanks dabbler. Yea, that makes sense to make it a int and a local variable. Still have the other problem to solve, but that made that bit neater.
 
davidb_012:

Thanks for your reply RaptorUK. Yea, makes sense. I've tried but failed to get all the syntax right for another loop for finding and counting just Objects with the right name.

Would it not be possible to just get the OrderDelete to look for one more instance than the number of open orders? I still can't work out how to do that either, but its a thought.

Following your idea, I can't even count the number of Objects of the type.

Here's my attempt that isn't compiling due to "wrong parameters count".

 if (ObjectsTotal() > 0)
   {
     int o;
     string obj_name = ("T_No"+o);
     int    obj_num;
     
     for (o=0; o<ObjectsTotal(); o++)
       {
        obj_num = 0;
        
        if (ObjectName() == ObjectName(obj_name))
          {
           obj_num ++;
          }
         
         Print ("my objects = "+obj_num);
         Print ("total objects = "+ObjectsTotal());
       }  
    }   
 

Your deinit() is wrong, if you want to delete objects, you must count down. Other useful thing is StringSubstr, to delete selectively:

   for (int j = ObjectsTotal() - 1; j >= 0; j--) {
      if (StringSubstr(ObjectName(j), 0, 4) == "T_No") {
         ObjectDelete(ObjectName(j));
      }
   }
 

Well I'm not surprised.

 if (ObjectsTotal() > 0)
   {
     int o;
     string obj_name = ("T_No"+o);
     int    obj_num;
     
     for (o=0; o<ObjectsTotal(); o++)
       {
        obj_num = 0;
        
        if (ObjectName() == ObjectName(obj_name))
          {
           obj_num ++;
          }
         
         Print ("my objects = "+obj_num);
         Print ("total objects = "+ObjectsTotal());
       }  
    }   

Let's go through it. First you have variable "o" which you declare but do not assign a value to before using it on the next line. Nasty.

Now MQL4 will assign 0 to it but most C compilers will not. You then use obj_name in a loop but only set it once outside the loop.

Then you take the function, ObjectName() and use it without the required index parameter, then compare it with the same function with a string as the parameter rather than an int.

I think you need a cup of tea, a quiet sit down, and a good think!

 
erzo:

Your deinit() is wrong, if you want to delete objects, you must count down. Other useful thing is StringSubstr, to delete selectively:

Err, I tweaked his deinit to make it correct. There is no need to count down when you are not indexing! There is no need to use StringSubstr when we created the labels and know exactly what they are called.

I find your "correction" to be over-complicated and unnecessary.

However, your use of ObjectsTotal() in the loop is better than my extra variable/#define so I am going to steal that idea and put it in my code above :-)

 
dabbler:

Well I'm not surprised.

Let's go through it. First you have variable "o" which you declare but do not assign a value to before using it on the next line. Nasty.

Now MQL4 will assign 0 to it but most C compilers will not. You then use obj_name in a loop but only set it once outside the loop.

Then you take the function, ObjectName() and use it without the required index parameter, then compare it with the same function with a string as the parameter rather than an int.

I think you need a cup of tea, a quiet sit down, and a good think!


Thanks dabbler. Appreciate the advice.

Made the changes to erzo's deinit as per yours. That's okay.

My problem still remains, numbers are added when a new trade opens, but numbers are not correctly deleted when a trade is closed.

Your suggestions

"Let's go through it. First you have variable "o" which you declare but do not assign a value to before using it on the next line. Nasty. Now MQL4 will assign 0 to it but most C compilers will not. You then use obj_name in a loop but only set it once outside the loop. Then you take the function, ObjectName() and use it without the required index parameter, then compare it with the same function with a string as the parameter rather than an int.

I think you need a cup of tea, a quiet sit down, and a good think!"

I'm sure are are correct. It's going to take a better man than me to make it work though. It's beyond my skills.

Thanks anyway.

 
dabbler:

There is no need to count down when you are not indexing! There is no need to use StringSubstr when we created the labels and know exactly what they are called.

You are absolutely right. But you must indexing because you created labels for orders that might be closed over time, and you will not find them without indexing. I found a possibly error in my code however: if an object has been deleted by user after StringSubstr check but before delete calling, it might delete another object accidentally. Correcting:
   string name;
   for (int j = ObjectsTotal() - 1; j >= 0; j--) {
      name = ObjectName(j);
      if (StringSubstr(name, 0, 4) == "T_No") {
         ObjectDelete(name);
      }
   }
Moreover: if you run this at the begining of strart(), it could clear all the old objects