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

 
Vitaly Muzichenko #:


Вот, как лучше всего сделать.
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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 H=100;
  double b, a;
  if(prev_calculated==0) {
    ArrayInitialize(Buffer1,EMPTY_VALUE);
    ArrayInitialize(Buffer2,EMPTY_VALUE);
  }

  b=SymbolInfoDouble(Symbol(),SYMBOL_BID);
  a=SymbolInfoDouble(Symbol(),SYMBOL_ASK);

  if(rates_total-prev_calculated==1) {
    Buffer1[H+1]=EMPTY_VALUE;
    Buffer2[H+1]=EMPTY_VALUE;
  }
  else if (rates_total == prev_calculated) { // сдвигаем данные только когда количество баров не поменялось (в случае появления нового бара они сдвигаются системой терминала)
    for(int j=H; j>0; j--) { 
      Buffer1[j]=Buffer1[j-1];
      Buffer2[j]=Buffer2[j-1];
    }
  }
  // записываем новые данные
  Buffer1[0]=b;
  Buffer2[0]=a;
  return(rates_total);
}
 
JRandomTrader #:
А если не двигать массив, а использовать его как кольцевой буфер, запоминая текущее место первого элемента?

Гениальная идея! Кто её придумал и какое её практическое применение? Сомневаюсь, что она используется исключительно для чартов со скользящим окном...

 
Mihail Matkovskij #:

Гениальная идея! Кто её придумал и какое её практическое применение? Сомневаюсь, что она используется исключительно для чартов со скользящим окном...

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

 
Mihail Matkovskij #:
Вот, как лучше всего сделать.

Проверил, да это хорошее решение - оставил.

Но всё-же хотелось-бы проверить работу ArrayCopy

---

Решил сделать так, а то не красиво оборванный график:

#property indicator_separate_window
#property indicator_buffers 2
#property indicator_plots   2
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrDodgerBlue
#property indicator_label1  "Bid"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrRed
#property indicator_label2  "Ask"

double Buffer1[];
double Buffer2[];
int H;
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void OnInit()
{
  SetIndexBuffer(0,Buffer1);
  ArraySetAsSeries(Buffer1,true);
  SetIndexBuffer(1,Buffer2);
  ArraySetAsSeries(Buffer2,true);
  ArrayInitialize(Buffer1,EMPTY_VALUE);
  ArrayInitialize(Buffer2,EMPTY_VALUE);
  IndicatorSetInteger(INDICATOR_DIGITS,Digits());
  IndicatorSetString(INDICATOR_SHORTNAME,"Tick:");
}
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
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[])
{
  H=(int)ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR);
  if(prev_calculated==0) {
    ArrayInitialize(Buffer1,EMPTY_VALUE);
    ArrayInitialize(Buffer2,EMPTY_VALUE);
  }

  double b=SymbolInfoDouble(Symbol(),SYMBOL_BID);
  double a=SymbolInfoDouble(Symbol(),SYMBOL_ASK);

  if(rates_total-prev_calculated==1) {
    Buffer1[H+1]=EMPTY_VALUE;
    Buffer2[H+1]=EMPTY_VALUE;
  } else if(rates_total == prev_calculated) { // сдвигаем данные только когда количество баров не поменялось (в случае появления нового бара они сдвигаются системой терминала)
    for(int j=H; j>0; j--) {
      Buffer1[j]=Buffer1[j-1];
      Buffer2[j]=Buffer2[j-1];
    }
  }
// записываем новые данные
  Buffer1[0]=b;
  Buffer2[0]=a;
  return(rates_total);
}
//+------------------------------------------------------------------+
void OnChartEvent(const int id,         // идентификатор события
                  const long& lparam,   // параметр события типа long
                  const double& dparam, // параметр события типа double
                  const string& sparam  // параметр события типа string
                 )
{
  if(id==CHARTEVENT_CHART_CHANGE) {
    H=(int)ChartGetInteger(0,CHART_FIRST_VISIBLE_BAR);
    int B=Bars(Symbol(),0);
    for(int j=H; j<B; j++) {
      Buffer1[j]=EMPTY_VALUE;
      Buffer2[j]=EMPTY_VALUE;
    }
  }
}
//+------------------------------------------------------------------+
 
JRandomTrader #:
А если не двигать массив, а использовать его как кольцевой буфер, запоминая текущее место первого элемента?

В примере Виталия можно использовать данную идею. Но от цикла всё равно не уйти (что для него критично). По любому, придется из кольцевого буфера переносить данные в буфер индикатора, с помощью цикла или с помощью функции ArrayCopy. И что поменяется?

 
Mihail Matkovskij #:

Гениальная идея! Кто её придумал и какое её практическое применение? Сомневаюсь, что она используется исключительно для чартов со скользящим окном...

Кто придумал - концов не найти, думаю, многократно переизобреталась, идея достаточно очевидна.

Я, например, использую в том числе для вычисления скользящего среднего данных, которые не хранятся в истории, а имеют только мгновенное значение.

В передаче данных такое использовалось с незапамятных времён.

 
Mihail Matkovskij #:

В примере Виталия можно использовать данную идею. Но от цикла всё равно не уйти (что для него критично). По любому, придется из кольцевого буфера переносить данные в буфер индикатора, с помощью цикла или с помощью функции ArrayCopy. И что поменяется?

Что можно вставить новое значение и сразу копировать с нужного места. Остаётся цикл копирования, но нет цикла сдвига.

 
Vitaly Muzichenko #:

Проверил, да это хорошее решение - оставил.

Но всё-же хотелось-бы проверить работу ArrayCopy

С помощью ArrayCopy можно только из другого массива перенести данные. Но сместить их нельзя. Можно воспользоваться кольцевым буфером и переносить данные из него... Но как это сделать с помощью ArrayCopy, если у него круговое движение... Не понятно. Да и, в принципе, не нужно это понимать. Обычное смещение с помощью цикла не столь критично по скорости работы. По крайней мере, быстрее я ничего не знаю. Что может быть быстрее, только ассемблер?... В общем. оставляйте всё как есть. Будет работать.

 
JRandomTrader #:

Что можно вставить новое значение и сразу копировать с нужного места. Остаётся цикл копирования, но нет цикла сдвига.

Давай-те примером, это будет в тему

Код для модернизации есть

Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам
Любые вопросы новичков по MQL4 и MQL5, помощь и обсуждение по алгоритмам и кодам
  • 2022.02.13
  • www.mql5.com
В этой ветке я хочу начать свою помощь тем, кто действительно хочет разобраться и научиться программированию на новом MQL4 и желает легко перейти н...
 
Mihail Matkovskij #:

С помощью ArrayCopy можно только из другого массива перенести данные. Но сместить их нельзя. Можно воспользоваться кольцевым буфером и переносить данные из него... Но как это сделать с помощью ArrayCopy, если у него круговое движение... Не понятно. Да и, в принципе, не нужно это понимать. Обычное смещение с помощью цикла не столь критично по скорости работы. По крайней мере, быстрее я ничего не знаю. Что может быть быстрее, ассемблер?... В общем. оставляйте всё как есть. Будет работать.

Сейчас код рабочий, но по скорости есть сомнения из-за цикла.

Что это будет?

Хочу проверить несколько кухонь на возможность арбитража, индикатор будет рисовать разность значений, работает по таймеру раз в 100мс. Задержки выполнения кода критичны для данной ситуации.

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