MQL – Moja pierwsza automatyczna strategia inwestycyjna

MQL - roboty inwestycyjne

To już ostatnia lekcja programowania w języku MQL. I najbardziej ekscytująca. Na zakończenie tego cyklu wykorzystamy bowiem wszystkie poznane wcześniej elementy, aby stworzyć pełną, automatyczną strategię inwestycyjną. Jak pamiętamy z pierwszego artykułu (MQL – programowanie robotów handlu automatycznego) automatyczna strategia inwestycyjna to najbardziej zaawansowany program, który pozwala zawierać transakcje kupna i sprzedaży na rynkach finansowych bez naszego udziału.

Założenia

Jako przykład wykorzystamy strategię opartą na przecięciu się dwóch średnich kroczących. Jednej o dłuższym okresie i drugiej o krótszym. Sygnałem otwarcia pozycji będzie przecięcie się tych dwóch średnich, a rodzaj otwieranej pozycji określimy poprzez kierunek tego przecięcia. Przecięcie długiej średniej kroczącej od dołu przez krótką średnią zamyka otwartą pozycję sprzedaży (SELL) oraz otwiera nową pozycję kupna (BUY).

MQL

Natomiast przecięcie długiej średniej kroczącej od góry przez krótką średnią kroczącą skutkuje zamknięciem pozycji kupna (BUY) oraz otwarciem przeciwnej pozycji, czyli sprzedaży (SELL).

mql

Nie zapominamy oczywiście o obowiązkowym ustawianiu poziomu SL, który wyrażany będzie w pipsach jako odległość od ceny otwarcia.

Poziom take profit jest w naszym przypadku dowolnością. Jeśli go ustawimy, pozycja zostanie zamknięta poprzez osiągniecie tego poziomu lub poprzez odpowiednie przecięcie się średnich – w zależności od tego, co nastąpi wcześniej. W przypadku jego braku tylko przecięcie średnich zamyka zyskowne pozycje. Wielkość otwieranej pozycji jest natomiast stała i nie zmienia się automatycznie w czasie działania programu. Umożliwimy jednak ręczną modyfikację tego parametru.

Na podstawie powyższych założeń możemy wyodrębnić pięć parametrów wejściowych dla naszej automatycznej strategii. Będą to: okres dla krótkiej średniej kroczącej, okres dla długiej średniej, poziom SL, ewentualny poziom TP oraz wysokość pozycji wyrażona w lotach.

Implementacja

Podobnie jak we wcześniejszych przykładach, zaczynamy od kreatora. Tym razem jednak wybieramy tworzenie Doradcy Ekspertowego. Tu często możemy się zetknąć ze skrótem EA, pochodzącym od angielskiego Expert Advisor.

mql

Wciskamy przycisk „Dalej” i uzupełniamy dane naszego programu. Identycznie jak na załączonym poniżej screenie.

mql

Jak widać, tym razem wykorzystujemy możliwość zdefiniowania parametrów zewnętrznych w oknie kreatora. W artykule MQL – Mój pierwszy skrypt zrobiliśmy to bezpośrednio w kodzie, wykorzystując słówko extern przed typem i nazwą zmiennej.

Jako parametry wejściowe zdefiniowaliśmy sobie pięć zmiennych. Dwie pierwsze – longMaPeriod oraz shortMAPeriod typu int – określają okresy dla średnich kroczących. Przypisaliśmy im też wartości początkowe: odpowiednio 24 okresy dla dłuższej średniej oraz 12 okresów dla krótkiej średniej. Wartości te wybrałem zupełnie losowo. Dalej dodaliśmy parametry określające poziom take profit oraz stoploss. Przyjmują one wartości typu double. Im również przypisaliśmy pewne wartości początkowe. Na koniec umożliwiamy definiowanie wielkości otwieranej pozycji poprzez zdefiniowany parametr lot typu double, o wartości początkowej 0,1 lota. Klikamy Zakończ i otrzymujemy kod startowy wygenerowany przez środowisko.

mql

Identycznie jak w poprzednich przykładach (wskaźników, skryptów), kod zaczyna się od informacji ogólnych dotyczących programu.

Poniżej widzimy wszystkie zdefiniowane przez nas parametry zewnętrzne, czyli zmienne określające okresy średnich kroczących, poziomy take profit oras stop loss i wielkość pozycji.

Dwie ostatnie zmienne – „CROSSED_UP” i „CROSSED_DOWN” – nie zostały wygenerowane automatycznie przez środowisko. Są to zmienne pomocnicze dodane już przeze mnie, które  przydadzą się przy określaniu kierunku przecięcia się linii średnich. Ich zastosowanie zobaczymy w późniejszych elementach programu.

MetaEditor ponownie przygotował swoje funkcje specjalne init(), deinit() oraz start().

mql

W naszym przykładzie funkcje init() oraz deinit() nie będą przydatne. Pozostawiamy je więc puste.

Całą logikę strategii umieścimy w metodzie start(), a wygląda ona następująco:

mql

W pierwszej kolejności dokonujemy pewnej walidacji, której poprawne przejście pozwoli nam otwierać lub zamykać potencjalne pozycje. Nie jest to jeszcze walidacja bezpośrednio związana z naszą strategią. Przyjrzymy się jej za chwilę.

Jeśli więc przejdziemy naszą walidację, określimy kierunek przecięcia się średnich. Wykorzystujemy w tym celu zdefiniowaną przez nas metodę crossDirection(), a jej wynik przypisujemy do zmiennej crossed.

Poniżej wykorzystujemy metodę Print() służącą do wyświetlania dowolnego tekstu w dzienniku platformy Meta Trader. Służy nam to w tym przypadku tylko do testów, ale zastosowania mogą być dowolne.

Kolejne dwie linie kodu to wywołania naszych metod closePositions() oraz openPositions(). Obie przyjmują jako parametr określoną wcześniej zmienną crossed. Pierwsza z nich służy do zamknięcia pozycji spełniających warunki naszej strategii, a druga do ich otwarcia, oczywiście również przy zachowaniu odpowiednich warunków, zgodnych z zakładaną strategią.

Zajrzyjmy teraz głębiej w kod, a zaczniemy od prześledzenia, na czym będzie polegała pierwsza walidacja.

mql

Mamy tu dwa sprawdzenia. Pierwsze z nich weryfikuje, czy na wykresie jest więcej niż 100 słupków. Jeśli nie, to wyświetlamy komunikat o błędzie oraz zwracamy wynik false, który uniemożliwia kontynuację, w tym wywołanie metody start(), dalszego działania procesu strategii. Wykorzystaliśmy tu zmienną predefiniowaną Bars, którą poznaliśmy już podczas tworzenia własnego wskaźnika (MQL – Mój pierwszy wskaźnik).

Drugie sprawdzenie wymusza na użytkowniku podanie poziomu stop loss większego niż 100 pipsów. Jeśli wartość ta będzie mniejsza, działanie programu również nie będzie niemożliwe. Co zasygnalizowanie zostanie wpisem w dzienniku dzięki wykorzystaniu metody Print().

Jeśli oba sprawdzenia przejdą walidację, będziemy mogli przejść do kolejnego kroku, czyli do określenia kierunku przecięcia się średnich kroczących. Stworzyliśmy do tego metodę crossDirection().

mql

Z przecięciem się średnich kroczących w górę mamy do czynienia w sytuacji, gdy dwie świece temu wartość długiej średniej była większa niż wartość krótkiej średniej, a jedną świecę temu nastąpiła zamiana stosunku tych wartości, czyli teraz krótka średnia ma większą wartość niż długa średnia.

img_123

Kierunek w dół będzie w sytuacji odwrotnej, czyli wtedy, gdy najpierw to krótka średnia miała większą wartość niż długa średnia, a w kolejnej świecy sytuacja się odwróciła i teraz długa średnia jest większa od krótkiej.

mql

Implementacja tej koncepcji w metodzie crossDirection() wygląda następująco.

Zaczynamy od przygotowania sobie kilku zmiennych (previousLongMA, previousShortMA, currentLongMA, currentShortMA), które posłużą do przechowywania wartości poszczególnych średnich.

Do określenia tych danych wykorzystujemy funkcję iMA(), która zwraca wartość średniej kroczącej według podanych parametrów.

double iMA(string symbol, int timeframe, int period, int ma_shift, int ma_method, int applied_price, int shift) – wylicza średnią kroczącą i zwraca jej wartość; parametry:

  • symbol – symbol, dla którego mają zostać wykonane wyliczenia; NULL oznacza bieżący symbol na aktywnym wykresie;
  • timeframe – interwał czasowy wykorzystywany do wyliczeń; 0 oznacza interwał aktywnego wykresu;
  • period – okres średniej;
  • ma_shift – przesunięcie linii średniej; 0 – bez przesunięcia, wartości większe od 0 przesuwają linię w prawo, a mniejsze od 0 w lewo;
  • ma_method – metoda wyliczania średniej; może przyjąć wartości: MODE_SMA, MODE_EMA, MODE_SMMA, MODE_LWMA;
  • applied_price – cena wykorzystywana do obliczania średniej, np. PRICE_OPEN, PRICE_CLOSE, PRICE_HIGH, PRICE_LOW, PRICE_MEDIAN, PRICE_TYPICAL, PRICE_WEIGHTED;
  • shift – index słupka, dla którego ma zostać wyliczona wartość średniej; 0 oznacza aktualny słupek, 1 poprzedni słupek, itd.

 
Najpierw określamy wartość długiej średniej kroczącej sprzed dwóch okresów. W tym przypadku metoda iMA() przyjmuje następujące parametry:

  • symbol = NULL – symbol z bieżącego wykresu;
  • timeframe = 0 – przedział czasowy z bieżącego wykresu;
  • period = longMAPeriod – okres średniej z parametru zewnętrznego podanego przez użytkownika;
  • ma_shift = 0 – średnia bez przesunięcia;
  • ma_method = MODE_SMA – prosta średnia krocząca;
  • applied_price = PRICE_CLOSE – średnia wyliczana na podstawie cen zamknięcia;
  • shift = 2 – wartość średniej dwa okresy temu.

mql

Analogicznie wyliczamy wartości dla długiej średniej kroczącej jeden okres temu (parametr shift = 1) oraz dla krótkiej średniej dwa okresy i jeden okres temu.

Mając te wartości za pomocą instrukcji warunkowych if, określamy kierunek przecięcia zgodnie z założeniami opisanymi wcześniej.

mql

Mając określony kierunek przecięcia linii, wracamy do metody start(), gdzie na podstawie tej wartości możemy zawrzeć odpowiednią transakcję.

Najpierw jednak próbujemy zamknąć ewentualne pozycje.

mql

string OrderSymbol() – zwraca nazwę instrumentu dla wybranego zlecenia (poprzez OrderSelect()).

 

string Symbol() – zwraca nazwę instrumentu na bieżących wykresie.

 
Porównanie to oznacza zatem, że wybieramy tylko te zlecenia, których instrument jest zgodny z tym na aktualnie otwartym wykresie.

Dalej już jest łatwo. Jeśli wybrana pozycja jest pozycją kupna, a linie średnich przecinają się w dół, to zamykamy tę pozycję. Jeśli wybraliśmy pozycję sprzedaży, a średnie przecięły się w górę, to zgodnie z założeniami strategii zamykamy taką pozycję.

Metody closeBuyPosition() oraz closeSellPosition() nie są również bardzo skomplikowane. Ich zadaniem jest tylko wysyłanie żądania zamknięcia wybranego wcześniej zlecenia.

mql

Wykorzystaliśmy tu kilka nowych funkcji.

int OrderTicket() – zwaraca unikalny numer ticket wybranego wcześniej zlecenia (poprzez OrderSelect()).

 

double OrderLots() – zwraca wielkość w lotach wybranej wcześniej pozycji (poprzez OrderSelect()).

 

bool OrderClose(int ticket, double lots, double price, int slippage, color Color = CLR_NONE) – zamyka otwarte zlecenie. Jeśli się powiedzie, zwraca wartość true, w przeciwnym razie zwróci false. Parametry:

  • ticket – unikalny numer zlecenia;
  • lots – wielkość zamykanej pozycji;
  • price – cena zamknięcia;
  • slippage – maksymalna wartość poślizgu ceny w punktach;
  • color – opcjonalny parametr powodujący narysowanie strzałki na wykresie w miejscu zamknięcia pozycji.

 
Przyjrzyjmy się teraz metodzie otwierającej zlecenia. Ogólnie mówiąc, otworzy ona pozycję kupna, gdy średnie przetną się w górę, a pozycję sprzedaży, gdy te same średnie przetną się w dół.

mql

Poprzez warunek „if (total == 0)” zabezpieczamy się, by nie mieć w danym momencie więcej niż jedną otwartą pozycję na danej parze walutowej.

To, co najbardziej nas ciekawi, znajduje się w metodach openBuyPosition() i openSellPosition(). Zajrzyjmy więc do ich kodu. Zacznijmy od otwarcia pozycji kupna.

