Работа над ошибками

Окончание, начало в статьях:

  1. Написание советника для торговли
  2. «Волшебство» в MQL4
  3. Советник «болтун»
  4. Обработка ошибок

Ошибки не очень приятная вещь, а за ошибки на рынке Форекс еще и приходится платить своими «кровными».
При удалении, модификации или открытии ордера мы задаем нужные нам параметры – цена, размер лота, стоп-лос и тейк-профит. И если хоть один из них будет задан не верно, терминал вернет ошибку и торговая операция не исполнится. Что бы не допускать ошибок наш «эксперт» перед отправкой торгового приказа должен проверить все параметры на корректность.

Итак:
Цена – если это маркет ордера, Buy выставляется по Ask и Sell по Bid.

Размер пункта в валюте котировки. Для текущего инструмента хранится в предопределенной переменной Point. Он может быть разным и зависит как к отдельным финансовым инструментам (например EUR/USD – 0.0001, USD/JPY – 0.01) так и от Дилинговых Центров. В зависимости от ДЦ тая ж валютная пара EUR/USD, в одних ДЦ размер пункта четыре знака после запятой (0.0001) а в других пять (0.00001).

Количество цифр после десятичного точки в цене инструмента. Для текущего инструмента хранится в предопределенной переменной Digits.

Если размер пункта для финансового инструмента предопределен как 0.0001 а в торговом приказе в значении цены после запятой будет больше чем четыре цифры – это вызовет ошибку.
Даже если взять для выставления ордера Ask или Bid часто бывает что терминал дает цену котировки Ask или Bid с ошибкой (лишней цифрой после запятой). Потому всегда перед торговой операцией значение цены нужно округлить до нужного количества цифр после запятой.

Для округления есть функция NormalizeDouble(число для округления, количество цифр после запятой).
Можно задать явно число цифр (для конкретной валютной пары и ДЦ).
Пример:

Price = NormalizeDouble(Ask, 4); // округляем до нужного нам числа цифр после запятой

А лучше так:

Price = NormalizeDouble(Ask, Digits); // округляем до нужного нам числа цифр после запятой

Тоже самое нужно сделать после вычисления лота, стоплоса и тейкпрофита (перед оформлением приказа).
Пример:

Price = Ask + Delta*Point; // вычисляем цену открытия байстопа
Price = NormalizeDouble(Price, Digits); // округляем до нужного нам числа цифр после запятой
SL = Price - StopLoss*Point; // вычисляем стоплос
SL = NormalizeDouble(SL, Digits); // округляем до нужного нам числа цифр после запятой
TP = Price + TakeProfit*Point; // вычисляем тейкпрофит
TP = NormalizeDouble(TP, Digits); // округляем до нужного нам числа цифр после запятой

При расчете лота нужно учитывать дополнительные параметры:
Минимальный размер лота – минимально разрешенный размер лота.

Min_Lot = MarketInfo(Symb,MODE_MINLOT);// Мин. размер. лотов

Максимальный размер лота – максимально разрешенный размер лота.

Max_L = MarketInfo(Symb,MODE_MAXLOT);// Мax. размер. Лотов

Расчет лота оформим в отдельной функции Lot().

double Lot()
 {
  int q;
  double dLot, Min_Lot, Max_L, One_Lot;
  One_Lot = MarketInfo(Symb,MODE_MARGINREQUIRED);// Стоим. 1 лота
  Min_Lot = MarketInfo(Symb,MODE_MINLOT);// Мин. размер. лотов
  Max_L = MarketInfo(Symb,MODE_MAXLOT);// Мax. размер. лотов
  dLot = Lot;
//---------
  // код Вашего манименеджмента (ММ)
//---------
  if(Min_Lot == 0.1) q = 1;
  if(Min_Lot == 0.01) q = 2;
  dLot = NormalizeDouble(dLot,q); // округляем до нужного нам числа цифр после запятой
  if(dLot < Min_Lot) dLot = Min_Lot; // если лот задан меньше допустимого - задаем минимально возможный
  if(dLot > Max_L) dLot = Max_L;// если лот задан больше допустимого - задаем максимально возможный
  if(dLot*One_Lot > AccountFreeMargin()) // Не хватает даже..
   {                         // ..на минимальн. лот:(
    inf(12,0,dLot);   // Сообщение..
    return(-1);       // ..и выход
   } //
  return(dLot); // ввозвращаем размер лота
 }

MarketInfo – С помощью этой функции можно получить разнообразною информацию об финансовых инструментах.
AccountFreeMargin() – свободные средства на Вашем счете.

Минимальная щистанция:
Может быть разной и зависит как от финансового инструмента (например EUR/USD – 2 пункта, GBP/JPY – 16 пунктов) так и от ДЦ.

Min_Dist = MarketInfo(Symb,MODE_STOPLEVEL); //Минимально допустимый уровень стоп-лосса/тейк-профита в пунктах

При попытке например выставить байстоп ордер по GBP/JPY к Ask ближе чем 16 пунктов, терминал вернет ошибку и ордер не будет выставлен.
Стоп-лос, Тейк-профит – если стоп-лос или тейк-профит задан ближе от цены открытия чем параметр «минимальная дистанция», та же ошибка.
При работе с маркет ордером нужно проверять стоп-лос и тейк-профит относительно цены открытия на минимально допустимое расстояние.
При работе с отложенным ордерам, помимо проверки стоп-лоса и тейк-профита нужно еще проверить и расстояние цену открытия относительно текущей цены.

Не забудьте объявить переменные. Теперь наш «эксперт» готов к работе, но Вы думаю еще помните что он делался не для торговли а как пример для изучения основ языка MQL4.

Полный код «советника».

//+------------------------------------------------------------------+
//|                                                  TradeOnNews.mq4 |
//|                      Copyright © 2008, MetaQuotes Software Corp. |
//|                                        http://www.metaquotes.net |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2008, MetaQuotes Software Corp."
#property link      "http://www.metaquotes.net"

//---- input parameters
extern int    Magic          = 111; //число может быть любым
extern string StartTime      = "15:30";  // время открытия маркет ордера (по времени MetaTrader)
extern string CloseTime      = "16:00";  // Время закрытия ордеров
extern int    Delta          = 15;  // расстояние от цены для выставления стоп ордеров
extern int    StopLoss       = 20;
extern int    TakeProfit     = 30;
extern double Lot            = 0.1;

int Ticket, day, EP, Min_Dist;
string Symb, Text;

double   Mas_Ord[31][13];   // Массив ордеров
int      Mas_Tip[6];            // Массив колич. ордеров всех типов // [] тип орд: 0=B,1=S,2=BL,3=SL,4=BS,5=SS
int      Mas_Tip_T[6];          // Массив колич. ордеров всех типов - открытых сегодня
//+------------------------------------------------------------------+
//| expert initialization function                                   |
//+------------------------------------------------------------------+
int init()
  {
   Symb = Symbol();    // Название фин.инстр.
   Min_Dist = MarketInfo(Symb,MODE_STOPLEVEL); //Минимально допустимый уровень стоп-лосса/тейк-профита в пунктах
   return(0);
  }
//+------------------------------------------------------------------+
//| expert start function                                            |
//+------------------------------------------------------------------+
int start()
  {
   int total;
   double Price, LT, SL, TP;
   bool answer;
   total = OrdersTotal(); // сколько всего ордеров открыто
   Orders(); // вызываем функцию учета ордеров
   if(total > 1) // если ордеров больше одного - в нашем случае два
    {
     for(int i = 0; i < total; i ++) // начало цикла
      {
       if(OrderSelect(i, SELECT_BY_POS) == false) continue; // если ордер не выбран, возвращаемся в начало цыкла
       if(Magic != OrderMagicNumber()) continue;// если магическое число не совпадает с нашим Magic - возвращаемся в начало цикла
       Ticket = OrderTicket(); // запоминаем номер ордера
       if(Mas_Tip[0] > 0 && OrderType() == OP_SELLSTOP) // если ордеров бай больше нуля - есть бай ордер // и есть селстоп
        {
         Text ="SellStop"; // для функции inf... что бы вывести в сообщении с каким ордером работаем.
         inf(5, Ticket, -1); // вызываем информациную функцию... собщаем о попытке закрыть SellStop ордер
         answer = OrderDelete(Ticket); // удаляем селстоп
         if(answer == true) // если true значит все прошло успешно
          { // сообщаем об этом
           inf(7, Ticket, -1); // вызываем информациную функцию... собщаем что попытка закрыть SellStop ордер удалась
           return(0); // выходим из start()
          }
         inf(15, GetLastError()); // если дошли сюда значит есть ошибка... узнаем какая именно
         return(0); // выходим из start()
        }
       if(Mas_Tip[1] > 0 && OrderType() == OP_BUYSTOP) // если ордеров сел больше нуля - есть сел ордер // и есть байстоп
        {
         Text ="BuyStop"; // для функции inf... что бы вывести в сообщении с каким ордером работаем.
         inf(5, Ticket, -1); // вызываем информациную функцию... собщаем о попытке закрыть BuyStop ордер
         answer = OrderDelete(Ticket); // удаляем байстоп
         if(answer == true) // если true значит все прошло успешно
          { // сообщаем об этом
           inf(7, Ticket, -1); // вызываем информациную функцию... собщаем что попытка закрыть BuyStop ордер удалась
           return(0); // выходим из start()
          }
         inf(15, GetLastError()); // если дошли сюда значит есть ошибка... узнаем какая именно
         return(0); // выходим из start()
        }
      } // конец цикла
    }
//-----------------------------------
   if(total == 1 && Mas_Tip[4] == 1) // если открыт один ордер и этот ордер байстоп
    {
     LT = Lot(); // вызываем функцию расчета лота
     if(LT == -1) return(0); // если ф-ция Lot() вернула -1 значит нет денег даже на минимальный лот - выходим из start()
     Price = Bid - Delta*Point; // вычисляем цену открытия селлстопа
     Price = NormalizeDouble(Price, Digits); // округляем до нужного нам числа цифр после запятой
     SL = Price + StopLoss*Point; // вычисляем стоплос
     SL = NormalizeDouble(SL, Digits); // округляем до нужного нам числа цифр после запятой
     TP = Price - TakeProfit*Point; // вычисляем тейкпрофит
     TP = NormalizeDouble(TP, Digits); // округляем до нужного нам числа цифр после запятой
     if(((Bid - Price) > Min_Dist*Point) && ((SL - Price) > Min_Dist*Point) && ((Price - TP) > Min_Dist*Point))
      {//проверяем на мин. дистанцию - цену рткрытия, стоп-лос, тейк-профит
       Expiration(); // вызываем функцию Expiration для расчета продолжительности жизни отложеного ордера
       Text = "SellStop"; // для функции inf... что бы вывести в сообщении с каким ордером работаем.
       inf(1, Ticket, -1); // вызываем информациную функцию... собщаем о попытке открыть SellStop ордер
       Ticket = OrderSend(Symb,OP_SELLSTOP,LT,Price,3,SL,TP,NULL,Magic,EP,Red); // открываем селстоп
       if(Ticket > 0) // если Ticket больше 0 значит все прошло успешно... Ticket содержит номер ордера
        { // сообщаем об этом
         inf(2, Ticket, -1); // вызываем информациную функцию... собщаем что попытка открыть SellStop ордер удалась
         return(0); // выходим из start()
        }
       inf(15, GetLastError()); // если дошли сюда значит есть ошибка... узнаем какая именно
       return(0); // выходим из start()
      }
    }
//-------------------------------
   if((total == 0) && (TimeCurrent() > StrToTime(StartTime)) && (TimeCurrent() < StrToTime(StartTime) + 60))
    { // если нет ни одного открытого ордера и текущее время перевалило за время открытия и текущее время меньше за время открытия плюс 60 секунд
     LT = Lot(); // вызываем функцию расчета лота
     if(LT == -1) return(0); // если ф-ция Lot() вернула -1 значит нет денег даже на минимальный лот - выходим из start()
     Price = Ask + Delta*Point; // вычисляем цену открытия байстопа
     Price = NormalizeDouble(Price, Digits); // округляем до нужного нам числа цифр после запятой
     SL = Price - StopLoss*Point; // вычисляем стоплос
     SL = NormalizeDouble(SL, Digits); // округляем до нужного нам числа цифр после запятой
     TP = Price + TakeProfit*Point; // вычисляем тейкпрофит
     TP = NormalizeDouble(TP, Digits); // округляем до нужного нам числа цифр после запятой
     if(((Price - Ask) > Min_Dist*Point) && ((Price - SL) > Min_Dist*Point) && ((TP - Price) > Min_Dist*Point))
      {//проверяем на мин. дистанцию - цену рткрытия, стоп-лос, тейк-профит
       Expiration(); // вызываем функцию Expiration для расчета продолжительности жизни отложеного ордера
       Text = "BuyStop"; // для функции inf... что бы вывести в сообщении с каким ордером работаем.
       inf(1, Ticket, -1); // вызываем информациную функцию... собщаем о попытке открыть BuyStop ордер
       Comment("Min_Dist = ",Min_Dist,"\nLT = ",LT);
       Ticket = OrderSend(Symb,OP_BUYSTOP,LT,Price,3,SL,TP,NULL,Magic,EP,Blue); //открываем байстоп
       if(Ticket > 0) // если Ticket больше 0 значит все прошло успешно... Ticket содержит номер ордера
        { // сообщаем об этом
         inf(2, Ticket, -1); // вызываем информациную функцию... собщаем что попытка открыть BuyStop ордер удалась
         return(0); // выходим из start()
        }
       inf(15, GetLastError()); // если дошли сюда значит есть ошибка... узнаем какая именно
       return(0); // выходим из start()
      }
    }
   return(0); // выходим из start()
  }
//+------------------------------------------------------------------+
// расчет лота                                                       |
//+------------------------------------------------------------------+
double Lot()
 {
  int q;
  double dLot, Min_Lot, Max_L, One_Lot;
  One_Lot = MarketInfo(Symb,MODE_MARGINREQUIRED);// Стоим. 1 лота
  Min_Lot = MarketInfo(Symb,MODE_MINLOT);// Мин. размер. лотов
  Max_L = MarketInfo(Symb,MODE_MAXLOT);// Мax. размер. лотов
  dLot = Lot;
//---------
  // код Вашего манименеджмента (ММ)
//---------
  if(Min_Lot == 0.1) q = 1;
  if(Min_Lot == 0.01) q = 2;
  dLot = NormalizeDouble(dLot,q); // округляем до нужного нам числа цифр после запятой
  if(dLot < Min_Lot) dLot = Min_Lot; // если лот задан меньше допустимого - задаем минимально возможный
  if(dLot > Max_L) dLot = Max_L;// если лот задан больше допустимого - задаем максимально возможный
  if(dLot*One_Lot > AccountFreeMargin()) // Не хватает даже..
   {                         // ..на минимальн. лот:(
    inf(12,0,dLot);   // Сообщение..
    return(-1);       // ..и выход
   } //
  return(dLot); // ввозвращаем размер лота
 }
//+------------------------------------------------------------------+
// заполняем масив даными об ордерах - сколько, каких и тд.          |
//+------------------------------------------------------------------+
int Orders()//Інформація про ордера... сколько, каких, цена открытия, стоплос и тд.
 {
  int Qnt = 0;                          // Счётчик количества ордеров
  Qnt = 0;                              // Обнуление счётчика ордеров
  ArrayInitialize(Mas_Ord,0);       // Обнуление массива
  ArrayInitialize(Mas_Tip,0);           // Обнуление массива
  ArrayInitialize(Mas_Tip_T,0);         // Обнуление массива
  for(int i = 0; i < OrdersTotal(); i++)// По рыночн. и отлож. ордерам
   {
    if((OrderSelect(i,SELECT_BY_POS) == true) && (OrderSymbol() == Symb))//Если есть следующ.  //.. и наша вал.пара
     {
      if(Magic != OrderMagicNumber()) continue;// если магическое число не совпадает с нашим Magic - возвращаемся в начало цикла
      Qnt++;                                            // Колич. ордеров
      Mas_Ord[Qnt][1] = OrderOpenPrice();           // Курс открытия орд
      Mas_Ord[Qnt][2] = OrderStopLoss();            // Курс SL
      Mas_Ord[Qnt][3] = OrderTakeProfit();          // Курс ТР
      Mas_Ord[Qnt][4] = OrderTicket();              // Номер ордера
      Mas_Ord[Qnt][5] = OrderLots();                // Количество лотов
      Mas_Tip[OrderType()]++;                           // Кол. ордеров типа
      Mas_Ord[Qnt][6] = OrderType();                // Тип ордера
      Mas_Ord[Qnt][7] = OrderMagicNumber();         // Магическое число
      if(OrderComment() == "") Mas_Ord[Qnt][8] = 0; // Если нет коммент
      else Mas_Ord[Qnt][8] = 1;                     // Если есть коммент
      Mas_Ord[Qnt][9] = OrderOpenTime();            // Время открвтия ордера
      Mas_Ord[Qnt][10] = OrderCloseTime();          // Время закрытия ордера
      Mas_Ord[Qnt][11] = OrderExpiration();     // Возвращает дату истечения для выбранного отложенного ордера.
      if(day == TimeDayOfYear(OrderOpenTime()))         // работа с ордером ...
       {
        Mas_Tip_T[OrderType()]++;                       // Кол. ордеров типа... открытых сегодня
       }
     }
   }
  Mas_Ord[0][0] = Qnt;                         // Колич. ордеров
  return;
 }
//+------------------------------------------------------------------+
//                                                                   |
//+------------------------------------------------------------------+
int Expiration()
 { // если время открытия больше чем время закрытия - додаем одни сутки в секундах(60*60*24)
  if(StrToTime(StartTime) > StrToTime(CloseTime)) EP = 60*60*24 + StrToTime(CloseTime);
    else EP = StrToTime(CloseTime); // если время открытия не больше чем время закрытия - не додаем
 }
//----------------------------------------------------------------+
//
//----------------------------------------------------------------+
int inf(int Mess_Number, int Number=0, double Value=0.0)
 {
  string Graf_Text;                   // Строка сообщения
  switch(Mess_Number)                 // Переход на сообщение
   {
    case 1:  Graf_Text = StringConcatenate("Попытка открыть ",Text," ордер. Ожидание ответа..");  break;
    case 2:  Graf_Text = StringConcatenate("Открыт ",Text," ордер: № ",Number);           break;
    case 3:  Graf_Text = StringConcatenate("Попытка модифицировать ",Text," ордер: № ",Number,". Ожидание ответа.."); break;
    case 4:  Graf_Text = StringConcatenate("Ордер ",Text,"  модифицирован: № ",Number);   break;
    case 5:  Graf_Text = StringConcatenate("Попытка закрыть ",Text," ордер № ",Number,". Ожидание ответа..");  break;
    case 6:  Graf_Text = StringConcatenate("Закрыт ",Text," ордер: № ",Number);           break;
    case 7:  Graf_Text = StringConcatenate("Удалён отложенный ",Text," ордер № ",Number); break;
    case 8:  Graf_Text = StringConcatenate("Ордер ",Number," преобразовался в рыночный"); break;
    case 9:  Graf_Text = StringConcatenate("Переоткрыт ордер ",Number);                   break;
    case 10: Graf_Text = StringConcatenate("Частично закрыт ордер ",Number);              break;
    case 11: Graf_Text = StringConcatenate("Новая минимальная дистанция: ",Number);       break;
    case 12: Graf_Text = StringConcatenate("Не хватает денег на ",DoubleToStr(Value,2)," лотов"); break;
    case 15: switch(Number)                 // Переход на номер ошибки
              {
               case 2: Graf_Text = "Общая ошибка.";
                       break;
               case 4: Graf_Text = "Торговый сервер занят.";
                       if(IsTesting() == false) Sleep(5000); // если это не тестирование - "засыпаем" на 5 секунд.
                       break;
               case 129: Graf_Text = "Неправильная цена.";
                         break;
               case 130: Graf_Text = "Неправильная дистанция.";
                         break;
               case 135: Graf_Text = "Цена изменилась.";
                         break;
               case 136: Graf_Text = "Нет цен. Ждём новый тик..";
                         if(IsTesting() == false) Sleep(1); // если это не тестирование - "засыпаем" на 1 миллисекунду.
                         break;
               case 137: Graf_Text = "Брокер занят.";
                         if(IsTesting() == false)Sleep(5000); // если это не тестирование - "засыпаем" на 5 секунд.
                         break;
               case 146: Graf_Text = "Подсистема торговли занята.";
                         if(IsTesting() == false) Sleep(500); // если это не тестирование - "засыпаем" на пол секунды.
                         break;
               case 5 :  Graf_Text = "Старая версия терминала.";
                         break;
               case 64:  Graf_Text = "Счет заблокирован.";
                         break;
               case 133: Graf_Text = "Торговля запрещена";
                         break;
               case 134: Alert("Недостаточно денег для совершения операции.");
                         return(0);                             // Выход из функции
               default:  Graf_Text = StringConcatenate("Возникла ошибка ",Number);
              }
             break;
    default: Graf_Text = StringConcatenate("default ",Mess_Number);
   }
  Alert(Graf_Text);
 }
//+------------------------------------------------------------------+

Исходник: TradeOnNews 0.4

Обсудить интересующую тему и получить новые знания, можно на Форуме

Содержание курса по программированию на языке MQL4

Публикация от: : Валерий
Имеет вредную привычку – не может сидеть без дела или просто смотреть телевизор. Поэтому все свободное время что-то делает и изучает. Валерий говорит: Трейдинг - это риск и в тоже время свобода, здесь нет начальника над тобой и ты никому ничего не должен, только ты и монитор. Но сидеть постоянно перед монитором это пустая трата времени. Это время можно использовать с большей пользой, а за рынком пусть следит программа, заодно будут сэкономлены деньги на успокоительных средствах. Тестирование торговых стратегий и систем с помощью «экспертов» экономит ему уйму времени. Торгует с помощью «Советников», и это экономит ему не только время но и нервы.

RSSКомментариев (13)

Оставить комментарий

  1. Хук:

    Можно спросить, нигде не могу найти ответ:)

    А от какой линии функция маркетинфо с параметром стоплевел возвращает значение в пунктах от Аск или Бид? Вниз понятно, от Бид а вверх? Не будет ли ошибки если я попытаюсь установить отложку SELLLIMIT или BUYSTOP на расстоянии Bid + MarketInfo (…, MODE_STOPLEVEL) + 1; Или мне нужно писать так: Ask + MarketInfo (…, MODE_STOPLEVEL) + 1; ??? Спасибо.

  2. STOPLEVEL — Минимальная дистанция от цены открытия. Бай открываем по Аску значит Ask + MarketInfo (…, MODE_STOPLEVEL) + 1;, селл по Биду значит и расчет делаем от Bid. Отложеоные ордера BUYSTOP, SELLLIMIT и тд. при выставлении стопов Ask и Bid не учитывают. Они имеют цену открытия от нее и выставляются стопы.

  3. Хук:

    Спасибо, еще вопрос, на пятизнаке, MarketInfo (…, MODE_STOPLEVEL), возвращает чистые пункты или уже перемноженные на 10.0 ??? Или у разных кухонь по разному и универсально это не сделать, вот это в смысле: Ask + (MarketInfo (…, MODE_STOPLEVEL) + 1) * Pips; Где Pips = 1.0 или 10.0 в зависимости от Digits = 2, 4 или 3, 5 ??? Спасибо.

  4. Хук:

    По инфе на странице;)

    Неплохо, хорошо бы еще пояснить тонкости использования оператора break. Почему например в последнем case, оператора switch, данный оператор использовать нельзя, вопреки стандартному описанию. Примеры использования switch в циклах или циклы в циклах с использованием break:). Хорошо было бы увидеть пример расчета iMAOnArray на массиве полученном от ArrayCopySeries, ну или почему стандартная функция AccountLeverage, на некоторых дц, возвращает неправильное кредитное плече (например реально 100, а возврат 150), а с вопросом предыдущего своего поста — разобрался, на пятизнаке, MarketInfo возвращает не пункты а уже пункты * 10.0. Ну и подобные темные переулки MQL:). Спасибо Вам за информацию.

  5. 1. Верно будет для любых ДЦ — Ask + (MarketInfo (…, MODE_STOPLEVEL) + 1) * Point;. Что такое Point прочитайте на этой странице выше.
    2. ДЦ возвращает не верное кредитное плечо — это уже заморочки конкретного ДЦ и выяснять нужно у них.
    3. Почему break нельзя использовать в последнем case оператора switch… можно и нужно. я всегда использую.
    Остальные Ваши вопросы возьму на заметку и постараюсь описать в статье.

  6. Хук:

    Извините Валерий, я наверно неправильно акцентировал внимание на case, я не имел ввиду именно case, я имел ввиду последний оператор оператора switch. В Вашем примере это default. Почему после него нет оператора break? Ведь по правилам синтаксиса MQL он там обязательно должен быть:). И почему компилятор за милую душу проглатывает такой код. Код, к стати корректный. Спасибо.

  7. Хук:

    И еще одно, если программа формирует стринги разного размера и просто инициализирует объявленную ячейку методом простого склеивания (S1 + S2) то такая программа на MQL, может вести себя неадекватно. Это связано с не выделением (не правильным распределением) памяти под полученный в результате работы программы стринг. Поэтому, я всегда пользуюсь StringConcatenate, особенно при отрисовки интерфейса и любых мессенжах. А если мессенж блок конечен и четко определен, то лучше для него объявить отдельный массив (или объявить все с помощью #define) в хидере и при его инициализации, предварительно активно пользоваться функцией ArrayResize. Она, на удивление, хорошо работает:). Все это желательно бы увидеть на этой странице. Спасибо.

  8. Хук:

    Еще одной вещи, очень важной для качества и скорости разработок, хотел бы уделить внимание. Создание пользовательских библиотек импортируемых функций. Т.е. многократное использование наработанного кода для быстрой и качественной реализации любых торговых идей, отрисовки любых программных интерфейсов мессендж блоков, и т.п. Как правильно это делать? Ведь не секрет, что каждый программист имеет свои наработки, профессиональные фишки, помогающие ему решать быстро и качественно практически задачи любой сложности. Вот если бы как то освятить эту тему:). Чтобы не стирать в кровь пальцы и не выворачивать мозги на изнанку рисуя сотни и тысячи строк практически одного и того же кода для разных задач. Т.е. я говорю о библиотечной надстройке над MQL. Спасибо.

  9. 1. break это выход из switch а поскольку после последнего case мы итак выйдем из switch то я в последнем его никогда не использую. В MQL, break в switch можно вообще неиспользовать но тогда switch будет работать немного по другому и я это импользую в своих советниках. В статье поясню в примерах.
    2. Насчет StringConcatenate согласен, как выдите из статьи тоже в основном ее пользуюсь. Ковсему прочему она быстрее создает строку (MQL «медленый» относительно других языков програмирования).
    3. Вы правы каждый програмист имеет набор функций. у меня тоже есть свой набор функций на все случае жизни, с помощью их простые советники делаются за несколько минут. В интернете можно найти наборы функций других програмистов. Но у каждого програмиста свой стиль и не всегда получается просто скопировать. Свой набор делал сам. Использовать ли библиотеки или шаблон это уже предпочтение програмиста. Я использую шаблон, что бы все было в одном файле. Библиотеку использую когда хочу защитить код, но библиотеку пишу на другом языке (MQL легко взломать).

    Оператор-переключатель switch — http://forexlab.ru/?p=9733&preview=true

  10. Хук:

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

  11. Учту, только защита это уже не для новичков:)).

  12. Александр:

    Ребята! А что такое аватар?

Оставить комментарий



Если вы хотите аватар, получите его в сервисе Gravatar.

  • О портале — Форекс Лаборатория

    Портал Форекс лаборатория - Forex Lab, создан для того чтобы Вы смогли получить всю необходимую информацию, которая позволит стать Вам профессиональным трейдером. На сайте представлены разделы для начинающих, которые помогут познать основы торговли на рынке Forex и разделы для опытных трейдеров, в которых описываются техники и стратегии торговли, хитрости и тонкости трейдинга, осуществления сделок.

    На нашем сайте Вашему вниманию предлагаются обучающие вебинары и курсы, которые позволят быстрее усвоить новые знания. А также Вы можете пройти курсы трейдинга и мастер-классы по различным методикам и видам анализа от практикующих профессиональных трейдеров, с помощью которых новички быстро научатся основным правилам торговли, а опытные трейдеры смогут усовершенствовать свои стратегии и методы технического анализа. Помимо этого Вам будет предоставлен доступ к информации об инвестировании, вариантах доверительного управления, программировании для трейдинга и многом другом.

    Для того, чтобы рынок Forex стал для вас источником финансовой стабильности и процветания, нужны только ваше желание и вера в свои силы. Подкрепить и развить свои знания о валютном рынке Вы можете с помощью информации на нашем сайте. Мы всегда готовы поделиться с Вами опытом и знаниями!