I need help finding the Unbalanced Left Paranthesis. Thanks!

 

//+------------------------------------------------------------------+
//| 2MACross.mq4 |
//| Copyright © 2010, Andrew Young|
//+------------------------------------------------------------------+
#property copyright "Andrew Young"
#include <stdlib.mqh>
//---- INPUT PARAMETERS
extern bool DynamicLotSize = true;
extern double EquityPercent = 2.0,
FixedLotSize = 0.10,
StopLoss = 50,
TakeProfit = 100;
extern int Slippage = 5,
MagicNumber = 123,
FastMAPeriod = 10,
SlowMAPeriod = 20;
//---- GLOBAL VARIABLES
int BuyTicket, SellTicket;
double UsePoint;
int UseSlippage, ErrorCode;
//---- INIT FUNCTION
int init()
{
UsePoint = PipPoint(Symbol());
UseSlippage = GetSlippage(Symbol(),Slippage);
}
//---- START FUNCTION pg. 160
int start()
{
//MOVING AVERAGES pg. 160
double FastMA = iMA(NULL,0,FastMAPeriod,0,0,0,1);
double SlowMA = iMA(NULL,0,SlowMAPeriod,0,0,0,1);
//LOT SIZE CALCULATION pg. 161
if(DynamicLotSize == true)
{
double RiskAmount = AccountEquity() * (EquityPercent / 100);
double TickValue = MarketInfo(Symbol(),MODE_TICKVALUE);
if(Point == 0.001 || Point == 0.00001) TickValue *= 10;
double CalcLots = (RiskAmount/StopLoss) / TickValue;
double LotSize = CalcLots;
}
else LotSize = FixedLotSize;
//LOT SIZE VERIFICATION pg. 161
if (LotSize<MarketInfo(Symbol(), MODE_MINLOT));
{
LotSize=MarketInfo(Sybol(), MODE_MINLOT);
}
else if(LotSize > MarketInfo(Symbol(), MODE_MAXLOT));
{
LotSize = MarketInfo(Symbol(), MODE_MAXLOT);
}
if(MarketInfo(Symbol(), MODE_LOTSTEP) == 0.1)
{
LotSize = NormalizeDouble(LotSize,1);
}
else LotSize = NormalizeDouble(LotSize,2);
//BUY ORDER pg. 161
if(FastMA > SlowMA && BuyTicket == 0)
{
//CLOSE ORDER pg. 161
OrderSelect(SellTicket, SELECT_BY_TICKET);
if(OrderCloseTime() == 0 && SellTicket > 0)
{
double CloseLots = OrderLots();
while(IsTradeContextBusy()) Sleep(10);
RefreshRates();
double ClosePrice = Ask;
bool Closed = OrderClose(SellTicket, CloseLots, ClosePrice, UseSlippage, Red);
//ERROR HANDLING pg. 161
if(Closed == false)
{
ErrorCode = GetLastError();
string ErrDesc = ErrorDescription(ErrorCode);
string ErrAlert = StringConcantenate("Close Sell Order - Error ",
ErrorCode,": ",ErrDesc);
Alert(ErrAlert);
string ErrLog = StringConcatenate("Ask: ",Ask," Lots: ",LotSize,
" Ticket: ",SellTicket);
Print(ErrLog);
}
}
}
//OPEN BUY ORDER pg. 162
while(IsTradeContextBusy()) Sleep(10);
RefreshRates();
BuyTicket = OrderSend(Symbol(), OP_BUY, LotSize, Ask, UseSlippage,0,0,"Buy Order", MagicNumber,0,Green);
//ERROR HANDLING pg. 162
if(BuyTicket == -1)
{
ErrorCode = GetLastError();
ErrDesc = ErrorDescription(ErrorCode);
ErrAlert = StringConcatenate("Open Buy Order - Error ", ErrorCode, ": ", ErrDesc);
Alert(ErrAlert);
ErrLog = StringConcatenate("Ask: ", Ask, " Lots: ", LotSize);
Print(ErrLog);
}
//ORDER MODIFICATION pg. 162
else
{
OrderSelect(BuyTicket, SELECT_BY_TICKET);
double OpenPrice = OrderOpenPrice();
//CALCULATE STOP LEVEL pg. 162
double StopLevel = MarketInfo(Symbol(), MODE_STOPLEVEL) * Point;
RefreshRates();
double UpperStopLevel = Ask + StopLevel;
double LowerStopLevel = Bid - StopLevel;
double MinStop = 5 * UsePoint;
//CALCULATE STOP LOSS AND TAKE PROFIT pg. 162
if (StopLoss > 0) double BuyStopLoss = OpenPrice - (StopLoss * UsePoint);
if (TakeProfit > 0) double BuyTakeProfit = OpenPrice + (TakeProfit * UsePoint);
//VERIFY STOP LOSS AND TAKE PROFIT pg. 163
if(BuyStopLoss > 0 && BuyStopLoss > LowerStopLevel)
{
BuyStopLoss = LowerStopLevel - MinStop;
}
if(BuyTakeProfit > 0 && BuyTakeProfit < UpperStopLevel)
{
BuyTakeProfit = UpperStopLevel + MinStop;
}
//MODIFY ORDER pg. 163
if(IsTradeContextBusy()) Sleep(10);
if (BuyStopLoss > 0 || BuyTakeProfit > 0)
{
bool TicketMod = OrderModify(BuyTicket, OpenPrice, BuyStopLoss, BuyTakeProfit, 0);
//ERROR HANDLING pg. 163
if(TicketMod == false)
{
ErrorCode = GetLastError();
ErrDesc = ErrorDescription(ErrorCode);
ErrAlert = StringConcatenate("Modify Buy Order - Error ", ErrorCode, ": ", ErrDesc);
Alert(ErrAlert);
ErrLog = StringConcatenate("Ask: ", Ask, " Bid: ", Bid, " Ticket: ", BuyTicket, " Stop: ", BuyStopLoss, " Profit: ", BuyTakeProfit);
Print(ErrLog);
}
}
SellTicket = 0;
}
//SELL ORDER pg. 164
if(FastMA < SlowMA && SellTicket == 0)
{
OrderSelect(BuyTicket, SELECT_BY_TICKET);
if(OrderCloseTime() == 0 && BuyTicket > 0)
{
CloseLots = OrderLots();
while(IsTradeContextBusy()) Sleep(10);
RefreshRates();
ClosePrice = Bid;
Closed = OrderClose(BuyTicket, CloseLots, ClosePrice, UseSlippage, Red);
//ERROR HANDLING pg. 164
if(Closed == false)
{
ErrorCode = GetLastError();
ErrDesc = ErrorDescription(ErrorCode);
ErrAlert = StringConcatenate("Close Buy Order - Error ", ErrorCode, ": ", ErrDesc);
Alert(ErrAlert);
ErrLog = StringConcatenate("Bid: ", Bid, " Lots: ", LotSize, " Ticket: ", BuyTicket);
Print(ErrLog);
}
}
while(IsTradeContextBusy()) Sleep(10);
RefreshRate();
SellTicket = OrderSend(Symbol(), OP_SELL, LotSize, Bid, UseSlippage, 0, 0, "Sell Order", MagicNumber, 0, Red);
//ERROR HANDLING pg. 164
if(SellTicket == -1)
{
ErrorCode = GetLastError();
ErrDesc = ErrorDESCRIPTION(ErrorCode);
ErrAlert = StringConcatenate("Open Sell Order - Error ", ErrorCode, ": ", ErrDesc);
Alert(ErrAlert)
ErrLog = StringConcatenate("Bid: ", Bid, " Lots: ", LotSize);
Print(ErrLog);
}
else
{
OrderSelect(SellTicket, SELECT_BY_TICKET);
OpenPrice = OrderOpenPrice();
StopLevel = MarketInfo(Symbol(), MODE_STOPLEVEL) * Point;
RefreshRates();
UpperStopLevel = Ask + StopLevel;
LowerStopLevel = Bid - StopLevel;
MinStop = 5 * UsePoint;
if(StopLoss > 0) double SellStopLoss = OpenPrice + (StopLoss * UsePoint);
if(TakeProfit > 0 double SellTakeProfit = OpenPrice - (TakeProfit * UsePoint);
if(SellStopLoss > 0 && SellStopLoss < UpperStopLevel)
{
SellStopLoss = UpperStopLevel + MinStop;
}
if(SellTakeProfit > 0 && SellTakeProfit > LowerStopLevel)
{
SellTakeProfit = LowerStopLevel - MinStop;
}
if(IsTradeContextIsBusy()) Sleep(10);
if(SellStopLoss > 0 || TakeProfit > 0)
{
TicketMod = OrderModify(SellTicket, OpenPrice, SellStopLoss, SellTakeProfit, 0);
//ERROR HANDLING pg. 165
if(TicketMod == false)
{
ErrorCode = GetLastError();
ErrDesc = ErrorDecription(ErrorCode);
ErrAlert = StringConcatenate("Modify Sell Order - Error ", ErrorCode, ": ", ErrDesc);
Alert(ErrAlert);
ErrLog = StringConcatenate("Ask: ", Ask, " Bid: :", Bid, " Ticket: ", SellTicket, " Stop:", SellStopLoss, " Profit:", SellTakeProfit);
Print(ErrLog);
}
}
}
BuyTicket = 0;
}
return(0);
}

//PIP POINT FUNCTION pg. 166
double PipPoint(string Currency)
{
int CalcDigits = MarketInfo(Currency, MODE_DIGITS);
if(CalcDigits == 2 || CalcDigits == 3) double CalcPoint = 0.01;
else if(CalcDigits == 4 || CalcDigits == 5) CalcPoint = 0.0001;
return(0);
}

//GET SLIPPAGE FUNCTION
int GetSlippage(string Currency, int SlippagePips)
{
int CalcDigits = MarketInfo(Currency, MODE_DIGITS);
if(CalcDigits == 2 || CalcDigits == 4) double CalcSlippage = SlippagePips;
else if(CalcDigits == 3 || CalcDigits == 5) CalcSlippage = SlippagePips * 10;
return(CalcSlippage);
}



YOU ARE GOING TO HAVE TO SEE THE ATTACHMENT BECAUSE USING SRC DOESNT WORK BECAUSE IT SAYS TEXT TO LONG. THANKS.

Files:
2macross.mq4  11 kb
 

...orz

Files:
2macross_1.mq4  11 kb
 
YOU ARE GOING TO HAVE TO SEE THE ATTACHMENT BECAUSE USING SRC DOESNT WORK BECAUSE IT SAYS TEXT TO LONG. THANKS.

For long code use attachments. Pasting via SRC should be used for short code snippets only...

 
gordon wrote >>

For long code use attachments. Pasting via SRC should be used for short code snippets only...


Good to know, That works better anyway


fai: Thanks I really appreciate seeing my file! Thank you very much.

 

Hi,
I'm a NuB as well and relate only too well to your plight and frustration.

1 - The thing that initially gave me the insight that helped me considerably is that I learned from someones comments that where the error is shown in the program is NOT usually where the problem is located in these incidences! I hope that they introduce this feature in MQL5, but for now..... This made a tremendous amount of difference as initially I was only looking for the error in and around the line that the MQL4 editor marked but it was in a different location altogether.

The MQL4 editor does this in others instances as well.

When you get an error message that there is a Semi-Colon ';' missing, it needs to be in front of or above where the editor puts the cursor at, usually at the end of the preceding line.

2 – Though it makes no difference to the computer what the physical layout of the program is so long as it is syntactically correct, it makes a huge difference to us. Especially us NuBs in trying to locate such problems. When laid out correctly, it is very readily easier to ‘compartmentalize’ the code.

3 - It makes it much easier to figure out what the program is doing as the layout itself is in some senses 'documenting' the program for you

4 – With the code indented and listed out in proper fashions, it allows you to do 2 things quite readily:

A – Match the pairs of the braces up readily and thus spot the extra/missing one.

/*

B – If you are still unable to find it, go through the compartmentalized code and one at a time and /* Remark Out */ each section until you find the section that the pairs are out of balance. You need to be careful in this as it IS very easy to temporarily ‘disappear’ a section with unbalanced braces in it that will through you off even worse. If when you compile it and it still tells you there is an error, just moving either the opening or closing group rem functions /* <=-=-=> */ then it is indicative of the error location. But be aware of this! If you are sure one of your rem'd out sections has balanced pairs of braces, then it has to be else where. Here again with the code laid out properly, it is very easy to ascertain where each group with balanced braces in them are.

If you want, you can just start at the top of the code and move the closing rem mark ==> */ down to the next section until you don't get any errors on compilation. Then move the 'opening rem mark ==> '/*' down until you just rem out the last section with the closing 'group rem mark' '*/' and if it complies ok, then you are now in the ball park and know where to look.

*/

In case you have not encountered and are familiar with the technique used to ‘remark out’ whole sections, I used it above with section B.

Everything after the /* and up to the */ has now become 'documentation' that the program ignores. Be VERY aware that these MUST be used in pairs as well. You can not 'nest them'! Be sure to be aware of them and not leave a third one in the middle someplace that is going to cause problems. The color is only there to make it easier for you in this example.

Also, remember that the braces ARE functional and are used in pairs to ‘group’ functional sections of code together.

If I still can't find my errant brace, I slowly and carefully scroll through the code and first count the 'left hand braces' - '{' as they scroll into or out of view at the top or bottom of the window.
Then I do the same with the 'right hand' braces: '}'
Here again, if you have been able to narrow it down to a specific section, then it is much easier and faster to find and fix the errant brace.

I hope this helps!
Good luck.

/*
Where did my SRC go???
It was here with the SRC = Source Code
Section a minute ago!
*/


Here is a good example of how a well formatted section of code that is well laid out which you can readily see the advantages of.


 RefreshRates();

double dLotsOptimized()
  {
   double dLot=dLots;
   int    iOrders=HistoryTotal(); // history orders total
   int    iLosses=0;              // number of losses orders without a break

//---- select lot size
   dLot=NormalizeDouble(AccountFreeMargin()*dMaximumRisk/1000.0,1);

//---- calculate number of lossing orders without a break
   if(dDecreaseFactor>0)
     {
      for(int i=iOrders-1;i>=0;i--)
        {
         if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false)
          { 
           Print(sTradeComment," Error in history!");
           break;
          }
         if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL) continue;
         //----
         if(OrderProfit()>0) break;
         if(OrderProfit()<0) iLosses++;
        }
      if(iLosses>1) dLot=NormalizeDouble(dLot-dLot*iLosses/dDecreaseFactor,1);
     }

//---- return lot size
   if(dLot<0.1) dLot=0.1;
   return(dLot);
  }

// ==== NOW COMPARE IT TO THIS: =================================

RefreshRates();
double dLotsOptimized()
{double dLot=dLots;
int iOrders=HistoryTotal(); // history orders total
int iLosses=0;// number of losses orders without a break
dLot=NormalizeDouble(AccountFreeMargin()*dMaximumRisk/1000.0,1);
if(dDecreaseFactor>0)
{
for(int i=iOrders-1;i>=0;i--){
if(OrderSelect(i,SELECT_BY_POS,MODE_HISTORY)==false){ 
Print(sTradeComment," Error in history!");
break;}
if(OrderSymbol()!=Symbol() || OrderType()>OP_SELL) continue;
if(OrderProfit()>0) break;
if(OrderProfit()<0) iLosses++;
}
if(iLosses>1) dLot=NormalizeDouble(dLot-dLot*iLosses/dDecreaseFactor,1);}
if(dLot<0.1) dLot=0.1;
return(dLot);}

/* ^^^^^^^^^^^^^ Quite the difference eh? ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 
You tell me, which is going to be 
easier to trouble shoot and find errors in?
*/



 
My preference is concise for even more readability:
if(dDecreaseFactor>0) {
   for(int i = OrdersTotal() - 1; i >= 0; i--) if (
      OrderSelect(i, SELECT_BY_POS)         // Only my orders w/
   && OrderMagicNumber()  == MagicNumber    // my magic number
   && OrderSymbol()       == Symbol() ) {   // and period and symbol
       if(OrderType()>OP_SELL) continue;
       //----
       if(OrderProfit()>0) break;
       if(OrderProfit()<0) iLosses++;
    }
    if(iLosses>1) dLot=NormalizeDouble(dLot-dLot*iLosses/dDecreaseFactor,1);
}
I also use notepad2 for syntax highlighting, code folding. I can easily search for the open parenthesis and see the corresponding close highlighted.
 
HRoeder wrote >>
My preference is concise for even more readability: I also use notepad2 for syntax highlighting, code folding. I can easily search for the open parenthesis and see the corresponding close highlighted.

I utilized an example from the code base here.

I definitely versus strongly prefer all of the braces: { & } all on the left side with equal indentations for corresponding braces. They stand out MUCH better and more readily and are much easier to spot the 'pairs' of them than putting some of them at the end of some lines of code.

I don't indent the lines of code as much as the example from the code base here in the MQL4.Com forum, but am working towards it as likewise it very readily gives indications of the program structure and is much easier to readily understand it.

You are likely much more experienced than either myself or the person that posted the initial topic and subject and thus don't need the code from as readily as the first of my examples, but to us NuBs it is definitely much easier to fathom and understand the structure when laid out as in the initial layout copied and pasted from MQL4.Com here.

Either way, one thing for SURE is the fact that both yours and my initial example as opposed to the second version with no indicative formatting and structure. Which is Very similar to the person's original postings and takes a LOT more wasted time, energy and frustration to understand: regardless if it the inexperienced author or someone looking at the code and trying to assist in trouble shooting it. When formatted and laid out as in my 1st example, it VERY readily is indicative of the proper structure and what and where the functions are grouped as opposed to .WHRoeder's code structure which basically has none and thus makes it a LOT more difficult and time consuming to readily find and figure out the function groupings.

