Ошибки написания программ в MQL. Нужна помощь!

Тема в разделе "Программирование MQL4", создана пользователем Dimonaman, 28 фев 2018.

  1. Dimonaman . Гость_

    Сообщения:
    10
    Симпатии:
    0
    Здравствуйте!
    Почему при таком написании выражение для 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;
    }
    
    Я где-то "накосячил", но не пойму где.
    По отдельности, числитель и знаменатель даёт число, а после деления - "ноль".
    Помогите разобраться!
     

    Вложения:

    • Код.txt
      Размер файла:
      492 байт
      Просмотров:
      10
  2. felixfix . Гость_

    Сообщения:
    138
    Симпатии:
    148
    Эти динамические массивы ассоциированы с буферами индикатора? Если нет, то до их использования нужно задать размер массивов. Нужен весь код индикатора иначе не понятно.
     
  3. Dimonaman . Гость_

    Сообщения:
    10
    Симпатии:
    0
    Виноват!
    Код:
    #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;
    }
    
     
  4. Dimonaman . Гость_

    Сообщения:
    10
    Симпатии:
    0
    Проблему я решил, но не могу понять почему так!
    В строке:

    for(i=limit; i>=0; i--)

    я указал численное количество баров

    for(i=1000; i>=0; i--)

    и всё заработало.

    В чём была проблема?
    Если у кого есть идеи - готов выслушать.
     
  5. option . Administrator

    Сообщения:
    2.647
    Симпатии:
    2.324
    Код:
    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; `41
     
    felixfix нравится это.
  6. Dimonaman . Гость_

    Сообщения:
    10
    Симпатии:
    0
    Я так уже пробовал.
    Результат отрицательный.
    Исчезает график. И значение = 0.
    Спасибо за ответ!
     
  7. felixfix . Гость_

    Сообщения:
    138
    Симпатии:
    148
    Выше ответ уже дан на заданный вопросу, от себя замечу, заменять в указанном цикле limit на число не стоит, иначе на каждом тике индикатор будит пробегать бо барам от 1000 до 0 делая расчеты тем самым нагружая терминал.
     
  8. Dimonaman . Гость_

    Сообщения:
    10
    Симпатии:
    0
    ВСЁ!!!
    Нашёл проблему!
    Всё дело в том, что Болинджер не с первого бара истории рисуется.

    Спасибо Option за мысль!
     

    Вложения:

    • Тренд.
      Тренд.jpg
      Размер файла:
      122,2 КБ
      Просмотров:
      0
  9. felixfix . Гость_

    Сообщения:
    138
    Симпатии:
    148
    Код:
    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);
      }
    Результат
    upload_2018-2-28_17-48-21.
     
  10. Dimonaman . Гость_

    Сообщения:
    10
    Симпатии:
    0
    Тогда, надо писать:

    int limit = Bars-counted_bars-22
     
  11. Dimonaman . Гость_

    Сообщения:
    10
    Симпатии:
    0
    Спасибо всем за участие и помощь!
     
  12. Dimonaman . Гость_

    Сообщения:
    10
    Симпатии:
    0
    Всем привет!
    Хочу подвести итог. Может кому понадобиться.

    То, что график не рисовался и значение было "ноль" - это вина расчёта ВВ.
    Первые N баров истории (где N - период ВВ) нужны для расчёта ВВ и на этом участке у меня получалось деление на "ноль".
    Чтобы этого избежать надо к знаменателю прибавить какую-нибудь очень маленькую величину (не влияющую на вычисления).
    После этого можно использовать вариант:

    int limit = Bars-counted_bars-1

    Мой вариант:
    int limit = Bars-counted_bars-22
    не работает.
    График появляется но расчёт в реале не идёт.

    Спасибо!
     
  13. felixfix . Гость_

    Сообщения:
    138
    Симпатии:
    148
    А вот этого категорически делать нельзя. Поделив некое число на очень маленькое число получим очень большое число. Уж лучше оставлять значение буфера пустым в случае если деление на ноль.
    Попробуй сделать так:
    Код:
    Sign[i]=EMPTY_VALUE;  
    if((BBup[i]-BBdown[i])!=0) Sign[i] = (Close[i]-BBdown[i])/(BBup[i]-BBdown[i]);
     
  14. Dimonaman . Гость_

    Сообщения:
    10
    Симпатии:
    0
    Согласен!
    Мой вариант "корявый".
    Ваш вариант работает и, я думаю, это лучший выход из такой ситуации.
    Спасибо!
     
  15. Михаил__ . Гость_

    Сообщения:
    49
    Симпатии:
    6
    Что-то я не могу понять, почему limit на число заменять не стоит. Функция старт итак выполняется заново при каждом тике. Меняйте вы или не меняйте. Так ведь?
     
  16. Dimonaman . Гость_

    Сообщения:
    10
    Симпатии:
    0
    Цикл:

    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 баров).

    Как-то так!
     
  17. Михаил__ . Гость_

    Сообщения:
    49
    Симпатии:
    6
    Блин.Спасибо. Я не знал о существовании IndicatorCounted();