Программирование на MQL 4: Циклы
|

Программирование на MQL 4: Циклы

   Прежде чем перейти к дальнейшему изучению языка MQL 4, давайте вспомним, что было сказано на эту тему в предыдущих 4-х выпусках журнала Forex Magazine.


   До этого момента мы рассматривали, что такое переменные языка MQL 4, каких типов они бывают, и как правильно объявлять переменные. Далее мы разобрали, что такое функции, и как их правильно оформлять. Затем мы научились из написанных нами функций организовывать подключаемые файлы и использовать их в дальнейшем при написании своих программ. Так же мы рассмотрели, каким образом мы можем воспользоваться библиотеками функций, написанными на других языках.


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


   Для наглядности рассмотрения дальнейшего материала, давайте сначала попробуем составить словесное описание шаг за шагом какого-нибудь более или менее сложного алгоритма.


   Многие из читающих эти строки знакомы с индикатором Aroon. Его алгоритм детально описан Tushar Chande в сентябрьском выпуске журнала Technical Analysis of Stocks & Commodities за 1995 год. На русском языке описание алгоритма и применение этого индикатора можно найти в интернете на страничке


   Внимание, в переводе по указанной ссылке есть небольшая ошибка: вместо упоминаемых n-дневных High и Low, следует читать n-периодный.


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


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


   . Так как индикатор состоит из двух линий, то нам следует вычислять по два числа для каждого бара. Для удобства дальнейшей работы заведём некоторую таблицу, в которой будут две строки, соответствующие первому и второму значению индикатора, и множество колонок, соответствующее количеству индикаторов, на которых мы будем строить индикатор.


   Далее начинаем непосредственно считать значения индикатора Aroon на каждом из баров графика котировок, а именно:


   1. Для того бара, на котором считается текущее значение индикатора, выполняем действия:


   a. ищем бар среди предшествующих баров, на котором достигается максимум за указанный период. Запоминаем его номер.


   b. ищем бар среди предшествующих баров, на котором достигается минимум за указанный период. Запоминаем его номер.


   c. Находим количество периодов, прошедших со времени последнего максимума на указанном периоде, и ранжируем значение так, чтобы при достижении максимума на текущем баре значение было 100. Заносим значение в первый ряд таблицы в колонку, соответствующую бару, на котором считается текущее значение индикатора.


   d. Находим количество периодов, прошедших со времени последнего минимума на указанном периоде, и ранжируем значение так, чтобы при достижении минимума на текущем баре значение было равно 100. Заносим значение во второй ряд таблицы в колонку соответствующую бару, на котором считается текущее значение индикатора.


   2. Проверяем, есть ли ещё на графике котировок бары, для которых требуется подсчитать значение индикатора. Если такие бары есть, то для повторения вычислений на следующем баре переходим к пункту 1. Если таких баров нет, то заканчиваем алгоритм.


   В конце работы этого алгоритма у нас появится табличка со значениями, глядя на которые, мы можем построить изображение индикатора Aroon на листке бумаги.


   Теперь рассмотрим основные конструкции, которые мы использовали при построении алгоритма: так как нам приходится перебирать бары до каких-либо пор, то мы используем конструкцию “цикл”.


   Если отвлечься от деталей алгоритма, то его можно было бы представить в виде следующей схемы:


Выполнять цикл {
    …
    Здесь выполняются какие-либо действия
    …
    Проверить некоторое условие.
    Если условие выполнено, то повторить цикл, иначе – выйти из цикла.
    …
}


   Для указания начала и конца цикла используются так называемые операторные скобки. В нашем случае открывающей операторной скобкой является левая фигурная скобка, а закрывающей операторной скобкой является правая фигурная скобка. Из предыдущих публикаций о программировании на MQL 4 видно, что в этом языке так же используются фигурные скобки в качестве операторных скобок. Мы уже сталкивались с ними для указания начала и конца функций. Начало и конец циклов в MQL 4 тоже указываются левой и правой фигурными скобками соответственно.


   В MQL 4 существуют два вида циклов, далее для краткости будем называть их “for” и “while”. Первый тип “for” используют, как правило, для того, чтобы определённое количество раз повторить какое-либо действие. Записывается такой цикл, например, так:
 
int i;
 
for( i=0; i < 100; i++) {
 print(i);
}


   Здесь показано, как организовать цикл, который выполняется 100 раз. Первая итерация приведённого цикла выводит на печать в журнал число 0. Перед каждой следующей итерацией, число, хранящееся в целочисленной переменной “i”, увеличивается на единицу и снова выводится на печать. Таким образом, в результате работы этого цикла, в журнал будут напечатаны числа от 0 до 99. Видно, что оператор “for” имеет три параметра, разделённых точками с запятой. Первый параметр “i=0” говорит о том, что перед первым выполнением тела цикла переменной “i” будет присвоено значение “0”. Второй – “i < 100” говорит о том, что цикл будет повторяться до тех пор, пока число, хранящееся в переменной “i”, будет меньше “100”. Третий – “i++” говорит о том, что после каждой итерации цикла, число, хранящееся в переменной “i”, будет увеличиваться на 1.


   Приведённый ниже пример цикла “for” выводит числа в обратном порядке, то есть от 99 до 0.
 
int i;
 
for( i=100; i >= 0; I–) {
 print(i);
}
 
   Второй тип циклов в MQL 4, – “while”, используется, когда нельзя точно сказать, какое количество итераций нужно повторить, но есть определённое условие, после выполнения которого следует завершить цикл. Приведённый ниже пример показывает, как вывод чисел от 0 до 99 можно запрограммировать, используя цикл типа “while”:
 
int i = 0;
 
while(i < 100) {
 print(i);
 i++;
}
 
   Как мы видим, циклы взаимозаменяемы. И в том и в другом случае может присутствовать какая-то начальная инициализация, так же в обоих случаях могут присутствовать проверка некоторого условия, для того, чтобы решить, продолжить ли цикл или следует его завершить. Разница заключается лишь в том, что синтаксис “while” подчёркивает его ориентацию именно на проверяемое условие цикла, а синтаксис “for” – его ориентацию на равномерное увеличение счётчика, по которому выполняется циклический перебор некоторых значений.


   Например, когда нам потребуется перебрать определённое количество баров, нагляднее было бы воспользоваться именно циклом “for”.


   В рассмотренном выше алгоритме индикатора требуется рисовать линии Aroon’а на протяжении всей истории имеющихся у нас котировок, значит, мы с уверенностью можем сказать, сколько баров нужно перебрать, вычисляя необходимые значения. Из этого следует, что нагляднее было бы использовать цикл “for”.


   Ниже приведён исходный текст индикатора Aroon на языке MQL 4, демонстрирующий использование цикла “for”.


//+——————————————————————+
//|                                                        Aroon.mq4 |
//|                                           Copyright c 2004, Horn |
//|                                               alexander@indus.ru |
//+——————————————————————+
#define   copyright “Copyright c 2004, Horn”
#define   link      “alexander@indus.ru
 
int       g_period;
 
int       g_LineColor1;
int       g_LineStyle1;
int       g_LineWidth1;
int       g_LineColor2;
int       g_LineStyle2;
int       g_LineWidth2;
 
int init(int period=10,
 color LineColor1=Red,
 int LineWidth1=1,
 int LineStyle1=STYLE_SOLID,
 color LineColor2=MediumBlue,
 int LineWidth2=1,
 int LineStyle2=STYLE_SOLID)
{
   g period=period;
   g_LineColor1=LineColor1;
   g_LineWidth1=LineWidth1;
   g_LineStyle1=LineStyle1;
   g_LineColor2=LineColor2;
   g_LineWidth2=LineWidth2;
   g_LineStyle2=LineStyle2;
   
   return(0);
}
 
int deinit()
{
   return(0);
}
 
int start()
{
   int i;
   int HighestBar, LowestBar;
   double aroonUp, aroonDn;
 
   
   for(i=0; i < Bars-g_period; i++) {
      // Ищем номер бара с максимумом за указанный период
      HighestBar = Highest(MODE_HIGH,i+g_period-1,g_period);
      // Ищем номер бара с минимумом за указанный период
      LowestBar = Lowest(MODE_LOW,i+g_period-1,g_period);
 
      // Находим количество периодов, прошедших со времени последнего 
      // максимума/минимума на указанном периоде, и ранжируем значение
      // так, чтобы при достижении максимума/минимума на текущем баре
      // значение Aroon’ов было соответственно равно 100
      aroonUp = 100 – ((HighestBar – i) / g_period) * 100;
      aroonDn = 100 – ((LowestBar – i) / g_period) * 100;  
 
      // Показываем линии
      SetIndexValue(0, i, aroonUp);
      SetIndexValue(1, i, aroonDn);
   };
   
   return(0);
}
 
   На сегодня всё. В следующем номере мы рассмотрим ещё одно упомянутое в начале статьи недостающее звено, ещё одну основную языковую конструкцию: “условные операторы”.


Александр Иванов
для Forex Magazine