Изучаем язык программирования MQL4

gravity

Местный знаток
У нас же есть еще вариант когда цена закрытия равна цене открытия. Чтобы исключить эти случаи из расчетов, мы добавляем еще одно условие в часть else. Если этого не сделать, то получится, что мы в down будем учитывать не только бары закрытые вниз, но и бары с ценой закрытия равной цене открытия.
Вот теперь понятно.
 

BorisSedov

Активный участник
Не стану уговаривать. Пишите как считаете нужным.
Ugar, у меня для вас тоже есть простая задача. ;)
На самом деле, задача простая не потому, что ее легко решить, а потому, что в ней присутствуют простые числа.
Впрочем, условие у нее тоже довольно-таки простое. От вас требуется всего-то уметь находить k-е простое число.
Напишите скрипт, который находит k-е простое число. Значение k задается во входных параметрах скрипта, и может быть задано в диапазоне от 1 до 51 000 000 включительно.
(последовательность простых чисел начинается так: 2, 3, 5, 7, 11, .. ..)
 
Последнее редактирование:

gravity

Местный знаток
Попробовал с учетом добавлений от Домовёнка.
PHP:
Expand Collapse Copy
void OnStart()
{
int i,down=0,up=0,разница=0,Они_равны_черт_возьми=0;

for(i=Bars-1; i>0; i--)
   {
   if(Close[i]>Open[i])         up++; // при соблюдении условия считаем бычьи свечи    
   else
        if(Close[i]<Open[i]) down++; // если условие соблюдено, считаем медвежьи
        else Они_равны_черт_возьми++; // если не медвежья и не бычья, то считаем равные
   }
 
   if(down>up)
               разница=down-up;
               Print("Up","-", разница);  //при соблюдении условия выводим Up  
   if(up>down)
               разница=up-down;
               Print("Down","-", разница);   //если не соблюдено Down  
                 
   Print("Они равны черт возьми","-",Они_равны_черт_возьми);
}
Только получается, сделал так, что он при любом исходе показывает сколько вообще было на графике баров с равными ценами открытия и закрытия.
Правильно?
 

BorisSedov

Активный участник
Попробовал с учетом добавлений от Домовёнка.
Только получается, сделал так, что он при любом исходе показывает сколько вообще было на графике баров с равными ценами открытия и закрытия.
Правильно?
Правильно.
Чтобы выводилось что-то одно, делаем так:
C++:
Expand Collapse Copy
if(down>up)
   {
   разница=down-up;
   Print("Down","-", разница);  //при соблюдении условия выводим Down
   }
else if(up>down)
   {
   разница=up-down;
   Print("Up","-", разница);  //если не соблюдено Up
   }
else Print("Они равны черт возьми","-",Они_равны_черт_возьми);
 
Последнее редактирование:

gravity

Местный знаток
Правильно.
Чтобы выводилось что то одно, делаем так:
C++:
Expand Collapse Copy
if(down>up)
   {
   разница=down-up;
   Print("Down","-", разница);  //при соблюдении условия выводим Down
   }
else if(up>down)
   {
   разница=up-down;
   Print("Up","-", разница);  //если не соблюдено Up
   }
else Print("Они равны черт возьми","-",Они_равны_черт_возьми);
Последний вывод я специально хотел, чтобы он всегда выводился, так как вряд ли будет такой случай, что все свечи на графике равны по открытию и закрытию.

А вот, верхние 2, да, че-то я не учел и выводит оба.
А почему у домовенка не выводит оба верхних результата, хотя у него нет никаких else?
PHP:
Expand Collapse Copy
void OnStart()
// Нужно написать скрипт который определяет каких баров на графике больше,
// с ценой закрытия которая больше чем цена открытия
// или
// с ценой закрытия которая меньше чем цена открытия.
// Результат вывести словом Up – если баров закрытых вверх больше, или Down – если баров закрытых вниз больше.
// Рассматриваем только закрытые бары.
// Какой получится результат, в случае, если баров закрытых вверх или вниз будет поровну?
// При сравнении цен учесть погрешности double.
{
int i, a=0;
int n=0.0, m=0.0;        // Объявлены переменные, i, a, n, m, переменной a, n и m сразу же присвоено значение 0.

for(i=Bars-1; i>0; i--) // Сразу присвоено значение Bars-1 переменной i. После этого проверено условие что i>0,
   {                    // если это так, то выполняется один раз все, что написано внутри тела цикла.
   if(Close[i]>Open[i]) // Это условие (Close[i]>Open[i]) расположено как раз в теле цикла, и оно выполняется только если выше будет соблюдаться условие i>0,
      {                 
      n++;              // В теле условия суммируются все подходящие цены закрытия и подсчитывается количество подходящих баров.
      }                 
  
   if(Close[i]<Open[i]) // Это условие (Close[i]<Open[i]) расположено как раз в теле цикла, и оно выполняется только если выше будет соблюдаться условие i>0,
      {                 
      m++;              // В теле условия суммируются все подходящие цены закрытия и подсчитывается количество подходящих баров.
      }   
   }                   
if (n>m)               // если баров с условием (Close[i]>Open[i]) больше, чем баров с условием (Close[i]<Open[i]), то
      {
       a=n-m;
       Print("Up","-", a);  // Выводится результат.
      }               

if (n<m)               // если баров с условием (Close[i]>Open[i]) меньше, чем баров с условием (Close[i]<Open[i]), то
      {
       a=m-n;
       Print("Down","-", a);  // Выводится результат.
      }   

if (n==m)               // если баров с условием (Close[i]>Open[i]) равно  барам с условием (Close[i]<Open[i]), то
Print("Even","-",n,"-", m);  // Выводится результат.

}
 

BorisSedov

Активный участник
А почему у домовенка не выводит оба верхних результата, хотя у него нет никаких else?
Потому, что вместо конструкции else if, он использует просто второй if.

Примеры:
C++:
Expand Collapse Copy
if()
   {

   }
else if()
   {

   }
C++:
Expand Collapse Copy
if()
   {

   }
if()
   {

   }
В первом примере, если не будет выполнено первое условие, будет проверено второе условие.
Во втором примере, второе условие проверяется всегда, независимо от первого условия.

C++:
Expand Collapse Copy
if()
   {

   }
else
   {
   if()
      {
   
      }
   }
А этот вариант соответствует первому примеру, это одно и то же.
 
Последнее редактирование:

BorisSedov

Активный участник
Начинающим советую всегда расставлять скобки { } для всех используемых операторов, так будет проще и вы не ошибетесь.
 

gravity

Местный знаток
Следующая задача.
Нужно написать скрипт который подсчитает количество баров на графике, у которых –
Open=Close
или
High=Close
или
Low=Close
или
High=Open
или
Low=Open
Если хотя бы одно из перечисленных условий для конкретного бара выполняется, то учитываем этот бар при подсчете.

(у меня таких баров нашлось 12 630 из 100 000).
PHP:
Expand Collapse Copy
void OnStart()
//Следующая задача.
//Нужно написать скрипт который подсчитает количество баров на графике, у которых –
//Open=Close
//или
//High=Close
//или
//Low=Close
//или
//High=Open
//или
//Low=Open
//Если хотя бы одно из перечисленных условий для конкретного бара выполняется, то учитываем этот бар при подсчете.
{
int i,счетчик=0;

for(i=Bars-1; i>0; i--)
   {
   if(Open[i]==Close[i] ||
      High[i]==Close[i] ||
      Low [i]==Close[i] ||
      High[i]==Open [i] ||
      Low [i]==Open [i]) 
      {     
      счетчик++; // считаем все бары, которые подходят хотя бы по одному условию
      }
    }               
   Print("Подошло - ",счетчик," бара");
}
 

Mezon

Новичок форума
Пытаюсь научиться давно лет 7 - 8... результат 0! Утверждал и утверждаю, не может человек которого ни когда не учили программированию взять почитать "учебник", документацию или справку и начать писать программы...
 

BorisSedov

Активный участник
Очень важно запомнить –
без скобок срабатывает только один оператор по условию if. Даже если расставить на одной строке несколько операторов после if, по условию сработает только один (самый первый), а остальные уже не относятся к if, можно считать, что остальные расположены не на этой же строке, а ниже.

Пример:
C++:
Expand Collapse Copy
#property strict

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

a=1;
if(a>0) a=2; a*=2; Print(a);
// Результат: 4

a=0;
if(a>0) a=2; a*=2; Print(a);
// Результат: 0

// Ниже одно и тоже, что и вверху.

a=1;
if(a>0)
   {
   a=2;
   }

a*=2;
Print(a);
// Результат: 4

a=0;
if(a>0)
   {
   a=2;
   }

a*=2;
Print(a);
// Результат: 0
}
//+------------------------------------------------------------------+
 

Ugar

Гуру форума
Я все таки не догоняю, почему там в else надо задавать условия?
Ведь в справочнике написано.

Если выражение ложно, то выполняется оператор2.

PHP:
Expand Collapse Copy
if(Close[i]>Open[i])
    up++;   // при соблюдении условия считаем бычьи свечи
else
    down++; // если условие не соблюдено, то значит свеча медвежья. Считаем их.
PHP:
Expand Collapse Copy
if(Close[i]>Open[i]) up++;
else if(Close[i]<Open[i]) down++;

Разве в первом случае не будет работать?
В первом варианте свечи без тела, где цена открытия равна цене закрытия, будут считаться down++;
 

Ugar

Гуру форума
Пытаюсь научиться давно лет 7 - 8... результат 0! Утверждал и утверждаю, не может человек которого ни когда не учили программированию взять почитать "учебник", документацию или справку и начать писать программы...
А я считаю что может. Не может научиться программировать поэт и другие гуманитарии. Они мыслят более высоко образами и обстракциями. Не существует языков программирования настолько высокого уровня. А для программирования нужно уметь уровень мышления снизить до уровня компьютера. Чёткая логика и примитивная последовательность.
 

BorisSedov

Активный участник
А я считаю что может. Не может научиться программировать поэт и другие гуманитарии. Они мыслят более высоко образами и обстракциями. Не существует языков программирования настолько высокого уровня. А для программирования нужно уметь уровень мышления снизить до уровня компьютера. Чёткая логика и примитивная последовательность.
Ugar, покажите начинающим пример - как нужно решать задачи.
Решите простую задачу.
 

gravity

Местный знаток
Очень важно запомнить –
без скобок срабатывает только один оператор по условию if. Даже если расставить на одной строке несколько операторов после if, по условию сработает только один (самый первый), а остальные уже не относятся к if, можно считать, что остальные расположены не на этой же строке, а ниже.

Пример:
C++:
Expand Collapse Copy
#property strict

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

a=1;
if(a>0) a=2; a*=2; Print(a);
// Результат: 4

a=0;
if(a>0) a=2; a*=2; Print(a);
// Результат: 0

// Ниже одно и тоже, что и вверху.

a=1;
if(a>0)
   {
   a=2;
   }

a*=2;
Print(a);
// Результат: 4

a=0;
if(a>0)
   {
   a=2;
   }

a*=2;
Print(a);
// Результат: 0
}
//+------------------------------------------------------------------+

Мне вот так понятнее)
PHP:
Expand Collapse Copy
if()
   {

   }
if()
   {
   }
Если оператор находится вне {}, то он выполняется всегда, независимо от того что написано в if().
Вот тут к примеру, если скобки опустить.
PHP:
Expand Collapse Copy
int a=0;

if(a>0) a*=2; Print("я вне {} , поэтому меня видно в журнале ", a);
Получается а=0, условие a>0 не выполнено, так как 0=0. А Print все равно сработает, так как ему наплевать что там в условии написано. Он сам по себе, вне скобок{}.
Получается такая штука, что когда мы сами не ставим{}, то программа автоматически считает, что в эти самые {} заключен только первый оператор. Программа видит это так.
PHP:
Expand Collapse Copy
int a=0;

if(a>0) {a*=2;} Print("я вне {} , поэтому меня видно в журнале ", a);

А в одну строку вы пишете или в разные строки, это вообще значения не имеет, не влияет на результат.

Чтобы Print выполнялся, только когда соблюдено условие, нам надо его поместить в {}. В нашем случае, в журнал не будет выведено сообщение. Так как, не проходит по условию (a>0).
PHP:
Expand Collapse Copy
int a=0;

if(a>0) {a*=2; Print("Это сообщение вы никогда не увидите в журнале", a);}
 
Последнее редактирование:

Ugar

Гуру форума
Ugar, у меня для вас тоже есть простая задача. ;)
На самом деле, задача простая не потому, что ее легко решить, а потому, что в ней присутствуют простые числа.
Впрочем, условие у нее тоже довольно-таки простое. От вас требуется всего-то уметь находить k-е простое число.
Напишите скрипт, который находит k-е простое число. Значение k задается во входных параметрах скрипта, и может быть задано в диапазоне от 1 до 51 000 000 включительно.
(последовательность простых чисел начинается так: 2, 3, 5, 7, 11, .. ..)
Эта задача скорее арифметическая чем на программирование. Хотя, тут большинство задач такие.
Можно заранее посчитать простые числа или найти таблицу и загнать их в массив. Тогда по индексу массива всегда можно извлечь нужное число. Хотя это может показаться тупым решением, тем не менее оно не будет жрать ресурсы процессора так как нет никаких вычислений.
Но думаю что эта ветка не для экономии тактов процессора. Можно не знать математики, сложных формул и таблиц, а всё свалить на плечи компьютера. Достсточно знать что простое число A делится без остатка только на себя и 1, при делении на числа от 2 до А-1 будет остаток. Так как основная цель программирования на MQL это извлечение прибыли из рынка, а не создание математически совершенной программы, такой подход оправдан.
Вот скрипт. Он тупо перебирает числа и делители, считая найденные простые числа.
Код:
Expand Collapse Copy
#property script_show_inputs
//--- input parameters
input uint     N_Sample=1;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   uint a=2;//Здесь будет значение проверяемое на простоту
   uint i;//Это будет делитель
   uint n_sample=0;//Это будет счётчи найденных простых чисел
   bool Find;//Это будет флаг непростого числа
   while(!_StopFlag)//Это основной цикл
      {
      Print("Проверяем ",a);
      Find=false;//Инициализация флага непростого числа
      for(i=2; i<a; i++)//Цикл перебирающий делитель
         {
         if(a%i<0.00000000000001)//Если а делится без остатка
            {
            Find=true;//Поднять флаг непростого числа
            Print(a," делится на ", i, " без остатка. Не простое");
            break;//Прервать цикл перебирающий делитель
            }
         
         }
      if(!Find)//Если не поднят флаг непростого числа
         {
         n_sample++;//Нарастить счётчик простых чисел
         Print(a," простое число");
         }
      if(n_sample==N_Sample)//Если количество простых чисел достигло заданного
         {
         Print(N_Sample," простое число =",a);
         break;//Прервать основной цикл
         }
      a++;//Нарастит проверяемое число
      }
  }
//+------------------------------------------------------------------+
 

Ugar

Гуру форума
Да если хочется искать огромные по номеру простые числа, возможно стоит все uint заменить на ulong. Естественно убрать все лишние принты, они могут быть причиной замедления.
 

BorisSedov

