multi timeframe EA

 

Hello.

 I am thinking on a multi timeframe EA that uses indicator called parabolic_r2 (modified parabolic SAR) with the following code

void Parabolic(int TimeFrame, double& Buffer[],double& BufferUnit[])//_counts_parabolic_r2_for_all_TFs
{
  int j=1;  double d_step, d_High, d_Low, CL1;  //if (TimeFrame==0)  //  i=iBars(NULL,0)-2;  //else i=len + 100;
  int i=iBars(NULL, TimeFrame);
  for (int i1=i; i1>=0; i1--)
   {
    CL1 = iClose(NULL,TimeFrame,i1);
    if (i1==i)
     {
      Buffer[i1]=iLow(NULL,TimeFrame,i1) - 10.0*Point;
      j=1;
      d_step=step;
      d_High=iHigh(NULL,TimeFrame,i1);
      d_Low=iLow (NULL,TimeFrame,i1);
      BufferUnit[i1]=-j;
     }    else
     {
      if (CL1 > d_High)
           {
        d_High = CL1;
        if (j == 1  && d_step <= AFmax - step)
          d_step += step;
       }
      if (CL1 < d_Low)
       {
        d_Low = CL1;
        if (j == -1 && d_step <= AFmax - step) d_step += step;
       }
      if (j == 1)
             Buffer[i1] = Buffer[i1 + 1] + d_step * (d_High - (Buffer[i1 + 1]));
      else Buffer[i1] = Buffer[i1 + 1] + d_step * (d_Low - (Buffer[i1 + 1]));
      if ((Buffer[i1 + 1] < iClose(NULL,TimeFrame,i1+1) && Buffer[i1] > CL1)
       || (Buffer[i1 + 1] > iClose(NULL,TimeFrame,i1+1) && Buffer[i1] < CL1))
                {
          d_step = step;
          if (j == 1) Buffer[i1] = d_High;
          else Buffer[i1] = d_Low;
          d_Low = iClose(NULL,TimeFrame,i1);
          d_High = iClose(NULL,TimeFrame,i1);
          j = -1 * j;
        }
      BufferUnit[i1]=-j;
     }
   }   
}

 I use it both at current timeframe and at parent timeframe (here TFs) in the following way: 

int start()
{
  if (newbar==Time[0]) return(0);
  WorkingOrders();                                                                 //_checks_if_there_exist_orders_both_mkt_and_pending_of_the_current_symbol_and_magic

  Parabolic(0,   BufferSarCurrent, BufferSarCurrentUnit);                          //_calculating_current_TF_PSAR_BufferSarCurrent(1)=black;
  BufferInitialize();                                                              //_erases_all_buffer_content_for_list_of_buffers:buffers_Unit_and_ParentSAR
  ZigZag();                                                                        //_draws_zigzag_on top_of_the_waves
  if (TFs > Period())//_if_TFs_equals_current_Period_it_have_no_sense
  {
   Parabolic(TFs, BufferSar0ParentTF, BufferSar0ParentTFUnit);                     //_calculating_higher__TF_PSAR, BufferSar0ParentTF(-), not used directly, only in Project(...) function.
   Project  (TFs, BufferSarParentProj2Current, BufferSar0ParentTF, TFs/Period());  //_projecting_BufferSar0ParentTF_to_BufferSarParentProj2Current(0)=green;
   Project  (TFs, BufferSarParentProj2CurU, BufferSar0ParentTFUnit, TFs/Period()); //_projecting_BufferSar0ParentTFUnit_to_BufferSarParentProj2CurU(0)=;
   ZigZagHigherTF();                                                               //_draws_zigzag_on top_of_the_waves_of_higher_timeframe
  }

// ***code***   further operations with obtained buffers BufferSarCurrent, BufferSarCurrentUnit, BufferSarParentProj2Current, BufferSarParentProj2CurU, and ZigZags
  
  
  if (newbar != Time[0])   newbar = Time[0];//_closes_calculations_for_the_current_bar.
  return(0);
}

void Project(int TimeFrame,double& BufferTo[], double& BufferFrom[], int coefficient)//_projects_PSAR_from_higher_TF_to_current
{
  int i=iBarShift(NULL,0,iTime(NULL,TimeFrame,0),false);
  for (int j=0; j<=i; j++)
   { 
    BufferTo[j] = BufferFrom[0];
   } 
  for (int i1=0; i1<400; i1++)
   {
    for (int i2=1; i2<=coefficient; i2++)
     {
      BufferTo[i1*coefficient+i2+i]=BufferFrom[i1+1];
     }
   }
}
void BufferInitialize()  //cleans buffers for entering new values. if no cleaning it has errors(value for some bar moves to next bar when it comes).
{
  ArrayInitialize(BufferZzCurrent,0.0);
  ArrayInitialize(BufferZzCurrentUnit,EMPTY_VALUE);
  ArrayInitialize(BufferSar0ParentTFUnit,EMPTY_VALUE);
  ArrayInitialize(BufferSarParentProj2CurU,0);  
  ArrayInitialize(BufferZzParent,0.0);  
  ArrayInitialize(BufferZzParentUnit,EMPTY_VALUE);
}

 

And I have a problem. when it works real time at demo account, I have no complaints. When testing it with built-in MT4 Tester or with vHandsTrade tool, it works bad: it gets the first testing bar values for BufferSarParentProj2CurU (parent projected to current.Unit which is int +1 or -1) and uses for every other following bar. i.e., i start testing on 18 March 2015 when this buffer is -1 and it has this value for every testing bar even though that bar must be +1(and in real time it is correctly calculated as +1). can you help me, please?

here is a picture from vHandsTrade testing tool for visual testing: it draws (and calculates for EA) with bold magenta line correctly before testing start, then it does not change but must (at least it must rise as following the trend)

if there is no way of settling this multi time frame issue (but i hope there is) i would think of creating a file with data (time and value for this buffer) and then importing that data when testing at MT4Tester, but it will take much time and effort(which seems useless and may bring an error of seeing future) and I will appreciate if you advise on how to better organize that code too. I saw somewhere in the forum that programmers used to write such tools for testing when it takes much time for performing heavy indicator calculations - they make calculations once then write them somewhere and use for further backtests. but again it is much of work that seems useless for now, better to solve the problem inside the code. thank you for your time.

 
  1.   int i=iBars(NULL, TimeFrame);
      for (int i1=i; i1>=0; i1--)
       {
        CL1 = iClose(NULL,TimeFrame,i1);
    iClose(..,.., BARS) does not exist.
  2. void Parabolic(int TimeFrame, double& Buffer[],double& BufferUnit[])//_counts_parabolic_r2_for_all_TFs
    
    Why are you rewriting working code? Just call iSAR - MQL4 Documentation for the timeframe and shift you want.
  3. Your code returns BufferSar0ParentTF filled with that timeframes values. If tf is daily, one bar back is yesterdays, 5 bars back is last week. You must loop your bars, get the index for the other timeframe and fill the element with that index's values. If chart is H4, then buffer [0] .. buffer[5] is current daily value, buffer[6]..[11] is yesterdays.
    for(int iChart = Bars-1; iChart >= 0; --iChart){
       int iTF = iBarShift(NULL, TF, Time[iChart];
       buffer[iChart] = iSar(NULL, TF, ..., iTF);




 

thank you, WHRoeder

1. iBars returns (int) number of bars at the chart, let it be 500. iClose(NULL, TimeFrame, iBars) is equivalent to iClose( Symbol(), Period(), 500) - close price of the 500 bars back of the current symbol and current TF (or of another TF is TimeFrame in Parabolic(int TimeFrame,...){}  function is not 0) so it exists (and seems to work properly).

2. this Parabolic calculates in different way, so I have to use it instead of a built-in one. here is an picture with black(custom) and green(iSAR) and they differ significantly some time, especially when I use it for exit purpose, for entry it looks there is not much difference. 

3. yes, and I did it in function Project(...){} of course my code does not consider cases when some bars disappear as I do not check Time of every parent bar, but simply fill the buffers with obtained BufferSar0ParentTF&Unit values. and your code looks easier, thank you, I will try

 
danik: 1. iBars returns (int) number of bars at the chart, let it be 500. iClose(NULL, TimeFrame, iBars) is equivalent to iClose( Symbol(), Period(), 500) - close price of the 500 bars back of the current symbol and current TF (or of another TF is TimeFrame in Parabolic(int TimeFrame,...){}  function is not 0) so it exists (and seems to work properly).
Wrong. 500 bars numbered zero through 499 there is no bar 500.
 

well, it is no sense to argue if it exists or not. 

after your advise I rewrote Project() f-n and now EA works but indicator with the same code(with SetIndex... stuff) is not working correctly in visualization mode with vHandsTrade. do you have any ideas how this can be fixed?

 

WHRoeder, maybe you were rigth when telling about iBars-1 instead of iBars. I checked indicator code and iBars-2 is used. I have a problem with buffers size.

I set the size a random large enough value

double BufferSarCurrent[127];double BufferSarCurrentUnit[127];

in the head of program (where global variables are usually set) and noticed that occasionally it prints wrong value (compared to the one of indicator). I can attach a picture if necessary. I guess sth is wrong with initialization of those buffers. is there a short way to fix this problem without emulating indicator buffers? I don't want to use iCustom if possible as it increases time of tests. thank you in advance.

 

Hello again. I have another question, and it seems it deals with OOP (or maybe I am wrong:)

I want to have some number of orders, some of them "virtual" - they are waiting to be sent to market (not all conditions met), others are supposed to be sent to the market. Every bar I check conditions, if virtual orders conditions' met - I send them and probably cancell some real ones. for this purpose I think I should use array of orders, I create a class called Orders.mqh (below) and I want to add such orders to CArrayObj collection.

class Orders   																				   	{
 private:     int                     m_SymbolNumber;
	      int                     m_direction;
	      double                  m_OOP;
	      double                  m_OSL;
	      bool                    m_virtual;
	      datetime                m_date;
 public:      Orders(){         Print("OrderCreated!");             }
	      Orders(int SymNo, int dir, double OOP, double OSL)                                                                                                         {
        	 m_SymbolNumber = SymNo;         m_direction = dir;         m_OOP = OOP;         m_OSL = OSL;         m_virtual = false;         m_date = 0;             }
	      Orders(int SymNo, int dir, double OOP, double OSL, bool virt, datetime date)								                 {
        	 m_SymbolNumber = SymNo;         m_direction = dir;         m_OOP = OOP;         m_OSL = OSL;         m_virtual = virt;         m_date = date;           }
	     ~Orders() {         Print("Destructor ");		}														};

 to check how my class works I wrote a small code just to see how the class works.

#include <Orders.mqh>
#include <Arrays\ArrayObj.mqh>

datetime newBar = 0;

CArrayObj *obj;
Orders   *ord;

int OnInit()
{
   obj=new CArrayObj;
   if(obj==NULL)     {
      printf("Object create error");
      return (INIT_FAILED);
   }
   ord = new Orders();
   if(ord==NULL)     {
      printf("Object create error");
      return (INIT_FAILED);
   }
   return(INIT_SUCCEEDED);
}
void OnTick()
{
   if (TimeCurrent() > D'2015.07.01 01:00')
      {
      if (isNewBar()){
         Print("start ", TimeToStr(iTime(Symbol(),60, 0),TIME_MINUTES));
         int direction = getDirection();
         if (direction > 0){
            double tmp_OOP = iHigh(Symbol(),60, 1);
            int lowest = iLowest(Symbol(),60,MODE_LOW,3,1);
            double tmp_OSL = iLow(Symbol(),60, lowest); 	
	    ord = new Orders(1, 1, tmp_OOP, tmp_OSL, false, 0);
            obj.Add(ord);
         }
         if (direction < 0){
            double tmp_OOP = iLow(Symbol(),60, 1);
            int highest = iHighest(Symbol(),60,MODE_LOW,3,1);
            double tmp_OSL = iHigh(Symbol(),60, highest);
            obj.Add(new Orders(1, -1, tmp_OOP, tmp_OSL));
         }
         if (obj.Total() > 1){
            Print("Array has ", obj.Total(), " elements");
         }
      }
   }
}

 I didnt add functions bool isNewBar() as it is standard and getDirection(int returns +1 or -1 and has very few sence so I didn't put it here).

I have an error " 'Orders' - parameter conversion not allowed." two times and I think it is not because of my constructor(is it a problem to have a default one and two with parameters? I would like to remove a default one but how to initialize my object of Orders Class?) maybe it is because of Orders is not instanceof CObject. but how to solve this problem? thank you very much in advance!

 

I am sorry I place a post here, it is far from MTF. I will go to threads sth like "newbies look for advice" next time. and another question on the same OOP topic - it seems to me that one *ord is enough for the program, i will take them using

ord = obj.get(i);

and then rewrite it for looping over the array of orders. I used to study Java a little, all useless units are destroyed without my attention if they are not available with reference. Should I call destructor each time before I get another unit from the arrray in MQL? thank you again.

 

the problem was easy to solve. just extending Cobject is enough to fill in CArrayObj. sorry, my fault. topic is closed.

#include <Object.mqh>
class Orders : public CObject 
Reason: