Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам - страница 985

 

Доброго дня.

Прошу помощи. При написании пользовательской функции тестер выдаёт ошибку 3 и не открывает ордера. Укажите ошибки.

 ticket=OrderSend(Symbol(),OP_SELLSTOP,Lots,Prices_install(),3,0,0,NULL,MAGICNUMBER,0,clrGreen);
               if(ticket>0)//проверка отрытия позиции
                 {
                  if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
                     Print("SELL ордер открыт:",OrderOpenPrice());
                 }
               else
                  Print("Ошибка открытия ордера SELL:",GetLastError());
              }
            return;
           }
        }
 //+---------------------------------------------------------------------------+
      //|                     Условия модификации ордеров                           |
      //+---------------------------------------------------------------------------+

      if(ticket>0)
        {
         if(OrderSelect(ticket,SELECT_BY_TICKET,MODE_TRADES))
           {
            //--- длинная позиция открыта
            switch(OrderType())
              {
               case OP_BUYSTOP:
                  if(NormalizeDouble(OrderOpenPrice()-Prices_install(),Digits)>0 && NormalizeDouble(Prices_install()-Bid,Digits)>0)
                    {
                     if(OrderModify(ticket,Prices_install(),0,0,0,clrBlue))
                        Print("Цена Price_BUY ордера успешно модифицирована.");
                     else
                        Print("Ошибка модификации ордера BUYStop. Код ошибки=",GetLastError());
                    }
                  else
                     Print("Цена модификации выше цены ордера");
                  break;
               case OP_SELLSTOP:
                  if(NormalizeDouble(Prices_install()-OrderOpenPrice(),Digits)>0 && NormalizeDouble(Ask-Prices_install(),Digits)>0)
                    {
                     if(OrderModify(ticket,Prices_install(),0,0,0,clrGreen))
                        Print("Цена Price_SELL ордера успешно модифицирована.");
                     else
                        Print("Ошибка модификации ордера SELLStop. Код ошибки=",GetLastError());
                    }
                  else
                     Print("Цена модификации выше цены ордера");
                  break;
               case OP_BUY:
                  if(NormalizeDouble(StopLosse_install()-OrderStopLoss(),Digits)>0 && NormalizeDouble(Ask-StopLosse_install(),Digits)>0)
                    {
                     if(OrderModify(ticket,OrderOpenPrice(),StopLosse_install(),0,0,clrBlue))
                        Print("Цена Price_BUY ордера успешно модифицирована.");
                     else
                        Print("Ошибка модификации ордера BUY. Код ошибки=",GetLastError());
                    }
                  else
                     Print("Цена модификации выше цены ордера");
                  break;
               case OP_SELL:
                  if(NormalizeDouble(OrderStopLoss()-StopLosse_install(),Digits)>0 && NormalizeDouble(StopLosse_install()-Bid,Digits)>0)
                    {
                     if(OrderModify(ticket,OrderOpenPrice(),StopLosse_install(),0,0,clrGreen))
                        Print("Цена Price_SELL ордера успешно модифицирована.");
                     else
                        Print("Ошибка модификации ордера SELL. Код ошибки=",GetLastError());
                    }
                  else
                     Print("Цена модификации выше цены ордера");
                  break;
              }
           }
        }
      Sleep(5);
     }
   return;
  }
//+------------------------------------------------------------------+
double StopLosse_install()
  {
   double StopLoss=iSAR(NULL,PERIODs_short_term,Step,Maximum,1);
   double StopLoss_install;
   int StopLevel=(int)MarketInfo(Symbol(),MODE_STOPLEVEL); // Минимально допустимый уровень стоп-лосса/тейк-профита в пунктах
   int FreezeLevel=(int)MarketInfo(Symbol(),MODE_FREEZELEVEL);//Уровень заморозки ордеров в пунктах
   switch(OrderType())
     {
      case 0:
         if(Bid-StopLoss>FreezeLevel)
           {
            if(Bid-StopLoss>=StopLevel)
               StopLoss_install=NormalizeDouble(StopLoss,Digits);
            if(Bid-StopLoss<StopLevel)
               StopLoss_install=NormalizeDouble(StopLoss-StopLevel*MarketInfo(Symbol(),MODE_DIGITS),Digits);
           }
         else
            Print("Цена открытия ордера находится в дистанции заморозки:",GetLastError());
         break;
      case 1:
         if(StopLoss-Ask>FreezeLevel)
           {
            if(StopLoss-Ask>=StopLevel)
               StopLoss_install=NormalizeDouble(StopLoss,Digits);
            if(StopLoss-Ask<StopLevel)
               StopLoss_install=NormalizeDouble(StopLoss+StopLevel*MarketInfo(Symbol(),MODE_DIGITS),Digits);
           }
         else
            Print("Цена открытия ордера находится в дистанции заморозки:",GetLastError());
         break;
     }
     return(StopLoss_install);
  }
//+------------------------------------------------------------------+
double Prices_install()
  {
   double Price=iSAR(NULL,PERIODs_short_term,Step,Maximum,1);
   double Price_install;
   int StopLevel=(int)MarketInfo(Symbol(),MODE_STOPLEVEL); // Минимально допустимый уровень стоп-лосса/тейк-профита в пунктах
   int FreezeLevel=(int)MarketInfo(Symbol(),MODE_FREEZELEVEL);//Уровень заморозки ордеров в пунктах
   switch(OrderType())
     {
      case 4:
         if(Price-Ask>FreezeLevel)
           {
            if(Price - Ask>=StopLevel)
               Price_install=NormalizeDouble(Price,Digits);
            if(Price - Ask<StopLevel)
               Price_install=NormalizeDouble(Price+StopLevel*MarketInfo(Symbol(),MODE_DIGITS),Digits);
           }
         else
            Print("Цена открытия ордера находится в дистанции заморозки:",GetLastError());
         break;
      case 5:
         if(Bid-Price>FreezeLevel)
           {
            if(Bid-Price>=StopLevel)
               Price_install=NormalizeDouble(Price,Digits);
            if(Bid-Price<StopLevel)
               Price_install=NormalizeDouble(Price+StopLevel*MarketInfo(Symbol(),MODE_DIGITS),Digits);
           }
         else
            Print("Цена открытия ордера находится в дистанции заморозки:",GetLastError());
         break;
     }
     return(Price_install);
  }
//+------------------------------------------------------------------+
 
Ivan Butko:

Странно, если в одном советнике, то открывает сделки одну за другой по каждой указанной валютной паре... с промежутком времени. А когда ставишь на 5 разных графиков с разной валютной парой (symbol(0)), то все 5 сделок открываются одновременно и моментально при нажатии автоторговли. 

Не подскажите, что это может быть и как исправить? Чтобы все было в одном советнике и на одном графике (чтобы кнопка на графике открывала все пары так же быстро, как при активации "автоторговли" с несколькими советниками, как в изначальном варианте)

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

#property copyright "IgorM"
#property link      "https://www.mql5.com/ru/users/igorm"
#property version   "1.00"
#property strict
input string   sym1 = "EURUSD";
input double   lot1 = 0.01;
input string   sym2 = "GBPUSD";
input double   lot2 = 0.01;
input string   sym3 = "USDCAD";
input double   lot3 = 0.01;
input string   sym4 = "USDJPY";
input double   lot4 = 0.01;
input string   sym5 = "AUDUSD";
input double   lot5 = 0.01;
#include <Controls\Button.mqh>
CButton ButtonSend;

string sym[5];
double lot[5];
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+

int OnInit()
  {
   sym[0] = sym1;
   sym[1] = sym2;
   sym[2] = sym3;
   sym[3] = sym4;
   sym[4] = sym5;
   lot[0] = lot1;
   lot[1] = lot2;
   lot[2] = lot3;
   lot[3] = lot4;
   lot[4] = lot5;
   ButtonSend.Create(0, "ButtonSend" + _Symbol, 0, 10, 50, 100, 90);
   ButtonSend.Color(clrRed);
   ButtonSend.Text("Kill Forex!");
   OnTick();
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
  {
//---

  }
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
  {
   static int ticket[5] = {-1, -1, -1, -1, -1 };
   if(ticket[0] > 0 && ticket[1] > 0 && ticket[2] > 0 && ticket[3] > 0 && ticket[4] > 0)
   {
    ButtonSend.Text("EA Stop");
    return;
    }
   while(!IsStopped())
   {
   if(ButtonSend.Pressed())
     {
      ButtonSend.Text("Sending...");
         if(TerminalInfoInteger(TERMINAL_CONNECTED) && TerminalInfoInteger(TERMINAL_TRADE_ALLOWED) && !IsTradeContextBusy())
           {
            RefreshRates();
            for(int i = 0; i < 5; i++)
              {
               if(sym[i] == "") ticket[i] = INT_MAX;
               if(ticket[i] > 0) continue;
               double vol = NormalizeLot(lot[i],sym[i]);
               ticket[i] = OrderSend(sym[i], OP_SELL, vol, SymbolInfoDouble(sym[i],SYMBOL_BID), 3, 0, 0, "", 0, 0, clrRed);
              }
           }
        }
     if(ticket[0] > 0 && ticket[1] > 0 && ticket[2] > 0 && ticket[3] > 0 && ticket[4] > 0) break;        
     ChartRedraw();      
     Sleep(123);
     }
  }
//+------------------------------------------------------------------+
double NormalizeLot(const double value,const string sym_,bool up=false)
  {
   double res,sizetable[9]={1.0,0.1,0.01,0.001,0.0001,0.00001,0.000001,0.0000001,0.00000001};
   double lotStep=SymbolInfoDouble(sym_,  SYMBOL_VOLUME_STEP);
   int lotdigits;
   for(lotdigits=8; lotdigits>=0; lotdigits--) if(lotStep<=sizetable[lotdigits]) break;
   if(up) res=NormalizeDouble(MathCeil(MathMin(MathMax(value,SymbolInfoDouble(sym_,SYMBOL_VOLUME_MIN)),SymbolInfoDouble(sym_,SYMBOL_VOLUME_MAX))/lotStep)*lotStep,lotdigits);
   else res=NormalizeDouble(MathFloor(MathMin(MathMax(value,SymbolInfoDouble(sym_,SYMBOL_VOLUME_MIN)),SymbolInfoDouble(sym_,SYMBOL_VOLUME_MAX))/lotStep)*lotStep,lotdigits);
   return(res);
  }
//+------------------------------------------------------------------+
 
Igor Makanu:

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

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

По скорости исполнения получается так:
1. Быстрее всего - это тыкать на стандартную Trade Panel.
2. Раскидать по нескольким графикам и нажать "автоторговля"
3. Кнпока, открывающая последовательно корзину

 
Ivan Butko:

Сделки также открываются друг за другом.

а по другому никак, погуглите инфу по типам счетов Market Execution/ Instant Execution 

и второй момент https://www.mql5.com/ru/docs/runtime/running

Эксперт - В собственном потоке, сколько экспертов - столько потоков выполнения для них

если кратко - то советник после отправки ордера ждет подтверждение выставления ордера и если несколько советников на разных графиках, то Вы получите независимость работы каждого ЕА, т.е. многопоточное выполнение кода


думаю для Вашей задачи, насколько я понял торговля на новостях, самое оптимальное решение открыть несколько чартов, бросить на них настроенных советников, которые зацикленны в бесконечный цикл, и после выставления ордера советник должен удалиться с чарта, запускать всех советников кнопкой автоторговля

 
всем привет! как заставить стандартый индикатор Parabolic в советнике открывать отдер по созданию его первой точки( тоесть смене тенденции рынка)????
 
ponochka:
всем привет! как заставить стандартый индикатор Parabolic в советнике открывать отдер по созданию его первой точки( тоесть смене тенденции рынка)????

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

Вывод: Первая точка сверху будет тогда, когда цена коснётся точки которая снизу. И наоборот...

 
Igor Makanu:

а по другому никак, погуглите инфу по типам счетов Market Execution/ Instant Execution 

и второй момент https://www.mql5.com/ru/docs/runtime/running

если кратко - то советник после отправки ордера ждет подтверждение выставления ордера и если несколько советников на разных графиках, то Вы получите независимость работы каждого ЕА, т.е. многопоточное выполнение кода


думаю для Вашей задачи, насколько я понял торговля на новостях, самое оптимальное решение открыть несколько чартов, бросить на них настроенных советников, которые зацикленны в бесконечный цикл, и после выставления ордера советник должен удалиться с чарта, запускать всех советников кнопкой автоторговля

Ого... спасибо за пояснение. Имею ввиду. Действительно, только после открытия текущей открывается следующая. Любопытно.

А Вы не знаете случайно, если попробовать четвертую схему - копировальщик сделок - сделки тоже будут открываться последовательно? Например, подаем сигнал копировальщику, что якобы на мастере открыто 7 ордеров... как он их откроет? Или также 7 копировальщиков поставить, у каждого указать, чтобы копировал свою пару. Хотя, попробовать смогу, ничего дополнтельно создавать не нужно, вроде.

Есть еще пятый способ - использовать кликер. Но, это пока затратно, вряд ли кто-то напишет. Помучаю пока то, что есть в наличии.


UPD

Попробовал копировальщик - тоже самое, сделки открывает последовательно. А если ставить копир на 7 графиков и установить обновление 1 мс, то терминал вместе с ВПС взорвутся.

Остается два способа.

1. Действующий - на каждый график накинуть советник и включить автоторговлю.
2. Неиспробованный - использовать сторонее ПО - кликер.
 
Ivan Butko:

1. Действующий - на каждый график накинуть советник и включить автоторговлю. 

2. Неиспробованный - использовать сторонее ПО - кликер.

с вероятностью 99% варианты 1 и 2 будут одинаково по скорости работать, сервер все равно обрабатывает Ваши торговые запросы по очереди, а когда Вы отправляете 7 запросов с 7-ми чартов, это Вы выиграли время на ожидании ответа от сервера (пока советник не получит тикет, он ничего не делает - ждет)

про кликер вот можно с помощью WinAPI "тыкнуть мышей" в любую точку экрана, проверял месяц назад код рабочий https://www.mql5.com/ru/forum/156025#comment_7552799

но это уже без меня, не интересно, там в принципе не сложно если заняться - Вы же хотите еще с помощью панели автоторговля автокликером ордер отправить, вот и с помощью кода  @Koldun Zloy можете сделать тоже самое

 
Igor Makanu:

с вероятностью 99% варианты 1 и 2 будут одинаково по скорости работать, сервер все равно обрабатывает Ваши торговые запросы по очереди, а когда Вы отправляете 7 запросов с 7-ми чартов, это Вы выиграли время на ожидании ответа от сервера (пока советник не получит тикет, он ничего не делает - ждет)

про кликер вот можно с помощью WinAPI "тыкнуть мышей" в любую точку экрана, проверял месяц назад код рабочий https://www.mql5.com/ru/forum/156025#comment_7552799

но это уже без меня, не интересно, там в принципе не сложно если заняться - Вы же хотите еще с помощью панели автоторговля автокликером ордер отправить, вот и с помощью кода  @Koldun Zloy можете сделать тоже самое

Отлично, проверю. Спасибо огромное за помощь и проделанную работу

 

Здравствуйте.

Осваиваю МТ5. Но как то не понятно построение буферных линий... Скачал индикатор с сайта mql5 и немного его исправил.

Но появились косяки с линиями. Вопрос: ПОЧЕМУ КОСЯЧИТ ЛИНИЯ В ИСТОРИИ И КАК ИСПРАВИТЬ?

//+------------------------------------------------------------------+
//|                                                        Proba.mq5 |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property indicator_chart_window
//---- для расчета и отрисовки индикатора использовано пятнадцать буферов
#property indicator_buffers 4
//---- использовано пятнадцать графических построений
#property indicator_plots   4
//+----------------------------------------------+
//|  Параметры отрисовки уровня                  |
//+----------------------------------------------+
//---- отрисовка индикатора в виде значка
#property indicator_type1   DRAW_LINE
//---- в качестве цвета линии индикатора цвет MediumSeaGreen
#property indicator_color1 clrGold
//---- толщина линии индикатора равна
#property indicator_width1  1
//---- отображение метки индикатора
#property indicator_label1  "OPEN"
//+----------------------------------------------+
//|  Параметры отрисовки уровня                  |
//+----------------------------------------------+
//---- отрисовка индикатора в виде значка
#property indicator_type2   DRAW_LINE
//---- в качестве цвета индикатора использован цвет MediumSeaGreen
#property indicator_color2 clrRed
//---- толщина линии индикатора равна
#property indicator_width2  1
//---- отображение лэйбы индикатора
#property indicator_label2  "CLOSE"
//+----------------------------------------------+
//|  Параметры отрисовки уровня                  |
//+----------------------------------------------+
//---- отрисовка индикатора в виде значка
#property indicator_type3   DRAW_LINE
//---- в качестве цвета индикатора использован цвет Lime
#property indicator_color3 clrYellow
//---- толщина линии индикатора равна
#property indicator_width3  2
//---- отображение метки индикатора
#property indicator_label3  "HIGH"
//+----------------------------------------------+
//|  Параметры отрисовки уровня                  |
//+----------------------------------------------+
//---- отрисовка индикатора в виде значка
#property indicator_type4   DRAW_LINE
//---- в качестве цвета индикатора использован цвет MediumSeaGreen
#property indicator_color4 clrYellow
//---- толщина индикатора равна
#property indicator_width4  1
//---- отображение метки индикатора
#property indicator_label4  "LOW"
//+----------------------------------------------+
//| Входные параметры индикатора                 |
//+----------------------------------------------+
input int  ExtHowManyDays=10; //Количество Дней истории
input ENUM_TIMEFRAMES Timeframes = PERIOD_D1; //Период расчетов
//+----------------------------------------------+
//---- объявление динамических массивов, которые в дальнейшем
//---- будут использованы в качестве индикаторных буферов
double BufferLow[],BufferHigh[],BufferClose[],BufferOpen[];
//+------------------------------------------------------------------+
//| iBarShift() function                                             |
//+------------------------------------------------------------------+
int iBarShift(string symbol,ENUM_TIMEFRAMES timeframe,datetime time)
  {
//----
   if(time<0)
      return(-1);
   datetime Arr[],time1;

   time1=(datetime)SeriesInfoInteger(symbol,timeframe,SERIES_LASTBAR_DATE);

   if(CopyTime(symbol,timeframe,time,time1,Arr)>0)
     {
      int size=ArraySize(Arr);
      return(size-1);
     }
   else
      return(-1);
//----
  }
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
void OnInit()
  {
//---
   int draw_begin;
   if(ExtHowManyDays < 1)
      draw_begin=0;
   else
      draw_begin=ExtHowManyDays;

//---- превращение динамических массивов в индикаторные буферы
   SetIndexBuffer(0,BufferOpen,INDICATOR_DATA);
   SetIndexBuffer(1,BufferClose,INDICATOR_DATA);
   SetIndexBuffer(2,BufferHigh,INDICATOR_DATA);
   SetIndexBuffer(3,BufferLow,INDICATOR_DATA);
//---- создание метки для отображения в DataWindow
   PlotIndexSetString(0,PLOT_LABEL,"Price OPEEN");
   PlotIndexSetString(1,PLOT_LABEL,"Price CLOSE");
   PlotIndexSetString(2,PLOT_LABEL,"Price HIGH");
   PlotIndexSetString(3,PLOT_LABEL,"Price LOW");
//---- индексация элементов в буферах как в таймсериях
   ArraySetAsSeries(BufferOpen,true);
   ArraySetAsSeries(BufferClose,true);
   ArraySetAsSeries(BufferHigh,true);
   ArraySetAsSeries(BufferLow,true);
//---- определение точности отображения значений индикатора
   IndicatorSetInteger(INDICATOR_DIGITS,_Digits);
//--- установим номер бара, с которого будет идти отрисовка
   for(int q=0; q<=4; q++)
      PlotIndexSetInteger(q,PLOT_DRAW_BEGIN,draw_begin); //ПРОБЛЕМА ТУТ!!!!!
      //PlotIndexSetInteger(q,PLOT_SHIFT,0);
      //PlotIndexSetDouble(q,PLOT_EMPTY_VALUE,EMPTY_VALUE);
//----
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,    // количество истории в барах на текущем тике
                const int prev_calculated,// количество истории в барах на предыдущем тике
                const datetime &time[],
                const double &open[],
                const double& high[],     // ценовой массив максимумов цены для расчета индикатора
                const double& low[],      // ценовой массив минимумов цены  для расчета индикатора
                const double &close[],
                const long &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---- объявления локальных переменных
   int    begin_bar,first_bar,last_bar,cnt,copy;
   double High_=0.0,Low_=0.0,Close_=0.0,Open_=0.0;
   double iClose[],iOpen[],iHigh[],iLow[];
   datetime iTime[];
//---
   if(_Period>=Timeframes)
      return(0);
//---- проверка и установка начального бара
   if(ExtHowManyDays < 1)
      begin_bar=Bars(NULL,Timeframes)-2;
   else
      begin_bar=ExtHowManyDays-1;

//---- индексация элементов в массивах как в таймсериях
   ArraySetAsSeries(time,true);
   ArraySetAsSeries(iTime,true);
   ArraySetAsSeries(iOpen,true);
   ArraySetAsSeries(iClose,true);
   ArraySetAsSeries(iHigh,true);
   ArraySetAsSeries(iLow,true);

   copy=begin_bar+2;

   if(CopyTime(NULL,Timeframes,0,copy,iTime)<copy)
      return(0);
   if(CopyOpen(NULL,Timeframes,0,copy,iOpen)<copy)
      return(0);
   if(CopyClose(NULL,Timeframes,0,copy,iClose)<copy)
      return(0);
   if(CopyHigh(NULL,Timeframes,0,copy,iHigh)<copy)
      return(0);
   if(CopyLow(NULL,Timeframes,0,copy,iLow)<copy)
      return(0);

//----
   /*cnt=0;
   while(true)
     {
      if(iTime[0]>=(time[0]-Timeframes*60))
         break;
      cnt++;
      if(cnt>5)
         return(0);
      Sleep(300); //1000
     }*/
//----
   if(prev_calculated!=0)
     {
      begin_bar=0;
      BufferOpen[cnt]=0.0;
      BufferClose[cnt]=0.0;
      BufferHigh[cnt]=0.0;
      BufferLow[cnt]=0.0;
     }
//----
   for(cnt=begin_bar; cnt>=0; cnt--)
     {
      if(cnt<rates_total)
        {
         Open_=iOpen[cnt];
         Close_=iClose[cnt+1];
         High_=iHigh[cnt+1];
         Low_=iLow[cnt+1];
        }
      first_bar=iBarShift(NULL,_Period,iTime[cnt]);

      if(cnt>0)
         last_bar=iBarShift(NULL,_Period,iTime[cnt-1]);
      else
         last_bar=0;

      while(first_bar>=last_bar)
        {
         if((first_bar==last_bar && last_bar>0) || first_bar<0)
            break;

         BufferOpen[first_bar]=Open_;
         BufferClose[first_bar]=Close_;
         BufferHigh[first_bar]=High_;
         BufferLow[first_bar]=Low_;
         if(BufferOpen[first_bar]!=BufferOpen[first_bar+1])
            BufferOpen[first_bar+1]=EMPTY_VALUE;
         if(BufferClose[first_bar]!=BufferClose[first_bar+1])
            BufferClose[first_bar+1]=EMPTY_VALUE;
         if(BufferHigh[first_bar]!=BufferHigh[first_bar+1])
            BufferHigh[first_bar+1]=EMPTY_VALUE;
         if(BufferLow[first_bar]!=BufferLow[first_bar+1])
            BufferLow[first_bar+1]=EMPTY_VALUE;

         first_bar--;
        }
     }
//----
   ChartRedraw(0);
//----
   return(rates_total);
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+



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