Здравствуйте! Почему при таком написании выражение для Sign[] даёт результат "ноль"? Код: double BBup[]; double BBdown[]; double Sign[]; void start() { int i,counted_bars = IndicatorCounted(); if (counted_bars < 0) return; if (counted_bars > 0) counted_bars--; int limit = Bars-counted_bars; for(i=limit; i>=0; i--) { BBup[i]=iBands(NULL,0,20,2,0,PRICE_WEIGHTED,MODE_UPPER,i); BBdown[i]=iBands(NULL,0,20,2,0,PRICE_WEIGHTED,MODE_LOWER,i); Sign[i] = (Close[i]-BBdown[i])/(BBup[i]-BBdown[i]); } return; } Я где-то "накосячил", но не пойму где. По отдельности, числитель и знаменатель даёт число, а после деления - "ноль". Помогите разобраться!
Эти динамические массивы ассоциированы с буферами индикатора? Если нет, то до их использования нужно задать размер массивов. Нужен весь код индикатора иначе не понятно.
Виноват! Код: #property indicator_separate_window #property indicator_buffers 3 #property indicator_color3 Blue double BBup[]; double BBdown[]; double Sign[]; int init() { IndicatorBuffers(3); SetIndexBuffer(0,BBup); SetIndexStyle (0,DRAW_NONE); SetIndexBuffer(1,BBdown); SetIndexStyle (1,DRAW_NONE); SetIndexBuffer(2,Sign); SetIndexStyle (2,DRAW_LINE); return(0); } void start() { int i,counted_bars = IndicatorCounted(); if (counted_bars < 0) return; if (counted_bars > 0) counted_bars--; int limit = Bars-counted_bars; for(i=limit; i>=0; i--) { BBup[i]=iBands(NULL,0,20,2,0,PRICE_WEIGHTED,MODE_UPPER,i); BBdown[i]=iBands(NULL,0,20,2,0,PRICE_WEIGHTED,MODE_LOWER,i); Sign[i] = (Close[i]-BBdown[i])/(BBup[i]-BBdown[i]); } return; }
Проблему я решил, но не могу понять почему так! В строке: for(i=limit; i>=0; i--) я указал численное количество баров for(i=1000; i>=0; i--) и всё заработало. В чём была проблема? Если у кого есть идеи - готов выслушать.
Код: double BBup[]; double BBdown[]; double Sign[]; void start() { int i,counted_bars = IndicatorCounted(); if (counted_bars < 0) return; if (counted_bars > 0) counted_bars--; int limit = Bars-counted_bars; for(i=limit; i>=0; i--) { BBup[i]=iBands(NULL,0,20,2,0,PRICE_WEIGHTED,MODE_UPPER,i); BBdown[i]=iBands(NULL,0,20,2,0,PRICE_WEIGHTED,MODE_LOWER,i); Sign[i] = (Close[i]-BBdown[i])/(BBup[i]-BBdown[i]); } return; } Исправь девятую строку. Должно быть так: int limit = Bars-counted_bars-1;
Выше ответ уже дан на заданный вопросу, от себя замечу, заменять в указанном цикле limit на число не стоит, иначе на каждом тике индикатор будит пробегать бо барам от 1000 до 0 делая расчеты тем самым нагружая терминал.
ВСЁ!!! Нашёл проблему! Всё дело в том, что Болинджер не с первого бара истории рисуется. Спасибо Option за мысль!
Код: 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 i,counted_bars = IndicatorCounted(); if (counted_bars < 0) return 0; if (counted_bars > 0) counted_bars--; int limit = Bars-counted_bars-1; for(i=limit; i>=0; i--) { BBup[i]=iBands(NULL,0,20,2,0,PRICE_WEIGHTED,MODE_UPPER,i); BBdown[i]=iBands(NULL,0,20,2,0,PRICE_WEIGHTED,MODE_LOWER,i); if((BBup[i]-BBdown[i])!=0) Sign[i] = (Close[i]-BBdown[i])/(BBup[i]-BBdown[i]); else Sign[i] =0; } //--- return value of prev_calculated for next call return(rates_total); } Результат
Всем привет! Хочу подвести итог. Может кому понадобиться. То, что график не рисовался и значение было "ноль" - это вина расчёта ВВ. Первые N баров истории (где N - период ВВ) нужны для расчёта ВВ и на этом участке у меня получалось деление на "ноль". Чтобы этого избежать надо к знаменателю прибавить какую-нибудь очень маленькую величину (не влияющую на вычисления). После этого можно использовать вариант: int limit = Bars-counted_bars-1 Мой вариант: int limit = Bars-counted_bars-22 не работает. График появляется но расчёт в реале не идёт. Спасибо!
А вот этого категорически делать нельзя. Поделив некое число на очень маленькое число получим очень большое число. Уж лучше оставлять значение буфера пустым в случае если деление на ноль. Попробуй сделать так: Код: Sign[i]=EMPTY_VALUE; if((BBup[i]-BBdown[i])!=0) Sign[i] = (Close[i]-BBdown[i])/(BBup[i]-BBdown[i]);
Согласен! Мой вариант "корявый". Ваш вариант работает и, я думаю, это лучший выход из такой ситуации. Спасибо!
Что-то я не могу понять, почему limit на число заменять не стоит. Функция старт итак выполняется заново при каждом тике. Меняйте вы или не меняйте. Так ведь?
Цикл: int i,counted_bars = IndicatorCounted(); if (counted_bars < 0) return(-1); if (counted_bars > 0) counted_bars--; int limit = Bars-counted_bars-1; for(i=limit; i>=0; i--) { ... } один (первый) раз пробегается по всей истории. А дальше пересчитывается только последний (изменённый, текущий) бар. Тем самым экономятся ресурсы компа. Да и бессмысленно постоянно пересчитывать не изменившиеся бары. Результат будет тот же. А при использовании вместо int limit = Bars-counted_bars-1; int limit = 1000; каждый тик будут пересчитываться все бары, указанные числом (1000 баров). Как-то так!