помогите найти ошибку в советнике - страница 2

 
drknn >>:


Список ордеров лежит в массиве. Поскольку первым элементом является тот, который в нулевой ячейке массива, то последний ордер ляжет в ячейку с номером = OrdersTotal()-1

Пусть в рынке три ордера. Первый лежит в нулевой ячейке массива, содержащего список ордеров, второй - в первой, третий - во второй. Таким образом, если от OrdersTotal() не отнять единицу, то счётчик цикла будет проверять ордер в ячейке с индексом = 3, так как OrdersTotal() вернёт число три.

Конструкция if (OrderSelect())... тоже не желательна, так как не показывает причину, почему ордер нельзя выбрать, если такой глюк возникает. Правильнее была бы конструкция типа:

вот за это спасибо... может там и была ошибка при выборе а какая не ясно... теперь буду использовать... :)
 
Michelangelo >>:
вот за это спасибо... может там и была ошибка при выборе а какая не ясно... теперь буду использовать... :)


Скорее всего ордер оставался потому, что Вы использовали цикл for для закрытия рыночных ордеров. Если это так, то могу сказать однозначно, что для закрытия всех рыночных ордеров лучше использовать цикл while с командой RefreshRates(), которая должна идти первой на каждой итерации этого цикла. Почему так?

Посмотрим что произойдёт на быстром рынке при использовании цикла for для закрытия всех поз. Итак, счётчик цикла проинициализирован правильно. Пусть у нас только бай-ордера и пусть их у нас пять штук. Инициализируя текущим бидом цену закрытия ордера, даже если мы использовали  RefreshRates(), пока сервер раздумывал, пришла новая котировка и закрытие ордера было отвергнуто. Советник в цикле понял, что ордер, который стоял на позиции 4 (последний ордер в списке) закрыть не удалось, но текущая итерация цикла закончилась. Поэтому он уменьшает счётчик на 1 и переходит к ордеру, который стоит в ячейке массива с индексом три. Как видим, последний ордер уже закрыть не удастся. НО!

Если использовать конструкцию типа while(OrdersTotal()>0){}, то цикл будет выполняться до тех пор, пока все ордера ни будут закрыты.

Аккуратнее с циклом while() - повесить советника - раз плюнуть.

 
drknn >>:


Скорее всего ордер оставался потому, что Вы использовали цикл for для закрытия рыночных ордеров. Если это так, то могу сказать однозначно, что для закрытия всех рыночных ордеров лучше использовать цикл while с командой RefreshRates(), которая должна идти первой на каждой итерации этого цикла. Почему так?

Посмотрим что произойдёт на быстром рынке при использовании цикла for для закрытия всех поз. Итак, счётчик цикла проинициализирован правильно. Пусть у нас только бай-ордера и пусть их у нас пять штук. Инициализируя текущим бидом цену закрытия ордера, даже если мы использовали RefreshRates(), пока сервер раздумывал, пришла новая котировка и закрытие ордера было отвергнуто. Советник в цикле понял, что ордер, который стоял на позиции 4 (последний ордер в списке) закрыть не удалось, но текущая итерация цикла закончилась. Поэтому он уменьшает счётчик на 1 и переходит к ордеру, который стоит в ячейке массива с индексом три. Как видим, последний ордер уже закрыть не удастся. НО!

Если использовать конструкцию типа while(OrdersTotal()>0){}, то цикл будет выполняться до тех пор, пока все ордера ни будут закрыты.

Аккуратнее с циклом while() - повесить советника - раз плюнуть.

вешал... :)

ни когда не использовал while для закрытия ордеров, попробую... для открытия, модификации, получения сигналов использовал... надо будет завтра вставить испробывать... :)

 
// =================== Close_All() =======================
// функция закрывает все рыночные и отложенные ордера
// ===========================================================
void Close_All(bool Delete_Otlozh,int MAGIC, int Prosk){
        string  SMB=Symbol();
        int     Ticket=0;
        double  PriseAsk=0,PriseBid=0;
        double  Lot=0,MinTiskSize,PNT;
        int     DGS,Proskalz;
        while(SchBuy(MAGIC)+SchSell(MAGIC)>0){
                for (int i=OrdersTotal()-1;i>=0;i--){
                        if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)){
                                Alert("Ошибка ", GetLastError(), " при выборе ордера номер ",i," по паре ",SMB);
                        }
                        else {
                                if(OrderSymbol()!=Symbol() || OrderMagicNumber()!=MAGIC){ continue;}
                                RefreshRates();
                                DGS=MarketInfo(SMB,MODE_DIGITS);
                                MinTiskSize=MarketInfo(SMB,MODE_TICKSIZE);// минимальный шаг тика
                                PNT=MarketInfo(SMB,MODE_POINT);
                                Proskalz=NormalizeDouble(Prosk*MinTiskSize/PNT,0);
                                PriseAsk=MarketInfo(SMB,MODE_ASK);
                                PriseAsk=NormalizeDouble(PriseAsk,DGS); 
                                PriseBid=MarketInfo(SMB,MODE_BID);
                                PriseBid=NormalizeDouble(PriseBid,DGS); 
                                Ticket=OrderTicket();
                                Lot=OrderLots();
                                if(OrderType()==OP_BUY){
                                        if(!OrderClose(Ticket,Lot,PriseBid,Proskalz,CLR_NONE)){
                                                Alert("Ошибка ", GetLastError(), " при закрытии Buy-ордера номер ",Ticket," по паре ",SMB);
                                        }
                                }  
                                if(OrderType()==OP_SELL){
                                        if(!OrderClose(Ticket,Lot,PriseAsk,Proskalz,CLR_NONE)){
                                                Alert("Ошибка ", GetLastError(), " при закрытии Sell-ордера номер ",Ticket," по паре ",SMB);
                                        }
                                }  
                                 
                        }
                }
        }
}
// ===========================================================

// =================================================================================================
// ************************* Счётчики ордеров ******************************************************
// =================================================================================================


//=========== SchBuy()  ===============================
//  Функция возвращает количество Buy-ордеров
//   SchBuy      - счётчик Buy ордеров
//-----------------------------------------------------------
int SchBuy(int MAGIC){
  string SMB=Symbol();
  int SchBuy=0;
  for (int i=OrdersTotal()-1;i>=0;i--) {
    if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {WriteError(i);}
    else {
      if(OrderSymbol()!= SMB || OrderMagicNumber()!= MAGIC){ continue;}
      if(OrderType()==OP_BUY){ 
        SchBuy++;
      }  
    }
  }
  return(SchBuy);
}                  
//==================================================================================================

//=========== SchSell()  ===============================
//  Функция возвращает количество Sell-ордеров
//  SchSell  - счётчик Sell ордеров
//-----------------------------------------------------------
int SchSell(int MAGIC){
  string SMB=Symbol();
  int SchSell=0;
  for (int i=OrdersTotal()-1;i>=0;i--){
    if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {WriteError(i);}
    else {
      if(OrderSymbol()!=SMB || OrderMagicNumber()!=MAGIC){ continue;} 
      if(OrderType()==OP_SELL){
        SchSell++;
      }
    }
  }
 return(SchSell);     
}                  
//==================================================================================================
 
drknn >>:

вопрос... почти в тему... правильно ли я понимаю что в Ask и Bid хранятся тока что пришедшие цены?

и при RefreshRates() обновляются именно они... ?

 
Michelangelo >>:

вопрос... почти в тему... правильно ли я понимаю что в Ask и Bid хранятся тока что пришедшие цены?

и при RefreshRates() обновляются именно они... ?


Справочник MQL4 - Предопределенные переменные 

double Ask

Последняя известная цена продажи (запрашиваемая цена) текущего инструмента. Для обновления необходимо использовать функцию RefreshRates().

bool RefreshRates( )
Обновление данных в предопределенных переменных и массивах-таймсериях. Эта функция используется, когда эксперт или скрипт производит вычисления в течение долгого времени и нуждается в обновленных данных. Возвращается TRUE, если данные обновлены, иначе FALSE. Данные могут не обновиться только по той причине, что они соответствуют текущему состоянию клиентского терминала. Эксперты и скрипты работают с собственной копией исторических данных. Копия данных по текущему инструменту создается при первоначальном запуске эксперта или скрипта. При каждом следующем запуске эксперта (напомним, что скрипт выполняется однократно и не зависит от приходящих тиков) первоначально созданная копия обновляется. За то время, пока эксперт или скрипт работает, может прийти один или несколько новых тиков, поэтому данные могут устареть.

Это всё есть в справке Метаэдитора. Новички упрямо не хотят её юзать просто потому, что не знают одну хитрость. Если между букв служебного слова поставить курсор и нажать F1 или Ctrl+F1, то внизу окна метаэдитора откроется справка именно по этой функции, команде. Попробуйте это проделать с тем же RefreshRates()

 

 

 
drknn >>:

Справочник MQL4 - Предопределенные переменные

double Ask

Последняя известная цена продажи (запрашиваемая цена) текущего инструмента. Для обновления необходимо использовать функцию RefreshRates().

bool RefreshRates( )
Обновление данных в предопределенных переменных и массивах-таймсериях. Эта функция используется, когда эксперт или скрипт производит вычисления в течение долгого времени и нуждается в обновленных данных. Возвращается TRUE, если данные обновлены, иначе FALSE. Данные могут не обновиться только по той причине, что они соответствуют текущему состоянию клиентского терминала. Эксперты и скрипты работают с собственной копией исторических данных. Копия данных по текущему инструменту создается при первоначальном запуске эксперта или скрипта. При каждом следующем запуске эксперта (напомним, что скрипт выполняется однократно и не зависит от приходящих тиков) первоначально созданная копия обновляется. За то время, пока эксперт или скрипт работает, может прийти один или несколько новых тиков, поэтому данные могут устареть.

Это всё есть в справке Метаэдитора. Новички упрямо не хотят её юзать просто потому, что не знают одну хитрость. Если между букв служебного слова поставить курсор и нажать F1 или Ctrl+F1, то внизу окна метаэдитора откроется справка именно по этой функции, команде. Попробуйте это проделать с тем же RefreshRates()

прости... перефразирую вопрос... зачем использовать структуру

RefreshRates();
...
PriseAsk=MarketInfo(SMB,MODE_ASK);
...
OrderClose(Ticket,Lot,PriseAsk,Proskalz,CLR_NONE)

а не стурктуру

RefreshRates();
...
OrderClose(Ticket,Lot,Ask,Proskalz,CLR_NONE)
 
drknn >>:

а где отложенники то?

// =================== Close_All() =======================
// функция закрывает все рыночные и отложенные ордера
// ===========================================================
void Close_All(bool Delete_Otlozh,int MAGIC, int Prosk){
        string  SMB=Symbol();
        int     Ticket=0;
        double  PriseAsk=0,PriseBid=0;
        double  Lot=0,MinTiskSize,PNT;
        int     DGS,Proskalz;
        while(SchBuy(MAGIC)+SchSell(MAGIC)>0){
                for (int i=OrdersTotal()-1;i>=0;i--){
                        if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)){
                                Alert("Ошибка ", GetLastError(), " при выборе ордера номер ",i," по паре ",SMB);
                        }
                        else {
                                if(OrderSymbol()!=Symbol() || OrderMagicNumber()!=MAGIC){ continue;}
                                RefreshRates();
                                DGS=MarketInfo(SMB,MODE_DIGITS);
                                MinTiskSize=MarketInfo(SMB,MODE_TICKSIZE);// минимальный шаг тика
                                PNT=MarketInfo(SMB,MODE_POINT);
                                Proskalz=NormalizeDouble(Prosk*MinTiskSize/PNT,0);
                                PriseAsk=MarketInfo(SMB,MODE_ASK);
                                PriseAsk=NormalizeDouble(PriseAsk,DGS); 
                                PriseBid=MarketInfo(SMB,MODE_BID);
                                PriseBid=NormalizeDouble(PriseBid,DGS); 
                                Ticket=OrderTicket();
                                Lot=OrderLots();
                                if(OrderType()==OP_BUY){
                                        if(!OrderClose(Ticket,Lot,PriseBid,Proskalz,CLR_NONE)){
                                                Alert("Ошибка ", GetLastError(), " при закрытии Buy-ордера номер ",Ticket," по паре ",SMB);
                                        }
                                }  
                                if(OrderType()==OP_SELL){
                                        if(!OrderClose(Ticket,Lot,PriseAsk,Proskalz,CLR_NONE)){
                                                Alert("Ошибка ", GetLastError(), " при закрытии Sell-ордера номер ",Ticket," по паре ",SMB);
                                        }
                                }  
                                 
                        }
                }
        }
}
// ===========================================================

// =================================================================================================
// ************************* Счётчики ордеров ******************************************************
// =================================================================================================


//=========== SchBuy()  ===============================
//  Функция возвращает количество Buy-ордеров
//   SchBuy      - счётчик Buy ордеров
//-----------------------------------------------------------
int SchBuy(int MAGIC){
  string SMB=Symbol();
  int SchBuy=0;
  for (int i=OrdersTotal()-1;i>=0;i--) {
    if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {WriteError(i);}
    else {
      if(OrderSymbol()!= SMB || OrderMagicNumber()!= MAGIC){ continue;}
      if(OrderType()==OP_BUY){ 
        SchBuy++;
      }  
    }
  }
  return(SchBuy);
}                  
//==================================================================================================

//=========== SchSell()  ===============================
//  Функция возвращает количество Sell-ордеров
//  SchSell  - счётчик Sell ордеров
//-----------------------------------------------------------
int SchSell(int MAGIC){
  string SMB=Symbol();
  int SchSell=0;
  for (int i=OrdersTotal()-1;i>=0;i--){
    if (!OrderSelect(i, SELECT_BY_POS, MODE_TRADES)) {WriteError(i);}
    else {
      if(OrderSymbol()!=SMB || OrderMagicNumber()!=MAGIC){ continue;} 
      if(OrderType()==OP_SELL){
        SchSell++;
      }
    }
  }
 return(SchSell);     
}                  
//==================================================================================================
 
Michelangelo >>:

прости... перефразирую вопрос... зачем использовать структуру

а не стурктуру

С помощью первой структуры можно получить цены не только по тому инструменту, на котором прикреплен эксперт а по любому из обзора рынка.

Т.е. таким образом можно прописать условие мультивалютной торговли.

 
goldtrader >>:

С помощью первой структуры можно получить цены не только по тому инструменту, на котором прикреплен эксперт а по любому из обзора рынка.

Т.е. таким образом можно прописать условие мультивалютной торговли.

мультивалютной? хм...
  string  SMB=Symbol();
Причина обращения: