Непонятный Double вылазит в индикаторных буферах

 
В который раз возникает проблема с рандомными значениями в индикаторных буферах, которые отображаются как Float, возможно кто-то сталкивался и знает как исправить?
2018.02.06 02:52:22.375	OrderBook (EPM8,M1)	-1.302842498424572e+308 : -1.302842498424572e+308
В этот раз сделал такой костыль, но... с этим надо что-то решать... пример пустого индикатора, который возвращает такие значение ниже.
#property indicator_separate_window
#property indicator_buffers 4
#property indicator_plots 3

#property indicator_label1 "Buy"
#property indicator_type1 DRAW_HISTOGRAM
#property indicator_color1 clrDeepSkyBlue
#property indicator_width1 2

#property indicator_label2 "Sell"
#property indicator_type2 DRAW_HISTOGRAM
#property indicator_color2 clrRed
#property indicator_width2 2

#property indicator_label3 "Delta"
#property indicator_type3 DRAW_COLOR_LINE
#property indicator_color3 clrBlack, clrBlack
#property indicator_width3 1

input int InpDepth = 50;
input bool InpReal = true;
input bool InpCleanDeals = true;
input bool InpCleanDelta = false;

double iBuyBuffer[];
double iSellBuffer[];
double iBuyMean[];
double iSellMean[];
double iDelta[];
double iDeltaColor[];

ulong iTime;

void OnInit()
{
  SetIndexBuffer(0, iBuyBuffer, INDICATOR_DATA);
  SetIndexBuffer(1, iSellBuffer, INDICATOR_DATA);
  SetIndexBuffer(2, iDelta, INDICATOR_DATA);
  SetIndexBuffer(3, iDeltaColor, INDICATOR_COLOR_INDEX);

  ArraySetAsSeries(iBuyBuffer, true);
  ArraySetAsSeries(iSellBuffer, true);
  ArraySetAsSeries(iDelta, true);
  ArraySetAsSeries(iDeltaColor, true);

  ArrayInitialize(iBuyBuffer, 0);
  ArrayInitialize(iSellBuffer, 0);
  ArrayInitialize(iDelta, 0);
  ArrayInitialize(iDeltaColor, 0);
 
  ArrayFill(iSellBuffer, 0, ArraySize(iSellBuffer), 0);
  ArrayFill(iBuyBuffer, 0, ArraySize(iBuyBuffer), 0);
  ArrayFill(iDelta, 0, ArraySize(iDelta), 0);
  ArrayFill(iDeltaColor, 0, ArraySize(iDeltaColor), 0);
}

int OnCalculate(
  const int bars,
  const int counted,
  const datetime& time[],
  const double& open[],
  const double& high[],
  const double& low[],
  const double& close[],
  const long& ticks[],
  const long& volume[],
  const int& spread[]
)
{
  //Любая из строк ниже -1.302842498424572e+308
  //например DoubleToString(iBuyBuffer[0], 0)
  //сразу возвращает строку длиной 217 символов 
  //что-то типа 1302842498424572478367843647832324234620347656734056740256347628946789426436567834634673489578093793...
  //по длине строке проверяю валидное ли значение в буфере, но это пипец если честно...

  //int iMaxSize = StringLen(ULONG_MAX);
  //iDelta[0] = StringLen(DoubleToString(iDelta[0], 0)) > iMaxSize ? 0 : iDelta[0];
  //iBuyBuffer[0] = StringLen(DoubleToString(iBuyBuffer[0], 0)) > iMaxSize > 0 ? 0 : iBuyBuffer[0];
  //iSellBuffer[0] = StringLen(DoubleToString(iSellBuffer[0], 0)) > iMaxSize > 0 ? 0 : iSellBuffer[0];  

  Print(iBuyBuffer[0] + " : " + iSellBuffer[0]);
  return bars;
}
 

Для начала уберите

  ArrayFill(iSellBuffer, 0, ArraySize(iSellBuffer), 0);
  ArrayFill(iBuyBuffer, 0, ArraySize(iBuyBuffer), 0);
  ArrayFill(iDelta, 0, ArraySize(iDelta), 0);
  ArrayFill(iDeltaColor, 0, ArraySize(iDeltaColor), 0);

ведь строкой ранее Вы уже инициализируете массивы через ArrayInitialize

 

В OnInit() у индикаторных буфферов нолевой размер.

 
Сначала у буферов - а это динамические массивы - нулевая длина. И вот Вы с помощью ArrayInitialize заполняете буфера на всю нулевую длину нулями. Этого Вам показалось мало. и Вы с помощью ArrayFill еще раз на всю нулевую длину заполняете буфера нулями. Обе эти операции дают отсутствующий результат. А потом Вы смотрите, что получилось. Да все что угодно, рандомное содержимое памяти
 
STARIJ:
Сначала у буферов - а это динамические массивы - нулевая длина. И вот Вы с помощью ArrayInitialize заполняете буфера на всю нулевую длину нулями. Этого Вам показалось мало. и Вы с помощью ArrayFill еще раз на всю нулевую длину заполняете буфера нулями. Обе эти операции дают отсутствующий результат. А потом Вы смотрите, что получилось. Да все что угодно, рандомное содержимое памяти

Кстати это легко проверить если в OnInit выполнить код:

  Print("Size iBuyBuffer: ",ArraySize(iBuyBuffer));
  Print("Size iSellBuffer: ",ArraySize(iSellBuffer));
  Print("Size iDelta: ",ArraySize(iDelta));
  Print("Size iDeltaColor: ",ArraySize(iDeltaColor));
 
Про то, что он имеет нулевую длину в OnInit - знаю, обнуление было добавлено от отчаяния и никакой роли не играет, можете закоментировать этот код, сути не меняет.
Если непонятно сформулировал, то перефразирую - как ОБНУЛИТЬ индикаторный буфер?
Или так, как понять, что в индикаторе отрисовался новый бар с нулевым значением, если по факту с самого начала значение в нем НЕ нулевое, а рандомное?
Возможно IsNewBar, но надо ловить все тики, OnCalculate их и так пропускает, а с проверкой на изменение даты могут дополнительные косяки быть.
 
Andy Sanders:
Про то, что он имеет нулевую длину в OnInit - знаю, обнуление было добавлено от отчаяния и никакой роли не играет, можете закоментировать этот код, сути не меняет.
Если непонятно сформулировал, то перефразирую - как ОБНУЛИТЬ индикаторный буфер?
Или так, как понять, что в индикаторе отрисовался новый бар с нулевым значением, если по факту с самого начала значение в нем НЕ нулевое, а рандомное?
Возможно IsNewBar, но надо ловить все тики, OnCalculate их и так пропускает, а с проверкой на изменение даты могут дополнительные косяки быть.

Если prev_calculated ==0 значит это или первый заплыв или история была подкачана - в любом случае нужно ПРОЙТИСЬ по всем индексам всех индикаторных буферов. Процедура "ПРОЙТИСЬ" подразумевает ПРИСВОЕНИЕ какого-то значения КАЖДОМУ индексу каждого индикаторного буфера. "Какое-то" значение - зависит от логики индикатора, как правило это рассчитанное значение.

 
Vladimir Karputov:

Если OnCalculate==0 значит это или первый заплыв или история была подкачана - в любом случае нужно ПРОЙТИСЬ по всем индексам всех индикаторных буферов. Процедура "ПРОЙТИСЬ" подразумевает ПРИСВОЕНИЕ какого-то значения КАЖДОМУ индексу каждого индикаторного буфера. "Какое-то" значение - зависит от логики индикатора, как правило это рассчитанное значение.

Да, спасибо, это то.
Единственное уточнение, что именно в OnCalculate надо проверять на 0, prev_calculated / total_bars?

 
Andy Sanders:

Да, спасибо, это то.
Единственное уточнение, что именно в OnCalculate надо проверять на 0, prev_calculated / total_bars?

Извините опечатка (сейчас поправлю). Конечно prev_calculated ==0.

 
Counted / PrevCalculated = 0 только вначале, когда приходит самый первый тик, для каждого нового бара надо сравнивать количество обработанных тиков с количеством поступивших. Финальный вариант.
int OnCalculate(
  const int bars,
  const int counted,
  const datetime& time[],
  const double& open[],
  const double& high[],
  const double& low[],
  const double& close[],
  const long& ticks[],
  const long& volume[],
  const int& spread[]
)
{
    if (bars != counted)
    {
        iDelta[0] = 0;
        iBuyBuffer[0] = 0;
        iSellBuffer[0] = 0;
    }

    return bars;
}
Причина обращения: