Ошибка '\end_of_program' - Unbalanced left parenthesis

 
Недавно при компиляции такая ошибка после последней строки последней функции встретилась. После внимательного просмотра я ее обнаружил и исправил где-то в середине кода, совсем не в последней функции.

Вопрос разработчикам: это действительно очень трудно - отловить эту ошибку именно после той функции, в которой она встретилась, а не после окончания кода? Ведь понятно, что если после незакрытой скобки встречается объявление функции, то это уже нарушение синтаксиса... Если я чешу лабуду - приведите опровергающий пример, и я с этим смирюсь.
 
У разработчиков со стажем есть такая привычка набирать исходники - сразу ставить парные скобки. Например.
I. Вызов функции. Последовательность набор текста.
 
Шаг 1.
SomeFunction();
 
Шаг 2.
SomeFunction(param1, param2, param3, ...);
 
II. Написание if блока. Последовательность набор текста.
Шаг 1.
if ()
{
}
 
Шаг 2.
if (a < b)
{
}
 
Шаг 3.
if (a < b)
{
    // comment
    c = b - a;
}
Т.е. всегда ставятся ограничивающие скобки, а затем "кишки" внутри них. Тогда проблем со скобками практически не бывает, если не удалить часть текста.
Правда, в некоторых средах разработки, если встать курсором на одну из скобок, то парные скобки очеркиваются цветом:
 
А пример... легко.
В коде:
if (a1 < b1)
{
  // code
  c1 = a1 - b1;
}
 
if (a2 < b2)
{
  // code
  c2 = a2 - b2;
}
 
if (a3 < b3)
{
  // code
  c3 = a3 - b3;
}
Пропустим первую правую фигурную скобку (выделена цветом). По идее только мы знаем (точнее, думаем), что она должна быть здесь.
Но ведь компилятор, который обнаружит это в конце кода, мог подумать и иначе:
if (a1 < b1)
{
  // code
  c1 = a1 - b1;
 
  if (a2 < b2)
  {
    // code
    c2 = a2 - b2;
  }
 
  if (a3 < b3)
  {
    // code
    c3 = a3 - b3;
  }
}
А как это можно узнать наверняка, какой должен быть код?
 

ОК, с фигурными скобками понятно. Но я говорил о круглой скобке, парную к которой компилятор не нашел. Пардон, что не указал это в первом посте.

Ставим вопрос иначе: возможен ли в MQL4 синтаксически правильный код, в котором фигурная скобка находится между парными круглыми?

Я в этом сильно сомневаюсь. Если так, то закрывающую круглую компилятор должен легко обнаруживать не в конце программы, как сейчас, а как минимум сразу же после функции, в которой она должна быть.

Насчет приема разработчиков со стажем: я тоже так же и делаю - сразу ставлю парные (в том числе и круглые). Но, как назло, пришлось подредактировать саму формулу, и я случайно пропустил закрывающую круглую. Думаю, такая ситуация встречается не только у новичков. ..

 
Думаю, здесь Вы правы - фигурная не может быть между круглыми, потому что фигурная скобка открывает некий блок (функцию, блоки if, while и т.д.) и закрываться этот блок также должен правой фигурной скобкой. В круглых скобках указываются аргументы вызова функции или, опять же, логические условия. В общем, да, такого, на мой взгляд, быть не может.

Наверное, это место можно указать раньше, чем в конце программы. Просто до этого не дошла потребность и необходимость в редакторе у команды разработчиков.
А подсветку парных скобок IDE среда Visual Studio 2005 делает и для круглых скобок, и для квадратных. Возможно, в будущих версиях MT4 редактора появится и это.

 
И все-таки такое возможно. Пример: строка "(})", хе-хе... Правда, внутри строк эти скобки - уже не синтаксические скобки...
Кроме того, фигурные скобки, помимо блока, обрамляют также объявление массива-константы. См., например, хелп к ArrayMaximum().
 

подскажите, что это за ошибка и как ее исправить


 
max.ima: подскажите, что это за ошибка и как ее исправить

Аналогичная ошибка.

Информация неполна. Нужен полный код. Мало ли что Вы там вне этого куска наворотили.

И еще: Вы так всегда свой код оформляете? Он же практически нечитаем из-за отсутствия отступов...

 

мне нужно, что бы советник открывал сделку по пересечению МА, код есть тут: http://amadey-mf.livejournal.com/84565.html

но там и выход идет по обратному пересечению МА, а нужно по стопу, тейку, тралу

вторую часть кода взял тут: http://www.profiforex.org/pages/Learning/prog

сложил это вместе, следует сделать оговорку, я впервые работаю с кодом

вот полный код:

//+------------------------------------------------------------------+
//| MACD Sample.mq4 |
//| Copyright © 2005, MetaQuotes Software Corp. |
//| http://www.metaquotes.net/ |
//+------------------------------------------------------------------+

extern double TakeProfit = 500; 
extern double Lots = 0.1; 
extern double Stoploss = 30; 
extern double TrailingStop = 30; 
// Это переменные, которые будут 
// отображаться во время
// соединения эксперта с графиком

//+------------------------------------------------------------------+
//| |
//+------------------------------------------------------------------+
int start()
{
double a; 
int b; 
int total, ticket, cnt; 

// Просто переменные для использования в программе

if(Bars<100) 
{
Print("bars less than 100");
return(0); 
}
// Это условие проверяет, есть ли в истории графиков более 100 свечей и если нет, 
// выдает ошибку. Требуется для того, чтобы обратить ваше внимание на проблему 
// недостатка информации

if(TakeProfit<10) 
{
Print("TakeProfit less than 10");
return(0); 
}
// Это условие проверяет уровень Тейк-профита (одной из внешних переменных, 
// которая управляет уровнем фиксации прибыли. Нужен для того, чтобы проверить, не 
// выставили ли вы уровни фиксации прибыли на неразрешенном для вашего ДЦ 
// уровне. Нужен лишь для того, чтобы при НЕсрабатывании советника, вы четко знали 
// в чем здесь ошибка. Очень советую ставить. 

total=OrdersTotal();
if(total<1) 
// Эта проверка нужна для того, чтобы не открывать сразу нескольких одинаковых позиций. Если ее не будет, то, скажем, если ваш эксперт срабатывает, когда стохастик находится в зоне перекупленности, то он будет совершать сделку на каждом тике, пока не истратит всю маржу. 
// Поэтому, чтобы ограничить количество открываемых позиций, ставят данный 
// ограничитель. Если он стоит, то советник не будет открывать более определенного 
// количества позиций <х
{
// no opened orders identified
if(AccountFreeMargin()<(1000*Lots)) 
{
Print("We have no money. Free Margin = ", AccountFreeMargin());
return(0); 
}
// Еще один вспомогательный кусок кода. Если средств на счете недостаточно, он 
// выдаст ошибку. Данный кусок полностью бесполезен, если советник работает 
// в реальном времени, но очень полезен при тестинге на истории. 

// кусок кода Амадея, параметры мув
bool SellOp=false;
bool BuyOp=false;


double MAFast2=NormalizeDouble(iMA(NULL,0,MODE_SMA,PRICE_CLOSE,2),Digits); // быстрая прошлого бара
double MAFast3=NormalizeDouble(iMA(NULL,0,MODE_SMA,PRICE_CLOSE,0),Digits); // быстрая текущего бара

double MASlow2=NormalizeDouble(iMA(NULL,0,MODE_SMA,PRICE_CLOSE,2),Digits); // медленная прошлого бара
double MASlow3=NormalizeDouble(iMA(NULL,0,MODE_SMA,PRICE_CLOSE,0),Digits); // медленная текущего бара


if ( // проверка условий на покупку
(MAFast2<=MASlow2)&&
(MAFast3>MASlow3))
{
BuyOp=true;
}

// Наконец, мы добрались до самого интересного. Вместо этих иксов, надо вставить 
// условие, при котором происходит покупка. 

{
ticket=OrderSend(Symbol(),OP_BUY,Lots,Ask,3,Ask-Stoploss*Point, Ask+TakeProfit*Point ,"comment",16384,0,Green); 

// Это условия покупки. В принципе, менять здесь ничего не надо, но для расширения 
// кругозора, я расшифрую что здесь написано. Здесь сказано, что надо купить 
// (OP_BUY) текущий символ (пара валют, к графику которого прикреплен советник), 
// размер сделки Lots (переменная заданная в начале). Цена по рынку, с 
// проскальзыванием 3, и со стоп-лосом и тейк-профитом, выставленными в 
// начале, сделка будет с комментарием "comment", с определяющим числом 0, и на 
// месте покупки, на графике, будет зелененькая срелочка с определяющим кодом 
// 16384

if(ticket>0) 
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print("BUY order opened : ",OrderOpenPrice());
}
else Print("Error opening BUY order : ",GetLastError());
return(0); 
}

// Этот блок нужен только для того, чтобы записать в журнале, все ли прошло гладко. 
// Или, в противном случае, записать ошибку, из-за которой что-то не получилось. 

// Теперь тоже самое со ставкой на продажу. Вместо YYYYYYYY - условия

if ( // проверка условий на продажу
(MAFast2>=MASlow2)&&
(MAFast3<MASlow3))
{
SellOp=true;
}

{
ticket=OrderSend(Symbol(),OP_SELL,Lots,Bid,3,Bid+Stoploss*Point,Bid-TakeProfit*Point,"macd sample",16384,0,Red); 
if(ticket>0) 
{
if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES)) Print("SELL order opened : ",OrderOpenPrice());
}
else Print("Error opening SELL order : ",GetLastError());
return(0); 
}
return(0); 
}

// Теперь о выходе. Тут также ничего не изменилось, просто RRRRRRR - условие 
// закрытия сделки по BUY, ZZZZZZZZ - по SELL

for(cnt=0;cnt
//с помощью for'a перебираются все открытые пощиции
{
OrderSelect(cnt, SELECT_BY_POS, MODE_TRADES); 
if(OrderType()<=OP_SELL && // check for opened position 
OrderSymbol()==Symbol()) // check for symbol
{
if(OrderType()==OP_BUY) // long position is opened
{
// should it be closed? 
if (BuyOp) // если условия на покупку выполняются (вставка кода тест МА)
{
OrderClose(OrderTicket(),OrderLots(),Bid,3,Violet); // close position
return(0); // exit
}
// check for trailing stop
if(TrailingStop>0) 
{ 
if(Bid-OrderOpenPrice()>Point*TrailingStop) 
{
if(OrderStopLoss()
{
OrderModify(OrderTicket(),OrderOpenPrice(),Bid-Point*TrailingStop,OrderTakeProfit(),0,Green); 
return(0); 
}
}
}
}
else // Тоже самое с короткой позицией
{
// should it be closed? 
if (SellOp) // если условия на продажу выполняются (вставка кода тест МА)
{
OrderClose(OrderTicket(),OrderLots(),Ask,3,Violet); // close position
return(0); // exit
}
// check for trailing stop
if(TrailingStop>0) 
{ 
if((OrderOpenPrice()-Ask)>(Point*TrailingStop)) 
{
if((OrderStopLoss()>(Ask+Point*TrailingStop)) || (OrderStopLoss()==0)) 
{
OrderModify(OrderTicket(),OrderOpenPrice(),Ask+Point*TrailingStop,OrderTakeProfit(),0,Red); 
return(0); 
}
}
}
}
}
}
}
return(0);
}

 

Ошибок у Вас много:

Почти все они - потому, что переменные не объявлены.

Разберитесь вначале с остальными, когда последняя ошибка останется единственной.

Причина обращения: