Save Order Highest Profit and Lowest Profit values

 

Hello, 

This is my first post here, although I have been scouring these forums, to the point where I can see the usual suspects and their valuable contribution.

To these senior posters, I wanted to take a quick second to say thank you, for your valuable advice and input

My problem is: 

I have a method which is supposed to monitor open trades, save their highest profit, and lowest profit points in a data type. I have tried, simple variables, arrays, structs, and finally class objects

For example.

I have multiple open orders of any type (BUY or SELL). These orders naturally, go through a history, where their current profit is X or Y (negative or positive). I wanted to understand the effort an order goes through, until it reaches it's take profit, or stop loss

I thought I could accomplish this with simple variables, but the naming of those variables, became a problem for me.

I create all of these data types within a function that cycles through all open orders like this:

/*
 * Check if we should close orders heading in the wrong direction
 */
void CheckForClose()
{

    for(int i=0;i<OrdersTotal();i++)
    {
        if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true)
        {
            if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
            {

                // create my data structures here
                ..

            }
        }
    }
}

I thought I would use multi dimensional arrays, but I could not make that work either. 

I then tried using class objects, since, in my day job I write PHP and Python for a living, but admittedly MQL4 is still very new to me. 

My code now looks like:

// global class declaration
class OrderStats {
    public:
        string CurrentOrderTicket; // OrderTicket();
        double CurrentProfit; // OrderProfit()
        double HighestProfit; // Highest ORderProfit() value
        double LowestProfit; // Lowest ORderProfit() value

        void Setup() {
            CurrentOrderTicket=NULL;
            CurrentProfit=0;
            HighestProfit=0;
            LowestProfit=0;
        }
};

//
// Check if we should close orders heading in the wrong direction
//
void CheckForClose()
{

    for(int i=0;i<OrdersTotal();i++)
    {
        if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true)
        {
            if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
            {

                OrderTicketStats = OrderTicket(); // I am trying to create a name for this object, so I create a string var with the OrderTicket() as it's value
                OrderStats *OrderTicketStats; // I am creating a new instance of my class, with a pointer? (sorry, I'm a total n00b) giving it the name of my OrderTicket String
                OrderTicketStats = new OrderStats(); // I am not sure why I am doing this (sorry, I'm a total n00b)
                // OrderStats* OrderTicketStats = new OrderStats(); // I am not sure why I am doing this (sorry, I'm a total n00b)
		
		// current profit and OrderTicket
                OrderTicketStats.CurrentOrderTicket = OrderTicket(); // set some form of identification to this object
                OrderTicketStats.CurrentProfit = OrderProfit(); // set current order profit

                if(OrderTicketStats.CurrentOrderTicket == OrderTicket()) {
                    if(DEBUG) {
                        Print("===================================================");
                        Print("CheckForClose ",OrderTicket(), ":", OrderTypeByName, " : First Check");
                        Print("CheckForClose ",OrderTicket(), ":", OrderTypeByName, " : CurrentOrderTicket is: ", OrderTicketStats.CurrentOrderTicket);
                        Print("CheckForClose ",OrderTicket(), ":", OrderTypeByName, " : OrderProfit is: ", OrderTicketStats.CurrentProfit);
                        Print("CheckForClose ",OrderTicket(), ":", OrderTypeByName, " : OrderProfit High is: ", OrderTicketStats.HighestProfit);
                        Print("CheckForClose ",OrderTicket(), ":", OrderTypeByName, " : OrderProfit Low is: ", OrderTicketStats.LowestProfit);
                    }

                    RefreshRates(); // i read somewhere that this is a good thing
                    
                    // highest profit
                    if(OrderTicketStats.CurrentProfit > OrderTicketStats.HighestProfit) {
                        OrderTicketStats.HighestProfit = OrderTicketStats.CurrentProfit;
                    }

                    // lowest profit
                    if(OrderTicketStats.CurrentProfit < OrderTicketStats.LowestProfit) {
                        OrderTicketStats.LowestProfit = OrderTicketStats.CurrentProfit;
                    }

		    if(DEBUG) {
    			Print("===================================================");
    			Print("CheckForClose ",OrderTicket(), ":", OrderTypeByName, " : Second Check");
    			Print("CheckForClose ",OrderTicket(), ":", OrderTypeByName, " : CurrentOrderTicket is: ", OrderTicketStats.CurrentOrderTicket);
    			Print("CheckForClose ",OrderTicket(), ":", OrderTypeByName, " : OrderProfit is: ", OrderTicketStats.CurrentProfit);
    			Print("CheckForClose ",OrderTicket(), ":", OrderTypeByName, " : OrderProfit High is: ", OrderTicketStats.HighestProfit);
    			Print("CheckForClose ",OrderTicket(), ":", OrderTypeByName, " : OrderProfit Low is: ", OrderTicketStats.LowestProfit);
		    }		

                }
                
            }
        }
    }
}

The problem I have with my code, is that I can't seem to set data to each OrderTicket instance, the effect is, that order 1 is correct, but order 2 has the values of order 1

I think this post is getting a bit long, so I'm going to stop it here. 

Thank you for your advice, and assistance

 
BUMP!
 
winstonnolan:
BUMP!

I would highly recommend that you complete a c++ tutorial if you want to learn mql. Please take no offense but it's rather apparent by your code that you are used to higher level langs that do all the memory management for you, which is going to cause havoc on MT due to memory leaks. I'm not sure what you were hoping to accomplish with your example above... just like any other language you'd have to add your objects to a collection, but there is none here. So what's happening is you're orphaning objects on the heap every time you assign a new object to an existing pointer. The only way to can do that here is if you assign the object also to something that will handle the memory for you like an MQL collection for example. Here's an example of creating dynamic objects and working with them using pointer collections.

#property strict
#property indicator_chart_window


#include <Arrays\ArrayObj.mqh>

class ProfitTracker;

ProfitTracker *g_tracker;
//+------------------------------------------------------------------+
int OnInit()
{
   g_tracker = new ProfitTracker();
   g_tracker.DisplayOnChart(true);
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
{
   g_tracker.Refresh();
   return 0;
}
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
   if(CheckPointer(g_tracker))
      delete g_tracker;
}


//+------------------------------------------------------------------+
//|
//+------------------------------------------------------------------+
template<typename T>
class vector : public CArrayObj
{
 public: 
   T operator[](int i){return At(i);}
   bool Add(T element) { return CArrayObj::Add(element);}
};
//+------------------------------------------------------------------+
//|
//+------------------------------------------------------------------+
class ProfitTicket : public CObject
{
 protected:
   double         m_current;
   double         m_highest;
   double         m_lowest;
   int            m_ticket;
 public:
   //constructor
                  ProfitTicket(const int ticket);
                 ~ProfitTicket();
   //getters
   double         Current() const { return m_current; }
   double         Highest() const { return m_highest; }
   double         Lowest()  const { return m_lowest;  }
   int            Ticket()  const { return m_ticket;  }
   
   bool           Refresh();
   string         ToString();
   virtual int    Compare(const CObject *node,const int mode=0)const override;
};

//+------------------------------------------------------------------+
//|
//+------------------------------------------------------------------+

ProfitTicket::ProfitTicket(const int ticket)
{
   m_ticket = ticket;
   m_highest= DBL_MIN_10_EXP;
   m_lowest = DBL_MAX;
}
//+------------------------------------------------------------------+
ProfitTicket::~ProfitTicket()
{
   printf("Removing ticket from tracking. Final status:: %s",ToString());
}
//+------------------------------------------------------------------+
bool ProfitTicket::Refresh()
{
   if(!OrderSelect(m_ticket,SELECT_BY_TICKET))
      return false;
   double profit = OrderProfit()+OrderSwap()+OrderCommission();
   if(profit > m_highest)
      m_highest = profit;
   if(profit < m_lowest)
      m_lowest = profit;
   m_current = profit;
   return true;
}
//+------------------------------------------------------------------+
int ProfitTicket::Compare(const CObject *node,const int mode=0)const override
{
   const ProfitTicket *other=node;
   if(this.Ticket() > other.Ticket()) return 1;
   if(this.Ticket() < other.Ticket()) return -1;
   return 0;
}
//+------------------------------------------------------------------+
string ProfitTicket::ToString()
{
   return StringFormat(
      "ticket: %d, highest: %.2f, lowest: %.2f",
      m_ticket,
      m_highest,
      m_lowest
   );
}
//+------------------------------------------------------------------+
//| profit tracker src
//+------------------------------------------------------------------+
class ProfitTracker : public CObject
{
protected:
   bool                    m_display_on_chart;
   vector<ProfitTicket*>   m_list;
   
public:  
                  ProfitTracker():m_display_on_chart(false){}
                 ~ProfitTracker()            { Comment("");}
   void           DisplayOnChart(bool flag)  { m_display_on_chart = flag;}
   void           Refresh();
};
//+------------------------------------------------------------------+
void ProfitTracker::Refresh()
{
   m_list.Sort();
   for(int i =OrdersTotal()-1;i>=0;i--)
   {
      if(OrderSelect(i,SELECT_BY_POS) && OrderType() < 2)
      {
         ProfitTicket *ticket = new ProfitTicket(OrderTicket());
         if(m_list.Search(ticket) < 0)
            m_list.InsertSort(ticket);
         else
            delete ticket;
      }
   }
   string comm = "";
   for(int i = m_list.Total()-1;i>=0;i--)
   {
      if(!m_list[i].Refresh())
         m_list.Delete(i);
      else if(m_display_on_chart)
         comm+= m_list[i].ToString()+"\r\n";
   }
   if(m_display_on_chart)
      Comment(comm);
}
 

So you can save OrderProfit() , and then overwrite the value every time a new value has been reached.

I will try to explain with pseudo code:

 

double profit_highest[ticket_number],profit_lowest[ticket_number];

    for(int i=0;i<OrdersTotal();i++)
    {
        if(OrderSelect(i,SELECT_BY_POS,MODE_TRADES)==true)
        {
            if(OrderSymbol()==Symbol() && OrderMagicNumber()==MAGICMA)
            {
             // create my data structures here
               if(OrderProfit()>profit_highest[ticket_number])
                {
                 profit_highest[ticket_number]=OrderProfit(); // Overwrite old value because Orderprofit() is higher then previous value...
                }
                
               if(OrderProfit()<profit_lowest[ticket_number])
                {
                 profit_lowest[ticket_number]=OrderProfit(); // Overwrite old value because OrderProfit() is lower then previous value...
                } 
            }
        }
    }

This way you will end up with the higerst as well as the losest order profit value.

You only have to add some order tracking functionality.

 
nicholishen:

I would highly recommend that you complete a c++ tutorial if you want to learn mql. Please take no offense but it's rather apparent by your code that you are used to higher level langs that do all the memory management for you, which is going to cause havoc on MT due to memory leaks. I'm not sure what you were hoping to accomplish with your example above... just like any other language you'd have to add your objects to a collection, but there is none here. So what's happening is you're orphaning objects on the heap every time you assign a new object to an existing pointer. The only way to can do that here is if you assign the object also to something that will handle the memory for you like an MQL collection for example. Here's an example of creating dynamic objects and working with them using pointer collections.

I am so sorry for my lack of understanding, you are 100% right. I am completely used to higher level languages, and have zero experience with C++. Nevertheless, I am here to learn, and have some understanding of programming ecommerce based systems, but, I am here to learn. Thank you very much for your example, and patience with me. I will try to structure my code better, according to your example, and post my progress here

Thank you very much, 

Winst

 
winstonnolan:

I am so sorry for my lack of understanding, you are 100% right. I am completely used to higher level languages, and have zero experience with C++. Nevertheless, I am here to learn, and have some understanding of programming ecommerce based systems, but, I am here to learn. Thank you very much for your example, and patience with me. I will try to structure my code better, according to your example, and post my progress here

Thank you very much, 

Winst

No worries, bro, and if you know of any good django tutorials - send 'em my way.

 
Marco vd Heijden:

So you can save OrderProfit() , and then overwrite the value every time a new value has been reached.

I will try to explain with pseudo code:

 

This way you will end up with the higerst as well as the losest order profit value.

You only have to add some order tracking functionality.

Thank you! Thank you so much! I will digest these replies, including yours, and post back with my progress. 

My motive for writing this code is, that i want to manage orders, apart from using a stoploss, i wanted to keep track of what orders experience with profit and loss, based on current orderprofit, highets profit, and lowest profit, + market conditions, perhaps close these orders.  

Thank you again for your valuable advice, I'm here to learn

Winst

Reason: