Discussion of article "Cross-Platform Expert Advisor: Stops"

 

New article Cross-Platform Expert Advisor: Stops has been published:

This article discusses an implementation of stop levels in an expert advisor in order to make it compatible with the two platforms Metatrader 4 and Metatrader 5.

The general operation of the creation of stop levels is shown in the following figure:

General operation of creation of stop levels

As shown in the previous two flowcharts above, as soon as a trade has been successfully entered, a new COrder instance will be created representing it. After that, instances of COrderStop will be created for each of the stoploss and takeprofit levels defined. If there were no CStop instance declared on the expert advisor's initialization, this particular process would be skipped.

Author: Enrico Lambino

 

Which method should be used to set SL/TP to specific value but not as a distance from open price?

 
That would be the methods StopLossCustom and TakeProfitCustom. These methods will be discussed in the next article.
 

I tried to use few stops in my EA. Added your function manage_trades() and that's what I got after last stop activated (position closed):

2017.09.10 09:48:25.706 2017.01.03 17:50:23   failed market buy 0.00 EURUSD [Invalid volume]
2017.09.10 09:48:25.706 2017.01.03 17:50:23   CTrade::OrderSend: market buy 0.00 EURUSD [invalid volume]
2017.09.10 09:48:25.706 2017.01.03 17:50:23   position #2 is already closed, closing object..
2017.09.10 09:48:25.706 2017.01.03 17:50:23   failed market buy 0.00 EURUSD [Invalid volume]
2017.09.10 09:48:25.706 2017.01.03 17:50:23   CTrade::OrderSend: market buy 0.00 EURUSD [invalid volume]
2017.09.10 09:48:25.707 2017.01.03 17:50:23   position #2 is already closed, closing object..
2017.09.10 09:48:25.707 2017.01.03 17:50:23   failed market buy 0.00 EURUSD [Invalid volume]
2017.09.10 09:48:25.707 2017.01.03 17:50:23   CTrade::OrderSend: market buy 0.00 EURUSD [invalid volume]

Using 3 stops, all of them virtual.

That's something about lot. I use fixed lot 0.1. After first close the remaining volume 0.06. After the last close (main stop with no volume specified) I get above error.

When lot is higher it's ok. Same thing with your EA examples.

 
mbjen:

I tried to use few stops in my EA. Added your function manage_trades() and that's what I got after last stop activated (position closed):

Using 3 stops, all of them virtual.

That's something about lot. I use fixed lot 0.1. After first close the remaining volume 0.06. After the last close (main stop with no volume specified) I get above error.

When lot is higher it's ok. Same thing with your EA examples.

Make sure you are using the latest version of the library (the one attached in this article). Also, if you can attach the source code of your EA here that would greatly help.

 
Enrico Lambino:

Make sure you are using the latest version of the library (the one attached in this article). Also, if you can attach the source code of your EA here that would greatly help.


Yes, I have updated all the files with the attached to this article. But I don't know maybe you updated it once again.

Could you try with your sample stops_ha_ma2 by changing the MM to fixed lot and changing the lot size to some small value?

 
mbjen:

Yes, I have updated all the files with the attached to this article. But I don't know maybe you updated it once again.

Could you try with your sample stops_ha_ma2 by changing the MM to fixed lot and changing the lot size to some small value?

Could you post here the source code of the EA experiencing the issue? Our conversation is public, and the error you posted above is a serious issue for an EA. I would like other readers to learn from this conversation as well by giving them the opportunity to test your code.
 
Enrico Lambino:
Could you post here the source code of the EA experiencing the issue? Our conversation is public, and the error you posted above is a serious issue for an EA. I would like other readers to learn from this conversation as well by giving them the opportunity to test your code.

It's not related to my EA since I got the same error with your EA. Anyway, I have installed it to another terminal copy and it looks good now. No error anymore. Maybe there was smth wrong with my standard library or smth else...

Thank you.

 
mbjen:

It's not related to my EA since I got the same error with your EA. Anyway, I have installed it to another terminal copy and it looks good now. No error anymore. Maybe there was smth wrong with my standard library or smth else...

With a modified EA made from parts of one of the example EAs. I initially wondered what went wrong with your code. But since you mentioned that there are no errors now, well I am not quite sure what caused the problem you experienced. If you encounter it again, just let me know either here or through PM.
 

Hi Enrico,


Just wanted to point out that I found a couple of bugs in your code.  in ExpertAdvisorBase, the Time function is;

datetime CExpertAdvisorBase::Time(const int index=0)
  {
   if(index>=0)
     {
      double time[];
      if(CopyTime(m_symbol_name,m_period,index,1,time)>0)
         return(time[0]);
     }
   return(-1);
  }

When it should be as below.  The time type above is double instead of datetime.

datetime CExpertAdvisorBase::Time(const int index=0)
  {
   if(index>=0)
     {
      datetime time[];
      if(CopyTime(m_symbol_name,m_period,index,1,time)>0)
         return(time[0]);
     }
   return(-1);
  }

Also, TimesBase's Evaluate function does not pass the default value;

bool CTimesBase::Evaluate(datetime current) const

If changed to the below, it should be;

bool CTimesBase::Evaluate(datetime current) const

On compiling the Base\Order folder, the files throw lots of errors.

For example, the CreateStops function in OrderBase, below;

void COrderBase::CreateStops(CStops *stops)
  {
   if(!CheckPointer(stops)) return;
   if(stops.Total()>0)
     {
      for(int i=0;i<stops.Total();i++)
        {
         CStop *stop=stops.At(i);
         if(CheckPointer(stop)==POINTER_INVALID) continue;
         m_order_stops.NewOrderStop(GetPointer(this),stop);
        }
     }
  }

Throws 'operator=' - no one of the overloads can be applied to the function call OrderBase.mqh

'At' - object pointer expected OrderBase.mqh

The Base\Stop also has the same issues of throwing a number of errors related to Stops, Types etc.

Thanks for your good work, Shep

 
Hi Shep,
Shephard Mukachi:

Hi Enrico,


Just wanted to point out that I found a couple of bugs in your code.  in ExpertAdvisorBase, the Time function is;

When it should be as below.  The time type above is double instead of datetime.

Shephard Mukachi:

Hi Enrico,


Also, TimesBase's Evaluate function does not pass the default value;

If changed to the below, it should be;

Thank you for pointing these out. I have not noticed this until now. I will update the code.

Shephard Mukachi:

On compiling the Base\Order folder, the files throw lots of errors.

For example, the CreateStops function in OrderBase, below;

Throws 'operator=' - no one of the overloads can be applied to the function call OrderBase.mqh

'At' - object pointer expected OrderBase.mqh

The Base\Stop also has the same issues of throwing a number of errors related to Stops, Types etc.

Thanks for your good work, Shep

Yes, I am aware of this. This is still due to the forward declarations. CStop requires instances of COrder and COrderStop in its methods. The same also when you try to compile CStop. All these classes that require each other should be compiled together. It would give errors if each is compiled on its own. For example:

class Object1
{
public:
   Object2 *m_object2;
   Object1(){}
  ~Object1(){}
};

class Object2
{
public:
   Object1 *m_object1;
   Object2(){}
  ~Object2(){}
};

This will not compile. You have to declare a forward declaration so the compiler would recognize the class member m_object2 within the object1 class:

class Object2;
class Object1
{
public:
   Object2 *m_object2;
   Object1(){}
  ~Object1(){}
};

class Object2
{
public:
   Object1 *m_object1;
   Object2(){}
  ~Object2(){}
};

This is ok if Object1 and Object2 are in the same file. If they are in two separate files, then you need to make a forward declaration for Object2 on the class file of Object1, and for Object1 on the class file Object 2.Then the compiler would return no errors if you compile either file. That is true, until you add methods to either of the two classes.

The current version of the compiler recognizes forward declarations, but not the listed methods of the class declared forwardly. That is why you do not receive error messages like "CStop - declaration without type", but you receive compiler error messages for the methods such as you the one you posted above. The compiler recognizes the class, but not the methods of the class that has been forwardly declared.

Reason: