Attempting to improve my programming skills.

 

Hello everyone,

I found this post https://www.mql5.com/en/forum/150808

I am trying to get the example to work, but I have run into a problem with completely solving it.

I get these errors:

')' - unexpected end of program     line 159 col  6
'{' - unbalanced parentheses          line  11  col  3

Where have I gone wrong?

#define POLYLINE_MAX 30
#define INF 0
string  lineName[POLYLINE_MAX];

struct NAME{double Objects;}
Show;

string Polyline(string name,double value,color clr,int shift=0,
double indiMin=INF,double indiMax=INF,double chrtMin=INF,double chrtMax=INF)
  {
   if(!Show.Objects){
   return(""); 
   }
   static int=  LRU[POLYLINE_MAX]; 
   
   for(int iLine=0; iLine<POLYLINE_MAX; iLine++)
     {
      bool isNew=lineName[iLine]!=name; 
      if(!isNew) break;  
     }
   if(isNew)
     {
      for(iLine=0; iLine<POLYLINE_MAX; iLine++) LRU[iLine]++;
      iLine=ArrayMaximum(LRU);
      lineName[iLine]=name;
     }
   LRU[iLine]=0;
   double value00[],value01[],value02[],value03[],value04[],value05[],value06[],value07[],value08[],value09[],
   value10[],value11[],value12[],value13[],value14[],value15[],value16[],value17[],value18[],value19[],
   value20[],value21[],value22[],value23[],value24[],value25[],value26[],value27[],value28[],value29[];
   switch(iLine)
     {
   case  0: return(PLHelper(value00, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case  1: return(PLHelper(value01, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case  2: return(PLHelper(value02, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case  3: return(PLHelper(value03, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case  4: return(PLHelper(value04, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case  5: return(PLHelper(value05, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case  6: return(PLHelper(value06, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case  7: return(PLHelper(value07, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case  8: return(PLHelper(value08, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case  9: return(PLHelper(value09, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 10: return(PLHelper(value10, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 11: return(PLHelper(value11, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 12: return(PLHelper(value12, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 13: return(PLHelper(value13, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 14: return(PLHelper(value14, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 15: return(PLHelper(value15, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 16: return(PLHelper(value16, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 17: return(PLHelper(value17, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 18: return(PLHelper(value18, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 19: return(PLHelper(value19, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 20: return(PLHelper(value20, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 21: return(PLHelper(value21, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 22: return(PLHelper(value22, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 23: return(PLHelper(value23, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 24: return(PLHelper(value24, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 25: return(PLHelper(value25, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 26: return(PLHelper(value26, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 27: return(PLHelper(value27, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 28: return(PLHelper(value28, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
   case 29: return(PLHelper(value29, value, clr, iLine, isNew, shift,indiMin,indiMax,chrtMin,chrtMax));
    }
  // }  Polyline
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
   string PLHelper(double &mem[],double value0,color clr,int iLine,
                    bool isNew,int shift,double indiMin,
                    double indiMax,double chrtMin,double chrtMax)
     {
      string name=lineName[iLine];
      double price0=value0;          
      if(indiMin<INF)
        {
         if(chrtMin == INF)chrtMin = WindowPriceMin();
         if(chrtMax == INF)chrtMax = WindowPriceMax();
         price0=(value0-indiMin)/(indiMax-indiMin)*(chrtMax-chrtMin)+chrtMin;}
      datetime t0=Time[shift]; 
      static datetime timeL[POLYLINE_MAX];
      if(!isNew)
        {
         if(timeL[iLine]<Time[shift+1])
           {      // Missing bar(s), leave a gap.
            isNew=true;                                                   
           }
         else if(Time[shift]<timeL[iLine])
           {   // Redrawing earlier bars.
            isNew=true;
            for(int iObj=ObjectsTotal()-1; iObj>=0; iObj--)
              {
               string on=ObjectName(iObj);
               if(StringFind(on,name)==0) ObjectDelete(on);
              }
           }
        }
      if(isNew)
        {
         if(!ResizeBuffer(mem, 2)) 
         return("");
         mem[1] = price0; 
         static datetime timeF[POLYLINE_MAX];
         static color clrLn[POLYLINE_MAX];
         static int segNo[POLYLINE_MAX];
         timeF[iLine] = t0; 
         clrLn[iLine] = clr;
         segNo[iLine]++;                                                     
        }
      else if(clrLn[iLine]!=clr)
        {
         ArrayResize(mem,2);    // Series==true;
         mem[1] = mem[0];
         timeF[iLine] = timeL[iLine];
         clrLn[iLine] = clr;
         segNo[iLine]++;                                                     
        }
      else if(timeL[iLine]<t0)
        {                    // New bar, remember point
         if(!ResizeBuffer(mem,ArraySize(mem)+1)) return(""); 
        }
      mem[0] = price0;
      timeL[iLine] = t0;
      int iFirst = ArraySize(mem)-1;
      double priceF = mem[iFirst],
      valueF=priceF;
                                 
       if(indiMin<INF)
        {
         valueF= (priceF - chrtMin)/(chrtMax - chrtMin)*(indiMax-indiMin)+indiMin;}
      datetime Tf=timeF[iLine];                                 // One bar wide
      if(t0==Tf) Tf+=IfI(-1,+1,shift==0)*60*Period();    // to be visual
      string objName=name+"_"+RJust(segNo[iLine],3);
      TLine(objName,Tf,priceF,t0,price0,clr,valueF,value0);
      double maxError=0;
       for(int iMem=1; iMem<iFirst; iMem++)
        {
         double hight = ObjectGetValueByShift(objName, iMem+shift),
         error = MathAbs(hight - mem[iMem]);
         if(error>maxError)
         { 
          maxError=error; int iMaxError=iMem;
           }
        }
      if(maxError>=pips2dbl)
        {  // Split the line into two segments at max.
         double  priceM = mem[iMaxError],valueM=priceM;   
         if(indiMin<INF)
           {
            valueM= (priceM - chrtMin) / (chrtMax - chrtMin)*(indiMax-indiMin)+indiMin;    
           }
         TLine(objName,timeF[iLine],priceF,Time[iMaxError+shift],priceM,clr,valueF,valueM);
         ArrayResize(mem,iMaxError+1);          // Drop iFirst..(iMaxError+1)
         timeF[iLine]=Time[iMaxError+shift];
         segNo[iLine]++;
         objName=name+"_"+RJust(segNo[iLine],3);
         TLine(objName,timeF[iLine],priceM,t0,price0,clr,valueM,value0);}   // Split the line into two segments at the max.
      return(objName);
     }   // PLHelper
Shifting arrays & Filling arrays
Shifting arrays & Filling arrays
  • 2014.03.31
  • www.mql5.com
Hi i`m curious how the MT4 handles the shifting of the arrays after each tick.And here i`m mostly interested in the Volume[] Array...
 

In counting '(', ')', '{', and '}' the compilers treats them more or less as if they were the same. :(

Check each of them! But most probably (only) one of them causes the error!

Make it as your habit to write opening and closing brackets in one of theses two ways:

   // version 1
   if ( true ) {
      // do something ...
   }
   
   // version 2
   if ( true )
     {
         // do something
     }
 
Carl Schreiber:

Make it as your habit to write opening and closing brackets in one of theses two ways:


You should mention another most popular style:

// version 0
if(condition)
{
  // code
}
 

Hello again,

 Thank you both,

I am trying understand. The problem is after the "case" statements, correct?

Edit: After the "case" statements. polyline should be a return value, correct? 

 
GrumpyDuckMan: I am trying understand. The problem is after the "case" statements, correct?

Edit: After the "case" statements. polyline should be a return value, correct? 

Why create so many arrays and case conditions? Just create a single multi-dimensional array.

double value[][30];
Dynamic Array Object - Data Types - Language Basics - MQL4 Reference
Dynamic Array Object - Data Types - Language Basics - MQL4 Reference
  • docs.mql4.com
Dynamic Array Object - Data Types - Language Basics - MQL4 Reference
 
  1. Why are you modifying my polyline code? What's wrong with the original? (Other than changing dots in variable names to underscores.)
               Posted my code Why is there NO Complete EA within the Code-Base? - MQL4 and MetaTrader 4 - MQL4 programming forum It has not been adjusted for Build 600+.

  2. Fernando Carreiro: Why create so many arrays and case conditions? Just create a singlel multi-dimensional array.
    Because each array is dynamically sized. There was no classes or structures or pointers; yet it supports up to 20 independent lines. I intended to rewrite it as a class with one array but never got around to it.

  3.    if(!Show.Objects){
    This a a bool, not a structure
  4.    static int=  LRU[POLYLINE_MAX]; 
    Obviously bogus.
  5.    for(int iLine=0; iLine<POLYLINE_MAX; iLine++)
         {
          bool isNew=lineName[iLine]!=name; 
          if(!isNew) break;  
         }
    This code will not work with strict (it exports iLine and isNew outside the loop.)
 
whroeder Because each array is dynamically sized. There was no classes or structures or pointers; yet it supports up to 20 independent lines. I intended to rewrite it as a class with one array but never got around to it.

So it is old code, that never got modernised. OK understood, but I also did not realise it was your code (originally).

PS! You could have still used a single array and dynamically grown it as a whole based on the longest length needed! Not very memory efficient, but more elegant in terms of code!

 
Fernando Carreiro:

So it is old code, that never got modernised. OK understood, but I also did not realise it was your code (originally).

PS! You could have still used a single array and dynamically grown it as a whole based on the longest length needed! Not very memory efficient, but more elegant in terms of code!

Grumpy,


I think what Fernando is getting at, and correct me if I'm wrong Fernando, is that you shouldn't be learning to better your skills using examples from pre-build-600 style projects. Instead you should be learning to effectively use OOP and the (new) standard library (especially data-collections) in order to implement much more simple, small, and elegant solutions.

 
nicholishen: I think what Fernando is getting at, and correct me if I'm wrong Fernando, is that you shouldn't be learning to better your skills using examples from pre-build-600 style projects. Instead you should be learning to effectively use OOP and the (new) standard library (especially data-collections) in order to implement much more simple, small, and elegant solutions.

Actually my statement was in reply to @whroeder1, not the OP!

As for the OP, I had already suggested to him on another thread (see below), that since his coding skills are only at the beginning (not even having coded before in other languages), that he would be better served following a step-by-step method and even suggested a book or two to get him started.

However, I would NOT suggest that he start on OOP until he has properly grasped procedural coding first. OOP is just to "complicated" for those that have never coded before.

Forum on trading, automated trading systems and testing trading strategies

Account Management

Fernando Carreiro, 2017.09.09 08:47

I think you should first concentrate on learning the basics of the language, its structure, its syntax, code layout and readability, etc.

Then learn about the various functions that are available, how they work and how to use them properly.

The code you provided, will not even compile, because you are basically mixing apples, oranges, tomatoes, carrots, and anything else that fits in the basket.

For example, the OrderSelect() function is for selecting a particular Order either by Index or by Ticket Number. It does not by itself return the number of Orders of a certain type.

So, before you even think about "professional account management", first you need to learn the language, by reading the documentation and researching the example code in the CodeBase.

If you want or prefer, you can even get yourself a good book and follow it from start to end:

 
Fernando Carreiro:

Actually my statement was in reply to @whroeder1, not the OP!

As for the OP, I had already suggested to him on another thread (see below), that since his coding skills are only at the beginning (not even having coded before in other languages), that he would be better served following a step-by-step method and even suggested a book or two to get him started.

However, I would NOT suggest that he start on OOP until he has properly grasped procedural coding first. OOP is just to "complicated" for those that have never coded before.


As per usual we would disagree on that. :) I think it's (by orders of magnitude) more easy to understand how objects work than to trying to decipher a bunch of spaghetti that was written to circumvent the original language's restrictions. That's not a malicious comment directed at the author, since it's true of any old mql that uses multi-dimensional arrays instead of objects. It's just bad design by today's standards and should not be encouraged as a learning platform. 

As far as learning resources go, I had much better results by learning from C++ tutorials than MQL tutorials. Based on how much time I wasted and how long it took me to progress to the point where I am, if I had to do it over again I would've ditched the MQL tutorials and jumped straight into learning C++ first, and then later dive into the MQL docs and MQL5 codebase examples. 
 

Hello again,

I am very sorry if I have offended anyone, believe me I didn't mean to at all. I was searching the forum for code containing "Switch operators" and whroeder1 seem to be the most interesting one I found in a quick search.

Again please except my apology whroeder1, I was in no way trying rip off your code.

Reason: