ошибка в MQL4

 
Исследуя работу индикатора кауфмана получил странный вывод лога:
//+------------------------------------------------------------------+
//|                                                      Kaufman.mq4 |
//|                              Copyright © 2004, by konKop & wellx |
//|                                        https://www.metaquotes.net/ |
//+------------------------------------------------------------------+
#property copyright "Copyright © 2004, by konKop, GOODMAN, Mstera, af + wellx"
#property link      "http://www.metaquotes.net"

#property indicator_chart_window
#property indicator_buffers 1
#property indicator_color1 Sienna
//---- input parameters
extern int       periodAMA=9;
extern int       nfast=2;
extern int       nslow=30;
extern int       G=2;

//---- buffers
double kAMAbuffer[];

int    cbars=0;
double slowSC,fastSC;

//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int init()
  {
//---- indicators
   SetIndexStyle(0,DRAW_LINE);
   //SetIndexDrawBegin(0,nslow+nfast);
   SetIndexBuffer(0,kAMAbuffer);
   IndicatorDigits(6);
   
   
//----
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator deinitialization function                       |
//+------------------------------------------------------------------+
int deinit()
  {
   return(0);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int start()
  {
   int    i,pos=0;
   double noise,noise0,AMA,AMA0,signal,ER,SSC;
   
//---- TODO: add your code here
   slowSC=(2/(nslow+1));
   fastSC=(2/(nfast+1));

   if (Bars<=(periodAMA+2)) return(0);
   cbars=IndicatorCounted();
   
   //---- check for possible errors
   if (cbars<0) return(-1);
//---- last counted bar will be recounted
   if (cbars>0) cbars--;
   //pos=Bars-periodAMA-2;
   pos=100;
   //Print("cbars1: ", cbars);
   AMA0=Close[pos+1];
   while (pos>=0)
     {
      if(pos==Bars-periodAMA-2) AMA0=Close[pos+1];
      signal=MathAbs(Close[pos]-Close[pos+periodAMA]);
      noise=0;
      for(i=0;i<periodAMA;i++)
       {
        noise=noise+MathAbs(Close[pos+i]-Close[pos+i+1]);
       };
      ER =signal/noise;
      SSC=(ER*(fastSC-slowSC))+slowSC;
      AMA=AMA0+(MathPow(SSC,G)*(Close[pos]-AMA0));
      kAMAbuffer[pos]=AMA;
      AMA0=AMA;
      pos--;
      Print("nfast: ", nfast);
      Print("nslow: ", nslow);
      Print("slowSc: ", slowSC);
      Print("fastSc: ", fastSC);
      Print("signal: ", signal);
      Print("noise: ",  noise);
      Print("SSC: ", cbars);
      Print("AMA0: ", AMA0);
      Print("AMA: ", AMA);
      Print("MathPow: ", MathPow(SSC,G));
      Print("pos: ", pos);
      Print("------------------------ ", 0);
     };
     //Print("cbars2: ", cbars);
//----
   return(0);
  }



При работе индикатора получается такой вывод в лог
................
14:15:30 Kaufman2 GBPUSD,H1: ------------------------ 0
14:15:30 Kaufman2 GBPUSD,H1: nfast: 2
14:15:30 Kaufman2 GBPUSD,H1: nslow: 30
14:15:30 Kaufman2 GBPUSD,H1: slowSc: 0
14:15:30 Kaufman2 GBPUSD,H1: fastSc: 0
14:15:30 Kaufman2 GBPUSD,H1: signal: 0.0124
14:15:30 Kaufman2 GBPUSD,H1: noise: 0.0246
14:15:30 Kaufman2 GBPUSD,H1: SSC: 1002
14:15:30 Kaufman2 GBPUSD,H1: AMA0: 1.9198
14:15:30 Kaufman2 GBPUSD,H1: AMA: 1.9198
14:15:30 Kaufman2 GBPUSD,H1: MathPow: 0
14:15:30 Kaufman2 GBPUSD,H1: pos: 65
14:15:30 Kaufman2 GBPUSD,H1: ------------------------ 0
.................................

Т.е. обычная формула
slowSC=(2/(nslow+1));
дает 0;
Где ошибка?

 
А что Вы хотели получить?

int       nslow=30;
double    slowSC=(2/(nslow+1));

развернем:
double slowSC= 2 / (30 +1) = 2 / 31 = 0


так как Вы выполняете исключительно целочисленные вычисления (все константы целочисленные и
nslow тоже integer), то результат вычислений сводится к целым числам. В данном случае результат
меньше единицы и дробная часть отбрасывается - получаем ноль. А уж потом целочисленный ноль
присваиваем переменной с плавающей запятой.

Чтобы таких проблем небыло, поставьте double nslow=30

 
To renat
>> Чтобы таких проблем небыло, поставьте double nslow=30

Что-то не похоже на язык С. Может имеет смысл это внести в хелп по MQL4?
честно говоря это весьма не интуитивно. А как задать требуюмую точность double переменной?
 
To renat :

а все еще проще-
double slowSC=( 2.0 / (nslow+1));

Индикатор после этого заработал.

p.s Ув. Ренат и ко - не могли бы Вы пояснить принцип работы функции Indicator-counted()?
интересует как система узнает что бары были подсчитаны? и поясните хотя бы на примере моего инндикатора как сделать чтобы он не пересчитывал позиции при каждом тике, хотя нудно персчитывать только текущий бар и несколько баров назад?

Заранее благодарен.
 
Что-то не похоже на язык С. Может имеет смысл это внести в хелп по MQL4?


Это как раз и есть чистый С.

а все еще проще-
double slowSC=( 2.0 / (nslow+1));


Да, это более элегантный вариант в данном случае. Только тогда уже везде контролируйте
наличие явного/неявного приведения к double. Можно в другом месте нарваться на засаду.

не могли бы Вы пояснить принцип работы функции Indicator-counted()?


Терминал точно знает об изменениях, которые произошли с каждым графиком и может дать эту
информацию кастом индикатору. Если в истории произошли серьезные изменения (подкачка,
модификация из history center и тд), то эта функция выдаст 0, что означает - "надо бы с самого
начала все пересчитать от греха подальше". Иначе выдается номер бара, с которого (по мнению
терминала) надо пересчитатать индикатор.

Посмотрите в примерах индикаторов из стандартной поставки - там эта функция вовсю используется.
К сожалению, сейчас у нас абсолютно нет времени заниматься чужими индикаторами - исправляем
ошибки в МetaTrader4.
 
Уважаемый Ренат
а все еще проще-
double slowSC=( 2.0 / (nslow+1));

Данная конструкция с одной стороны смахивает на обычное преобразование типов в С. А с другой стороны больше похоже на переобьявление типа переменной. Просто, раз уж к слову пришлось, не могли бы Вы реализовать в MQL4 С-ишное преобразование типа:
double aaa;
int bbb;
...
bbb=int(aaa);

Или такой реализации не надо? Т.е. можно просто написать bbb=aaa и всё будет Ок, и ошибки не возникнет, и значения переменных будут правильными?
 
to avm:
double aaa;
int bbb;
...
bbb=int(aaa);

Вы правы, что нужно преобразование типа, но просто bbb=aaa не получится т.к. вы присваиваете меньшей точноти большую, а в С разрешено обратное.

То Renat

Моей ошибки не было бы, если бы Вы реализовали принудительное приведение типов как это и рекомендуется тем же к&r.
 
Пример:
   double aaa=10;
   int bbb=5;
   bbb=aaa;
   Print("New bbb=",bbb);


выдаст 10

Сработает как в C/C++ (с выдачей предупреждения о потере точности при автоматическом приведении),
так и в MQL4 (без выдачи предупреждения - преобразования автоматические).

Или такой реализации не надо? Т.е. можно просто написать bbb=aaa и всё будет Ок, и ошибки не возникнет, и значения переменных будут правильными?


Все будет правильно - работает автоматическое приведение типов.

 
Моей ошибки не было бы, если бы Вы реализовали принудительное приведение типов как это и рекомендуется тем же к&r.


Это программирование - в нем много засад. И если программист создал конструкцию из целочисленных
вычислений, то именно они(целочисленные вычисления) и должны быть произведены.
 
на самом деле в исходном примере такое принудительное приведение типов не помогло бы. а помогло бы вот такое
fastSC=2/(double(nfast)+1);


то есть достаточно один из членов выражения явно объявить даблом

fastSC=2.0/(nfast+1);


а выражение bbb=int(aaa); полностью аналогично выражению bbb=aaa;
за исключением того, что второе выражение должно генерировать предупреждение при компиляции.

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