Ваши вопросы по языку MQL4

BorisSedov

Активный участник
В скрипте двум переменным присваиваются одинаковые значения (0.7).
Почему-то при сравнении выходит что переменные не равны. А как же их тогда правильно сравнить?! При равенстве переменных должно выводится слово OK.
Нужно исправить эту ошибку, понять и объяснить почему так происходит.
 

Вложения

  • MQL4-test-2.mq4
    958 байт · Просмотры: 10
Последнее редактирование:

gravity

Местный знаток
Есть скрипт, в котором переменной присваивается значение. Далее значение переменной выводится при помощи функции Print.
Почему-то значение выводится с ошибкой, вместо 0.5 выводится 0.0.
Нужно исправить эту ошибку, понять и объяснить почему так происходит.

C-подобный:
#property copyright "© 2008-2019, mt4soft.ru"
#property link      "http://mt4soft.ru"
#property strict

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
double a;

a=1/2;

Print(DoubleToString(a,1));
}
//+------------------------------------------------------------------+
334800
На сколько я понял, в примере вместо в строке Print, вместо а, должно быть указано именно числовое значение. Но как это сделать, я пока не понял.
 

BorisSedov

Активный участник
На сколько я понял, в примере вместо в строке Print, вместо а, должно быть указано именно числовое значение. Но как это сделать, я пока не понял.
Ошибка только в одной строке кода. Переменной a присваивается значение 1 деленное на 2. Почему-то в ответе у нас 0.0. DoubleToStr это функция преобразования из числа с плавающей точкой в строку. В данном случае ожидается ответ 0.5.
a=1/2;
Ошибка тут. Но в чем эта ошибка, почему так происходит?
 
Последнее редактирование:

BorisSedov

Активный участник
Вычислим среднюю цену закрытия за всю историю на графике. Рассматриваем только закрытые бары.
На первый взгляд все правильно, но почему то выводится ошибка "array out of range".
Нужно исправить эту ошибку, понять и объяснить почему так происходит.
 

Вложения

  • MQL4-test-3.mq4
    1,1 КБ · Просмотры: 11

gravity

Местный знаток
Ошибка только в одной строке кода. Переменной a присваивается значение 1 деленное на 2. Почему-то в ответе у нас 0.0. DoubleToStr это функция преобразования из числа с плавающей точкой в строку. В данном случае ожидается ответ 0.5.
a=1/2;
Ошибка тут. Но в чем эта ошибка, почему так происходит?
Кое-как нашел. Так как в примере 1 это константа, то она ему присваивается тип int, в итоге все выражение получается типа инт. Вроде так. И выражение, которое получается равным 0,5 в итоге округлятеся до 0,0.

334805

C-подобный:
#property copyright "© 2008-2019, mt4soft.ru"
#property link      "http://mt4soft.ru"
#property strict

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
double a;

a=(double)1/2;

Print(DoubleToStr(a,1));
}
//+------------------------------------------------------------------+
Или так
C-подобный:
#property copyright "© 2008-2019, mt4soft.ru"
#property link      "http://mt4soft.ru"
#property strict

//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
{
double a;

a=1.0/2;

Print(DoubleToStr(a,1));
}
//+------------------------------------------------------------------+
 
Последнее редактирование:

Ugar

Гуру форума
Косяк в типе данных. 1 это целое число, если его поделить, результат будет целым. Что бы получить правильный результат нужно что бы программа знала что 1 это дробное. Есть несколько вариантов разжевать программе что 1 дробная.
1 вариант это преобразовать число в дробное:
double a=(double)1/2;
2 вариант это сразу указать дробную единицу:
double a=1.0/2;
3 вариант это использовать дробную переменную:
double b=1;
double a=b/2;
 

BorisSedov

Активный участник
Приведу все правильные варианты решения.
a=1.0/2.0;
a=(double)1/2;
a=1/(double)2;
a=1.0/2;
a=1/2.0;
Все это называется "Приведение типов".
 

Ugar

Гуру форума
При и операциях хранении
В скрипте двум переменным присваиваются одинаковые значения (0.7).
Почему-то при сравнении выходит что переменные не равны. А как же их тогда правильно сравнить?! При равенстве переменных должно выводится слово OK.
Нужно исправить эту ошибку, понять и объяснить почему так происходит.
При и операциях и хранении дробных чисел есть погрешности. Обычно это 1-2 единицы в 15 знаке.
То есть 0.7 может на деле оказаться в диапазоне 0.699999999999998- 0.700000000000002.
По этому никогда нельзя сравнивать 2 дробных переменных на =. Всегда надо учитывать допущения.
Вот функция из стандартной библиотеки, в ней сравниваются значения с точность до 8 знака.
//+------------------------------------------------------------------+
//| right comparison of 2 doubles |
//+------------------------------------------------------------------+
bool CompareDoubles(double number1,double number2)
{
if(NormalizeDouble(number1-number2,8)==0) return(true);
else return(false);
}
Есть и другие способы. Например 2 цены можно сравнить так:
if(fabs(Price1-Price2)<0.5*_Point)
Это значит если разница между Price1 и Price2 меньше пол пункта.
 

BorisSedov

Активный участник
Теперь можно разобраться со второй задачей.

if(NormalizeDouble(a,1)==NormalizeDouble(b,1)) Print("OK");

Этот способ сравнения двух чисел с плавающей точкой работает всегда.
При этом точность сравнения указывается так: NormalizeDouble(число,точность).

Цены сравниваем точно также:

if(NormalizeDouble(Price,Digits)==NormalizeDouble(Price,Digits)) Print("OK");

Digits - возвращает точность измерения цены символа текущего графика.
 
Последнее редактирование:

Ugar

Гуру форума
Вычислим среднюю цену закрытия за всю историю на графике. Рассматриваем только закрытые бары.
На первый взгляд все правильно, но почему то выводится ошибка "array out of range".
Нужно исправить эту ошибку, понять и объяснить почему так происходит.
total=Bars; Это количество баров. Нумерация ячеек в массиве начинается с 0, а не с 1.
Значит последняя ячейка не total, а total-1
 

BorisSedov

Активный участник
Поправка
for(i=total-1; i>=0; i--)
0 ячейка то же существует.
Но это противоречит условию. Мы рассматриваем только закрытые бары.
По этому правильный вариант:
for(i=total-1; i>0; i--)
Но 0 ячейка действительно существует, это тоже нужно знать.
 

Leonup

Новичок форума
Я тут поизвращался с расчетам по дневным барам. Попробуйте такой вариант:
SQL:
   MqlDateTime str1;
   MqlRates rates[];
   int copy_rates=0;
   bool begin=false;
   double High1=0.0;
   double Low1=10000.0;
   int day=32;

   for(int r=0; r<=62; r++)
     {
      copy_rates=CopyRates(_Symbol,PERIOD_D1,r,1,rates);
      if(copy_rates<1) {Print("Ошибка копирования данных"); break;}
      TimeToStruct(rates[0].time,str1);
      if(day>str1.day && !begin) {day=str1.day; continue;}
      else begin=true;
      if(begin)
        {
         if(High1<rates[0].high) High1=rates[0].high;
         if(Low1>rates[0].low) Low1=rates[0].low;
         if(str1.day==1) {begin=false; break;}
        }
     }
   Print("High= ",iHigh(_Symbol,PERIOD_MN1,1));
   Print("High1=",High1);
   Print("Low= ",iLow(_Symbol,PERIOD_MN1,1));
   Print("Low1=",Low1);
Тут в конце выводятся оба варианта принтами. На скрине я показал рез.

Еще раз спасибо вам за помощь.
Протестировал период с июля 18г. по июнь 19г.
Получается, что на графике максимумы июня и июля должны быть идентичными, но действительность – другая.
Такая же картина с их минимумами.
Так же обстоит дело и с минимумами августа и сентября.
С максимумами ноября и декабря.
С минимумами ноября, декабря и января.
Результаты – в файле Excel.
Может вкралась какая-то ошибка в коде?
Как быть?
 

Вложения

  • ZZ-код.txt
    4,9 КБ · Просмотры: 10

gravity

Местный знаток
Подскажите как исправить такую ошибку, декомпил. Или где примерно искать ответ?
 

Вложения

  • Screenshot_1.jpg
    Screenshot_1.jpg
    85,1 КБ · Просмотры: 25
  • CrazypipsMACD_.mq4
    2,5 КБ · Просмотры: 12

vladradon