Активный участник
Эта задача скорее арифметическая чем на программирование. Хотя, тут большинство задач такие.
Можно заранее посчитать простые числа или найти таблицу и загнать их в массив. Тогда по индексу массива всегда можно извлечь нужное число. Хотя это может показаться тупым решением, тем не менее оно не будет жрать ресурсы процессора так как нет никаких вычислений.
Но думаю что эта ветка не для экономии тактов процессора. Можно не знать математики, сложных формул и таблиц, а всё свалить на плечи компьютера. Достсточно знать что простое число A делится без остатка только на себя и 1, при делении на числа от 2 до А-1 будет остаток. Так как основная цель программирования на MQL это извлечение прибыли из рынка, а не создание математически совершенной программы, такой подход оправдан.
Вот скрипт. Он тупо перебирает числа и делители, считая найденные простые числа.
Код:
Expand Collapse Copy
#property script_show_inputs
//--- input parameters
input uint     N_Sample=1;
//+------------------------------------------------------------------+
//| Script program start function                                    |
//+------------------------------------------------------------------+
void OnStart()
  {
//---
   uint a=2;//Здесь будет значение проверяемое на простоту
   uint i;//Это будет делитель
   uint n_sample=0;//Это будет счётчи найденных простых чисел
   bool Find;//Это будет флаг непростого числа
   while(!_StopFlag)//Это основной цикл
      {
      Print("Проверяем ",a);
      Find=false;//Инициализация флага непростого числа
      for(i=2; i<a; i++)//Цикл перебирающий делитель
         {
         if(a%i<0.00000000000001)//Если а делится без остатка
            {
            Find=true;//Поднять флаг непростого числа
            Print(a," делится на ", i, " без остатка. Не простое");
            break;//Прервать цикл перебирающий делитель
            }
       
         }
      if(!Find)//Если не поднят флаг непростого числа
         {
         n_sample++;//Нарастить счётчик простых чисел
         Print(a," простое число");
         }
      if(n_sample==N_Sample)//Если количество простых чисел достигло заданного
         {
         Print(N_Sample," простое число =",a);
         break;//Прервать основной цикл
         }
      a++;//Нарастит проверяемое число
      }
  }
//+------------------------------------------------------------------+
Хотел проверить решение, закомментировал лишние выводы (Print), ввел значение k = 100 000, и программа зависла в раздумьях. С момента запуска прошло больше 10 минут, результата так и не дождался, но скрипт все еще запущен, жду результат.
А что будет если ввести k около 51 000 000? Программа будет работать примерно 82 года, я провел приблизительные расчеты.
Что могу сказать по такому решению? Задача не решена, ожидать годы для получения результата это не решение задачи. :)
Ожидал от вас более оптимального решения.

Ugar, попробуйте оптимизировать свой скрипт.

Дождался результата:
C++:
Expand Collapse Copy
2019.06.27 16:53:17.627    test8 EURUSD,H1: 100000 простое число =1299709
2019.06.27 16:39:36.383    test8 EURUSD,H1: initialized
2019.06.27 16:39:36.352    test8 EURUSD,H1 inputs: N_Sample=100000;
(с момента запуска прошло более 13 минут)

Задача эта, как раз на программирование, тут действовать перебором всех вариантов не получится. Нужен особый алгоритм.
 
Последнее редактирование:

Ugar

Гуру форума
Дождался результата:
C++:
Expand Collapse Copy
2019.06.27 16:53:17.627    test8 EURUSD,H1: 100000 простое число =1299709
2019.06.27 16:39:36.383    test8 EURUSD,H1: initialized
2019.06.27 16:39:36.352    test8 EURUSD,H1 inputs: N_Sample=100000;
(с момента запуска прошло более 13 минут)
Можно оптимизировать уменьшив количество проверок на остаток от деления. Но это не на много ускорит нахождения огромных номеров простых чисел. for(i=2; i<=a/2; i++)//Цикл перебирающий делитель
При таком цикле 100000 простое число находится за 6 минут.
Что бы построить программу работающую быстро (за секунды или даже доли секунды), нужно задумываться об оптимальности вычислений, для этого надо хорошо знать математику, что бы сразу вычислять нужное простое число, а не перебирать все.
Как вариант, если надо быстро получать нудное простое число, надо доставать готовое, а не считать. Я писал об этом ранее.
Как правило, трейдеры изучают программирование, что бы запрограммировать идею для своей торговли. Мало кто знает высшую математику что бы писать оптимальные программы. Покажите как напишите Вы. Может получится лучше?
 
Последнее редактирование:
Верх