mql

W tym miejscu określamy parametry dla nowego zlecenia. Wydaje mi się, że ten fragment kodu jest w miarę zrozumiały i nie wymaga dodatkowego tłumaczenia. Na końcu metody wszystkie parametry przekazujemy do metody openPosition(), której przyjrzymy się już za chwilkę. Najpierw jeszcze tylko pokażę, jak wygląda metoda openSellPosition(). Jest ona analogiczna do poprzedniej.

mql

Na koniec zostało nam już tylko wysłanie zlecenia na rynek. Tę funkcjonalność zamknęliśmy w metodzie openPosition().

mql

Do wysłania zlecenia na rynek wykorzystujemy funkcję OrderSend().

int OrderSend(string symbol, int cmd, double volume, double price, int slippage, double stoploss, double takeprofit, string comment = NULL, int magic = 0, datetime expiration = 0, color arrow_color = CLR_NONE) – funkcja pozwalająca otwierać pozycje lub składać zlecenia oczekujące. Zwraca unikalny numer ticket nowego zlecenia lub -1 w przypadku niepowodzenia. Parametry:

  • symbol – instrument otwieranej pozycji;
  • cmd – typ operacji; może to być jedna z wartości: OP_BUY, OP_SELL, OP_BUYLIMIT, OP_SELLLIMIT, OP_BUYSTOP lub OP_SELLSTOP;
  • volume – wielkość otwieranej pozycji (w lotach);
  • price – cena otwarcia;
  • slippage – maksymalne obsunięcie ceny otwarcia;
  • stoploss – poziom stop loss;
  • takeprofit – poziom take profit;
  • comment – opcjonalny komentarz dla zlecenia;
  • magic – tak zwany magiczny numer, który może służyć do identyfikowania pozycji otwartych poprzez tą strategię automatyczną;
  • expiration – data wygaśnięcia zlecenia (tylko dla zleceń oczekujących);
  • arrow_color – kolor rysowanej strzałki przy poziomie otwarcia pozycji; parametr opcjonalny.

 
Ostatnie sprawdzenia to weryfikacja, czy zlecenie zostało poprawnie otwarte. Jeśli tak, wyświetlamy odpowiedni komunikat wraz z ceną otwarcia pozycji. W przeciwnym razie informujemy o błędzie za pomocą metod Print() oraz GetLastError().

To wszystko, jeśli chodzi o implementację. Nasza automatyczna strategia inwestycyjna jest gotowa do testów. Czas przekonać się, na co ją stać i czy, co najważniejsze, może dać nam jakieś zyski.

Kompilacja i instalacja

Ten element już doskonale znamy. Wciskamy więc F5 (lub przycisk Kompiluj) i jeśli nie ma żadnych błędów, przechodzimy do platformy transakcyjnej Meta Trader.

Testy

Platforma MetaTrader udostępnia bardzo ciekawe i przydatne narzędzie do testowania wszelkich strategii inwestycyjnych napisanych w języku MQL. Nazywa się ono po prostu Testerem Strategii. Znajdziemy je w menu „Widok” → „Tester strategii”. Możemy też wykorzystać kombinację klawiszy Ctrl+R.

mql

Na dole platformy otworzy się okno testera.

mql

Z rozwijanej listy strategii wyszukujemy i wybieramy nazwę naszej strategii. Poniżej możemy wybrać symbol, na którym wykonamy testy, a zaraz obok okres dla wykresu. Możemy zawęzić przedział czasowy objęty testem. W tym celu zaznaczmy checkbox „Użyj daty”, a tuż obok wybieramy zakres dat. Przycisk „Właściwości strategii…” po prawej stronie testera pozwala dopasować parametry wejściowe dla naszego programu.

mql

Na razie jednak sprawdźmy, jakie rezultaty otrzymamy przy wartościach domyślnych. Testy zaczynamy, klikając przycisk „Start”. Po pewnej chwili zielony pasek postępu powinien dojść do końca, a w oknie testera pojawią się trzy nowe zakładki (Rezultaty, Wykres, Raport).

mql

Zanim jednak do nich przejdziemy, warto jeszcze wspomnieć o możliwości prześledzenia na wykresie cen wszystkich transakcji zawartych w ramach testów. Służy do tego przycisk „Otwórz wykres”. Dzięki temu możemy zweryfikować, czy wszystkie pozycje zostały otwarte zgodnie z założeniami określonymi w strategii.

mql

Wróćmy do wspomnianych nowych zakładek testera. Na pierwszej z nich, „Rezultatach”, mamy listę wszystkich zagrań. Przypomina ona nieco w uproszczeniu historię transakcji.

mql

W kolejnej zakładce, „Wykresie”, widzimy krzywą naszego kapitału.

mql

Jak widać, nie wygląda to dobrze. Jesteśmy na bardzo dobrej drodze do wyzerowania naszego konta. Jednak fakt, że w tym przypadku dana strategia przyniosła straty, nie musi wcale oznaczać, że jest zła lub że nie działa. Może wystarczy delikatnie zmodyfikować parametry, np. ustawić inną parę walutową, inny interwał czasowy czy inne okresy średnich, by ze stratnej strategii przeobraziła się w zyskowną. Wszystko to są elementy tworzenia skutecznego systemu gry na rynkach finansowych.

Zakładka „Raport” dostarcza statystyki testowanej strategii. Wylicza między innymi liczbę wszystkich transakcji, w tym liczbę zakończonych zyskiem i stratą, średni zysk, średnią stratę.

mql

Przydatną funkcjonalnością jest zapisanie tych informacji jako html-owy raport, który zawiera wszystkie dane z trzech zakładek opisanych powyżej. Wystarczy kliknąć prawym przyciskiem myszy w obszarze testera i wybrać pozycję „Zapisz jako Raport.”

mql

 

mql

Gdy uda nam się tak dopracować strategię, by dawała stabilne zyski na danych historycznych, kolejnym krokiem są już testy na danych rzeczywistych. Oczywiście cały czas nadal pracujemy na koncie demo. Jeszcze za wcześnie, by ryzykować realne pieniądze.

Uruchomienie

Załóżmy, że nasz robot inwestycyjny daje nam już pozytywne wyniki na danych historycznych. Czas go uruchomić na bieżących danych rynkowych.

Dodać strategię automatyczną możemy za pomocą okna nawigatora. Wystarczy na liście zlokalizować nazwę naszego programu, po czym przeciągnąć go lewym przyciskiem myszy na wykres bądź dwukrotnie kliknąć w nazwę.

mql

Otworzy się okno z właściwościami naszego programu, identyczne jakie widzieliśmy w przypadku testera strategii. Po zamknięciu tego okna przyciskiem OK w prawym górnym rogu wykresu powinniśmy zobaczyć nazwę strategii wraz z uśmiechniętą buźką.

Może się zdarzyć, że buźka będzie smutna lub zamiast niej pojawi się krzyżyk. Oznacza to, że nie wszystko jeszcze mamy odpowiednio ustawione na platformie MT4 i niestety strategia nie zadziała.

mql Strategia działa poprawnie.
mql Prawdopodobnie nie został włączony mechanizm automatycznych strategii. Spróbuj wcisnąć przycisk mql znajdujący się na pasku narzędzi.
mql Mechanizm strategie jest włączony, ale brakuje mu uprawnień do składania zleceń. Przejdź do Narzędzia → Opcje → zakładka Strategie i sprawdź, czy jest zaznaczona opcja „Umożliw handel”.

 
Po ustawieniu tych parametrów może być potrzebne ponowne dodanie strategii do wykresu.

Jeśli udało się nam doprowadzić do sytuacji, że buźka jest uśmiechnięta, oznacza to, że robot już dla nas pracuje. Możemy więc cierpliwie czekać na pierwsze wyniki…

Podsumowanie

Dzisiaj było bardzo dużo informacji i dlatego dziękuję, że dotarłeś do końca. Założenia naszej testowej strategii nie były skomplikowane, ale podejrzewam, że jej implementacja mogła przyprawić niektórych o zawrót głowy.

Mam jednak nadzieję, że udało mi się w dość jasny sposób pokazać niewielką część możliwości, jakie kryją się za językiem MQL i zachęcić Cię do zgłębiania tego tematu. Gorąco polecam wszystkim dalszą naukę.

Być może właśnie Ty otworzysz sobie drogę do wolności finansowej zbudowanej z dochodu pasywnego, jaki generowany jest przez samodzielnie zaprogramowane roboty inwestycyjne. Serdecznie życzę powodzenia!


Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

Komentarz do “MQL – Moja pierwsza automatyczna strategia inwestycyjna