Программист
Протестировал период с июля 18г. по июнь 19г.
Получается, что на графике максимумы июня и июля должны быть идентичными, но действительность – другая.
Привет! Да, моя ошибка - немного не додумал. Новый вариант проверял с начала прошлого года по сегодня - сравнивал значения - гадина в марте этого года все равно выдает разницу всего в 1 пункт и High и Low, но все остальные месяцы полностью совпадают. Возможно это из-за качества котировок (еще и 4-х знак). Попробуй такой вариант:
SQL:
   MqlDateTime str1;
   MqlRates rates[];
   int copy_rates=0;
   bool begin=false;
   double High1=0.0;
   double Low1=10000.0;
   int day=32;

   for(int r=0; r<=62; r++)
     {
      copy_rates=CopyRates(_Symbol,PERIOD_D1,r,1,rates);
      if(copy_rates<1) {Print("Ошибка копирования данных"); break;}
      TimeToStruct(rates[0].time,str1);
      if(day>str1.day && !begin) {day=str1.day; continue;}
      if(day<str1.day && !begin) {day=32; begin=true;}
      if(begin)
        {
         if(day>str1.day) day=str1.day;
         else {begin=false; break;}
         if(High1<rates[0].high) High1=rates[0].high;
         if(Low1>rates[0].low) Low1=rates[0].low;
        }
     }
 

Leonup

Новичок форума
Новый вариант проверял с начала прошлого года по сегодня - сравнивал значения

Привет!
Долго разбирался, где находить High1 и Low1. Думаю, что их нужно находить по самым последним двум строкам месяца. Так ли это?
Но почему стало столько строк даже в одной минуте, не говоря уже о месяце? Например, количество строк, содержащих запись: 2019.05.31 00:00:00, в сумме 44 строки. И к тому же в течение этой минуты они отличаются друг от друга и чаще всего значительно. А ведь ищутся сформированные, известные High1 и Low1. Видимо, поэтому в новом коде и нет print-ов.

И если все-таки их нужно находить по самым последним двум строкам месяца, то, как увидеть с помощью print только эти две строки?
 
Последнее редактирование:

vladradon

Программист
Привет!
Долго разбирался, где находить High1 и Low1. Думаю, что их нужно находить по самым последним двум строкам месяца. Так ли это?
Но почему стало столько строк даже в одной минуте, не говоря уже о месяце? Например, количество строк, содержащих запись: 2019.05.31 00:00:00, в сумме 44 строки. И к тому же в течение этой минуты они отличаются друг от друга и чаще всего значительно. А ведь ищутся сформированные, известные High1 и Low1. Видимо, поэтому в новом коде и нет print-ов.

И если все-таки их нужно находить по самым последним двум строкам месяца, то, как увидеть с помощью print только эти две строки?
Я просто не скопировал принты - они старые из старого кода подходят. Я вообще проверял:
SQL:
   MqlDateTime str1;
   MqlRates rates[];
   int copy_rates=0;
   bool begin=false;
   double High1=0.0;
   double Low1=10000.0;
   int day=32;

   for(int r=0; r<=62; r++)
     {
      copy_rates=CopyRates(_Symbol,PERIOD_D1,r,1,rates);
      if(copy_rates<1) {Print("Ошибка копирования данных"); break;}
      TimeToStruct(rates[0].time,str1);
      if(day>str1.day && !begin) {day=str1.day; continue;}
      if(day<str1.day && !begin) {day=32; begin=true;}
      if(begin)
        {
         if(day>str1.day) day=str1.day;
         else {begin=false; break;}
         if(High1<rates[0].high) High1=rates[0].high;
         if(Low1>rates[0].low) Low1=rates[0].low;
        }
     }
   Print("High= ",iHigh(_Symbol,PERIOD_MN1,1));
   Print("High1=",High1);
   Print("Low= ",iLow(_Symbol,PERIOD_MN1,1));
   Print("Low1=",Low1);
   if(iHigh(_Symbol,PERIOD_MN1,1)!=High1) Print(iHigh(_Symbol,PERIOD_MN1,1)," High ",High1);
   if(iLow(_Symbol,PERIOD_MN1,1)!=Low1) Print(iLow(_Symbol,PERIOD_MN1,1)," Low ",Low1);
А 2 последние строки сравнивают между собой оба варианта и выдают принт, если они не равны, но они у Вас будут постоянно принтовать. Просто оставьте нужные строки. Я не думал, что принты нужны для сова, если там автоматика работает.
Код считает сформированные данные 1-го месяца когда он уже сформирован полностью.
У меня отличаются только в марте этого года и все одинаковые результаты в каждой минуте одинаковые с первой по последнюю минуту, сколько бы тиков в ней не было.
В тестовом сове я ограничиваю работу - работает по открытию дневного бара, чтобы не тормозил по всем тикам.
 

Вложения

  • Test1.mq4
    6,7 КБ · Просмотры: 10
Последнее редактирование:
Верх