1. MQL4 dla początkujących. Część I.

1.9. Operator pętli for

Pętle (ang. loops) to kolejne potężne narzędzie MQL4. Są one przydatne w przypadku wielokrotnie powtarzających się działań tego samego typu. Załóżmy, że trzeba znaleźć średnią wartość najwyższych cen dla 5 świec, tj. od indeksu 0 do 4. Można zrobić to tak jak pokazano w kodzie 1.

Kod 1
#property strict

void OnStart()
  {
//---
   double Av_High = 0.0;

   Av_High = ( High[0] + High[1] + High[2] + High[3] + High[4] ) / 5;
                          
//--- wyświetlić wynik
   Alert("Średnia wartość cen High świec od 0 do 4 = " , Av_High);
  }

W powyższym kodzie najpierw zadeklarowano zmienną Av_High typu double i przypisano jej wartość 0.0. W kolejnej instrukcji zsumowano wartości High pięciu świec od [0] do [4], podzielono na 5 i wynik przypisano Av_High. Ostatnią instrukcją jest wyświetlenie komunikatu za pomocą funkcji Alert().

Widzimy tutaj kilka powtarzających się działań matematycznych, mianowicie zsumowanie pięciu High. Zapiszmy ten kod teraz trochę inaczej (kod 2).

Kod 2
#property strict

void OnStart()
  {
//---
   double Av_High = 0.0;

   Av_High += High[0]; // do Av_High dodajemy wartość ceny High świecy z indeksem 0
   Av_High += High[1];
   Av_High += High[2];
   Av_High += High[3];
   Av_High += High[4]; // Av_High równa się sumie cen High świec od 0 do 4
//---
   Av_High /= 5;       // Av_High równa się jednej piątej poprzednio uzyskanej sumy
                          
//--- wyświetlić wynik
   Alert("Średnia wartość cen High świec od 0 do 4 = " , Av_High);
  }

W tym kodzie zastosowaliśmy metodę opisaną w rozdziale 1.5. Praca ze zmiennymi, kod 2 i tutaj Av_High zwiększamy o kolejną wartość High używając zapisu +=. Zapis Av_High /= 5 mówi o tym, że suma przechowywana w Av_High została podzielona na 5 i wynik dzielenia z powrotem został przypisany zmiennej Av_High.


Powyższe skrypty będą działać prawidłowo, ale co robić jeśli trzeba znaleźć średnią wartość dla 1000 świec lub więcej? Właśnie do takich celów najlepiej używać pętlę. Pewnie zauważyłeś, że wszystkie operacje dodawania w powyższym przykładzie są takie same. Do zmiennej Av_High dodajemy po kolei wartości cen z tablicy High[ ]. Zmienia się tylko indeks od [0] do [4]. Było by o wiele łatwiej użyć jakiś licznik, za pomocą którego można było by pobierać dane z tej tablicy. Popatrz, jak taki algorytm można zrealizować za pomocą pętli for:

Kod 3
#property strict

void OnStart()
  {
//---
   double Av_High = 0.0;

//--- pętla 'for'
   for(int i = 0 ; i < 5 ; i++)
     {
      Av_High += High[i];
     }
//---
   Av_High /= 5;

//--- wyświetlić wynik
   Alert("Średnia wartość cen High świec od 0 do 4 = " , Av_High);
  }

Pętla składa się z kluczowego słowa for. W okrągłych nawiasach ( ), tj. w nagłówku operatora, należy wpisać trzy argumenty oddzielone od siebie średnikami. Następnie, między klamrami { }, tj. w ciele pętli, należy wpisać powtarzające się działania. Niżej jest przedstawiony schemat tej pętli.

Kod 4
for(condition_1 ; condition_2 ; condition_3)
  {
   // powtarzalne działania
  }

Condition_1:  dokonuje się deklaracja i inicjalizacja zmiennej, która będzie pełnić rolę licznika. Jego nazwa może być dowolna. Stosuje się tylko typ int. Konieczne tu jest określenie wartości początkowego indeksu, z którego pętla zacznie działać. Zapis int i = 0 oznacza: int to typ zmiennej-licznika, i - to jego nazwa, a początkowy indeks równa się 0.

Condition_2:  tu się sprawdza warunek przerwania pętli. Jeśli wartość licznika nie będzie zgodna z opisanym tu warunkiem, następuje przerwanie pętli. Zapis i < 5 oznacza – jeśli wartość licznika i jest zgodna z tym warunkiem (0 < 5 – prawda) wtedy program przechodzi do obliczeń zapisanych w ciele pętli, mówiąc inaczej do iteracji (iteracja – powtarzanie tego samego działania).

Condition_3:  po przeprowadzeniu obliczeń w ciele pętli, licznik zwiększa się o określoną wartość. Zapis i++ oznacza, że po zakończeniu iteracji licznik i zwiększy się o 1.


W naszym przykładzie (kod 3) na początku 4-ej iteracji, tj. kiedy i = 3, po zakończeniu wszystkich działań i zostanie powiększony o 1. Przed przejściem do następnej iteracji sprawdzana jest poprawność drugiego warunku i jeśli on jest poprawny (w tym przypadku tak, bo 4 < 5 to prawda) to program przejdzie do realizacji kolejnych działań w ciele pętli.

Na końcu 5-ej iteracji (i = 4) i będzie równe 5 i kolejna iteracja nie zostanie zrealizowana, ponieważ drugi warunek nie będzie już prawdziwy (5 < 5 – fałsz), to spowoduje przerwanie pętli for i przejście programu do działań zapisanych po pętli.

Warunek przerwania pętli (Condition_2) może wyglądać inaczej.

Kod 5
i <= 5   // pętla działa do póki 'i' jest mniejszy lub równy 5
i > 10   // pętla działa do póki 'i' jest większy niż 10
i >= 777 // pętla działa do póki 'i' jest większy lub równy 777

Licznik też można zmieniać inaczej (Condition_3):

Kod 6
i--      // licznik 'i' będzie pomniejszany o 1
i -= 2   // licznik 'i' będzie pomniejszany o 2
i += 25  // licznik 'i' będzie powiększany o 25

W celu utrwalenia materiału w pamięci stałej swojego mózgu, znajdźmy teraz średnią wartość najniższych cen (Low) dla 6 świec z parzystymi indeksami, tj. świec z indeksami 0, 2, 4, 6, 8 i 10. Dla małego utrudnienia zacznijmy liczyć od 10 do 0.

Kod 7
#property strict

void OnStart()
  {
//---
   double Av_High = 0.0;
   int    Start   = 10;
   int    End     = 0;

//--- pętla 'for'
   for(int i = Start; i >= End; i -= 2)
     {
      Av_High += Low[i];
     }
//---
   Av_High /= 6;

//--- wyświetlić wynik
   Alert("Średnia wartość cen Low parzystych świec od 10 do 0 = " , Av_High);
  }