WHR: the first example from MQL4.Com's code base IS considered to be the 'proper way' to format such things for the (obvious) reasons stated here and looking at all three of our examples it IS readily much more accessible and to find out the separate functions much easier and to troubleshoot and find problems in. Adopting this 'proper structure' right from the start and learning the 'proper' way of formatting code will save you MANY countless hours of very of frustrating and waste of time. Especially when you are a NuB like myself. It separates functions into ready made groups that are much easier to understand and figure out there function is as well as. I also strongly suggest at this point int time that you '//' document the program by providing a description of the entire functional groups and functions so that you can find specif areas ASAP. You may eventually get proficient enough that you will be able to do this without the documentation within programs. Especially if you have not used the EAs etc for some time it will make it much easier for you to remember and get up to full speed with them. But even there if you have a problem and need help with it, it will make assisting you much more readily and easier etc. and you will find others much more readily assist you as they can very quickly what the different functions are and find he problems problems You may do the same as I do in that you go though and edit the 'remarks' so that they are more concise and comprehensible.

 
WHRoeder:
My preference is concise for even more readability: I also use notepad2 for syntax highlighting, code folding. I can easily search for the open parenthesis and see the corresponding close highlighted.

Thanks for the notepad2 tip. I thought you meant notepad++... which has been a lifesaver (of brace-matching) for me... :) @ FourX & Subgenius : you should definitely try if you haven't...

, you might also want to check this post on FF.