Pierwszy krok w tworzeniu robota handlu

Anonim

Ten artykuł jest kontynuacją wszczęty 61 pokoi ForTrader magazyn. org cycle "Tworzenie robota handlowego: od A do Z". Zakłada się, że w tym momencie czytelnik jest już zaznajomieni z systemem handlu, którą przekształca się w robota, więc w tym artykule rozważymy początkową fazę pisania eksperta. Ta wersja robota zostanie nieco uproszczona, aby ułatwić zrozumienie kodu źródłowego.

Aby zaimplementować robota

należy najpierw ustalić, które moduły logiczne powinny pochodzić. Moduł detekcji sygnału transakcyjnego

Zadaniem tego modułu jest

wyszukiwanie instrumentu handlowego , w którym sygnał istnieje w danym momencie. Moduł określa sygnał dla każdego konkretnego instrumentu handlowego. Aby określić ogólny trend dla grupy narzędzi, musisz używać tego modułu tyle razy, ile narzędzi są dostępne w ustawieniach robota.

Z punktu widzenia programu może wyglądać

, aby wypełnić dwuwymiarową tablicę , gdzie indeks zerowy drugim wymiarze jest nazwą instrumentu handlowego, a pierwszy - sygnał instrumentu.Oznacza to, że aby znaleźć wspólny sygnał (ogólny kierunek) w dowolnym momencie będzie musiał tylko zrobić tablicę objazd bez wykonywania wykrywanie sygnału przez instrumentu ponownie. Jeśli odniesiesz się do opisu proponowanego systemu obrotu, możesz przypomnieć, że dla każdego konkretnego instrumentu zostanie ustalona przez ofertę handlową. W tym kontekście warto użyć drugiego indeksu w drugim wymiarze tablicy, w którym zostanie wyświetlony numer tego instrumentu handlowego. W tym przykładzie wykonania, moduł robota nie będzie (w celu poprawienia czytelności kodu), więc drugi wskaźnik drugiego wymiaru tablicy zostaną wypełnione z tym samym numerem - partii ustawieniach robotów pracujących.

999 Powróćmy do pomysłu modułu definicji sygnału dla konkretnego instrumentu. Moduł będzie osobną podprogramem (funkcją). Sam kod modułu będzie:

// + -------------------------------------- - +

// |

funkcja wyszukiwania sygnałów handlowych

| int find_signal (string Symb) { if (ıJawna (symb, 0, 0)> iMA (Symb, 0, MA_Period, MA_Shift, mA_Method, MA_Applied_Price, 0))

/ *, jeżeli cena otwarcia Symb postać w tym przedziale czasowym jest większe niż średniej ruchomej - zwiększenie sygnału * /

zwrotu (1);

if (ıJawna (symb, 0, 0)

/ *, jeżeli cena otwarcia Symb postać w tym przedziale czasu jest mniejsza niż średnia ruchoma - sygnał redukcji * /

powrotu (-1),

/ * jeśli nie ma sygnału, a następnie powrócić 0 * /

return (0);

}

// |

sygnały handlu funkcja wyszukiwania

| // ---- + ----------------------------------- + W tym przypadku parametry średniej ruchomej są pobierane do parametrów wejściowych robota (Robot góry kod zostanie pokazane później):

zewnętrzny Int MA_Period = 8 // czas uśredniania średniej ruchomej

Int zewnętrzny MA_Shift = 0 // zmiany średniej ruchomej

zewnętrzny Int mA_Method = 1 / * Sposób jesteś obliczanie średniej ruchomej

0 - prosty średniej ruchomej

1 - wykładniczy Moving Average

2 - wygładzone średniej ruchomej

3 - liniowo ważonej średniej kroczącej

* /> extern Int MA_Applied_Price = 1 / * używane Cena do obliczania średniej ruchomej

0 - cena zamknięcia

1 - cena otwarcia

2 - maksymalna cenę

3 - Niska cena,

4 - średnia cena (wysoki + niska) / 2

5 - typowy Cena (+ blisko wysoki + niska) / 3

6 - ważone Cena zamknięcia (wysoki + niskie + blisko + zamknij) / 4

* /

A zatem, sygnał wywołania funkcji find_signal (ciąg Symb) jest odbierany w punkcie B Ox Symb 1 - wzrost -1 - spadek i 0 - brak sygnału.

1. Otwórz moduł sprawdzania zamówienia

Niezbędne jest zrozumienie, czy na tym instrumencie jest otwarte zlecenie tego robota, czy nie. Jeśli nie ma transakcji, robot będzie szukał okazji, aby ją otworzyć. Jeśli tak, to będzie towarzyszyć i szukać okazji, aby ją zamknąć.

Wracając do tematu zamknięcia (patrząc w przyszłość), należy pamiętać, że

Zamknięcie transakcji, „rynek”

może być przypadek, gdy całkowity sygnał zmienia się na przeciwną stronę (w stosunku do kierunku otwartych zleceń). Ponieważ roboty handlowe będą używać takich narzędzi, jak *** USD i USD *** (na przykład GBPUSD i USDCHF), należy wprowadzić niektóre tagi - dokładnie to, jak robot powinien oceniać to narzędzie. W terminologii naszego zespołu (ze względu na doświadczenie tworzenia robotów handlowych oceniające zestawy narzędzi) etykieta ta nazywana jest „współczynnik instrumentu”, a typ narzędzia *** jest równe 1 i -1 *** (w naszym przypadku - USD). Oznacza to, że w przykładzie GBPUSD będzie to 1, a dla USDCHF wynosi -1. Współczynniki te są przyjmowane do parametrów wejściowych, a w kodzie robota są dodawane do tablicy narzędzi jako kolejny indeks drugiego wymiaru. Tak więc, w naszej dwuwymiarowej tablicy docelowej będziemy również przechowywać etykietę "gdzie to narzędzie" wygląda na całą grupę.

Wróćmy do tego modułu. Zostanie on również wdrożony jako osobna podprocedura (funkcja). Kod jest dość prosty: // + --------------------------------------- + // |

funkcja wyszukiwania otwarty porządek

|

int find_orders (int type = -1, int = -1 magia, string Symb = NULL) { int i = 0; // licznik cykli for (i = OrdersTotal () - 1, i> = 0; i-) {, jeśli nadal; (! OrderSelect (I SELECT_BY_POS, MODE_TRADES))

// Jeżeli tak nie jest zaznaczone - przejście do następnego etapu cyklu

if (((OrderType () == typu) || (typ == - 1))

&& ((OrderMagicNumber () == magic () = (999) && (OrderSymbol () == Symb)) {

/ * IF ((dla typu zlecenia == typu) OR (typ == - 1))

i ((magiczna liczba zleceń == magia) OR (magia == - 1))

i (zamówienia Symb == symbol))

rozkaz powrotu bilet * /

return (OrderTicket ());

przerwa; // wyjście z pętli

}

}

// jeśli dojdziemy do tego punktu - wtedy nie znaleziono nakazu - zwróć -1

return (-1);

}

// |

Funkcja wyszukiwania z otwartym zamówieniem

|

// + ----------------------- ---------------- +

Jeśli zamówienie zostanie znalezione, funkcja zwróci bilet, w przeciwnym razie wartość to "-1" 2.Moduł otwarcia transakcji Robot handlowy musi otwierać transakcje. Aby je otworzyć, należy użyć oddzielnego modułu (podprogramu, funkcji). Często programiści ograniczają się do standardowych funkcji otwierania zleceń, co nie zawsze jest wygodne. Tak więc, przy użyciu oddzielnych procedur może początkowo leżał sytuacje błędów obsługi, wykonywania obliczeń poziomów roboczych

Stop Loss

i

Take Profit

, i tak dalej. P. Kod w tym module obejmuje nie tylko samą funkcję otwieranie zleceń, ale także obliczenie poziomu stop Loss i Take Profit, jak również funkcję, która jest używana do odszyfrowania możliwych kodów błędów (która często jest wygodna - do zobaczenia w wyjaśnieniu dziennika błędów): // + -------- ------------------------------- + // | Funkcja otwierania zleceń | <9 99> void open_positions (sygnał int, double dużo, int magia dwukrotnie cena = 0 0, ciąg symb = »BRAK».) {

// sygnał = 0 -> sygnał do otwarcia zakupu

// sygnału = 1 -> sygnał, aby otworzyć sprzedaż

int i = 0; // zmienna dla licznika pętli int count = Count_Of_Trade_Try; // liczba prób otwarcia zamówienia w przypadku, gdy nie można wykonać natychmiast int err = 0;

if (symb == "NONE") symbol = Symbol ();

if (signal == 0)

price = MarketInfo (symbol, MODE_ASK); // otwarta cena za zakupy

jeśli (sygnał == 1)

cena = MarketInfo (symbol, MODE_BID); // otwarta cena sprzedaży

podczas gdy (i <= liczba) {

// funkcja otwarcia zamówienia (wbudowany). Dla wygody, parametry są rozdzielone na różnych liniach:

int bilet = OrderSend (symbol (), // przycisk

sygnał, // typ porządek

dużo, // ilość

Cena, // cena otwarcia

Slipage, // poziom dopuszczalnego rekwotowaniu

SL (SL, sygnał, cena), // wartość stop Loss

TP (TP, sygnał, cena), // wartość Take Profit

Order_Comment, / / komentarz zamówienia

magic, // magic number

0, // data ważności (używana przy zamówieniach oczekujących)

CLR_NONE); // kolor wyświetlanej strzałki na wykresie (CLR_NONE - nie jest rysowana strzałka)

jeśli (bilet!= -1) // jeśli odkrycie zakończyło się sukcesem, zastosujemy obiekt graficzny i kończymy przerwanie

;

err = GetLastError ();

if (! Err = 0) print («Błąd:« + Market_Err_To_Str (ERR));

i ++;

Sleep (Pause_Of_Trade_Try * 100); // jeśli błąd wstrzymuje przed próbą

} // end while (i <= count)

} // koniec void open_positions (int sygnału, double, int dużo magii, podwójną cenę = 0. 0, ciąg symb = »BRAK»)

// |

kolejność funkcji otwarcia

|

// + --------------------- ------------------ +

// + ------------------------- -------------- +

// |

funkcja obliczania wartości Stop Loss dla | double sl (int sl_value, int typ, string = symb »BRAK», int rmode = 1) {

// type = 0 -> zakupy rynkowe

// type = 1 -> sprzedaż na rynku

if (symb == »BRAK») symb = Symbol (); if (sl_value <= 0) return (0); if (rmode == 1) {

if (typ == 0) zwrotny (MarketInfo (symb, MODE_ASK) -sl_value * MarketInfo (symb, MODE_POINT)); // zakupy

if (typ == 1) zwrotny (MarketInfo (symb, MODE_BID) + sl_value * MarketInfo (symb, MODE_POINT)); // sprzedaży

}

if (rmode == 2) {

if (typ == 0) zwrotny (MarketInfo (symb, MODE_BID) -sl_value * MarketInfo (symb, MODE_POINT)); // zakupy

if (typ == 1) zwrotny (MarketInfo (symb, MODE_ASK) + sl_value * MarketInfo (symb, MODE_POINT)); // sprzedaży

}

} // koniec podwójne sl (int sl_value, int typ dwukrotnie cena = 0 0, ciąg symb = »BRAK», int rmode = 1)

// | < Funkcja Stop Loss dla zamówień

|

// + ------------------------------- -------- +

// + ----------------------------------- ---- +

// |

funkcja obliczania wartości zleceń Take Profit dla

| double tp (int tp_value, int typ, string symb = »BRAK») { // zakupy> rynek

// type = 1 - - type = 0> sprzedaż na rynku

if (symb == »BRAK») symb = Symbol ();

if (tp_value <= 0) return (0); if (typ == 0) zwrotny (MarketInfo (symb, MODE_ASK) + tp_value * MarketInfo (symb, MODE_POINT)); // zakupy if (typ == 1) return (MarketInfo (symb, MODE_BID) -tp_value * MarketInfo (symb, MODE_POINT)); // sprzedaży

} // koniec podwójne tp (int tp_value, int typ dwukrotnie cena = 0 0, ciąg symb = »BRAK».)

// |

Funkcja obliczania wartości zlecenia Take Profit dla

|

// + --------------------------------------- +

// + ----------------------------------- +

// | > funkcja kod błędu deszyfrowania

|

ciąg Market_Err_To_Str (int err) { / * funkcja dotyczy tylko kody błędów operacji handlowych * / switch (err) {

case (0): powrót ("Nie ma błędu");

case (1): return ("Brak błędu, ale wynik jest nieznany");

sprawa (2): powrót ("Błąd ogólny"); sprawa (3): return ("Nieprawidłowe parametry"); sprawa (4): return ("Serwer handlu jest zajęty");

sprawa (5): powrót ("stara wersja terminala klienta");

sprawa (6): powrót ("Brak połączenia z serwerem handlowym");

sprawa (7): powrót ("Niewystarczające prawa");

sprawa (8): powrót ("Zbyt częste zapytania");

sprawa (9): return ("Nieprawidłowa operacja naruszająca serwer");

sprawa (64): powrót ("zablokowane konto");

sprawa (65): powrót ("Niewłaściwy numer konta");

sprawa (128): powrót ("Termin zakończenia transakcji");

sprawa (129): powrót ("Niewła cena");

sprawa (130): powrót ("Niewłaściwe stopnie");

sprawa (131): powrót ("Niewłaściwa głośność");

sprawa (132): powrót ("rynek jest zamknięty");

sprawa (133): powrót ("handel jest zabroniony");

sprawa (134): powrót ("nie ma za mało pieniędzy na operację");

sprawa (135): powrót ("cena uległa zmianie");

sprawa (136): powrót ("brak cen");

sprawa (137): powrót ("Broker jest zajęty");

sprawa (138): powrót ("nowe ceny");

sprawa (139): powrót ("Zamówienie jest zablokowane i już przetworzone");

sprawa (140): powrót ("Zakup tylko" jest dozwolony);

sprawa (141): powrót ("Zbyt wiele próśb");

sprawa (145): powrót ("Modyfikacja jest zabroniona,ponieważ zamówienie jest zbyt blisko rynku ");

sprawa (146): powrót ("Podsystem handlu jest zajęty");

sprawa (147): powrót ("Użycie daty ważności jest zabronione przez pośrednika");

sprawa (148): return ("Liczba otwartych i oczekujących zamówień osiągnęła limit ustalony przez brokera");

obudowa (149) powrotny («próby otwarcia przeciwnego położenia do istniejącej, zabezpieczające jest zabronione");

sprawa (150): powrót ("Próbować zamknąć pozycję instrumentu w sprzeczności z zasadą FIFO");

domyślnie: return («»);

} // wyłącznik krańcowy (ERR)

} // koniec ciąg Err_To_Str (int err)

// |

kod błędu deszyfrowania funkcja

|

// + --- -------------------------------- + 3. Moduł zamawiania zamków

Robot powinien zamknąć transakcję w przypadku odwrócenia ogólnej tendencji. Ponieważ funkcja wyszukiwania zamówień zwraca zamówienie biletu, w ramach tego modułu rozsądne jest zamknięcie zamówienia bezpośrednio na bilecie. Kod tego modułu jest również bardzo proste i jest całkiem zrozumiałe nawet dla początkujących w MQL4:

// + ---------------------------- ----------- +

// |

kolejności funkcja zamykania przez jego numer (bilet)

| bool close_by_ticket (int c_ticket, int slipage) { / *

funkcję zamknięcia transakcji przez jego numer (bilet).

gdy zamknięcie kolejności rynku bierze się pod uwagę poziom maksymalny dopuszczalny poślizg (slipage)

* /

int i = 0, // zmienna licznika pętli

Err = 0; bilet bool = fałsz; // zmienna wskazująca (nie) powodzenie zamknięcia transakcji podwójna cena = 0; 0; // cena zamknięcia transakcji (w przypadku zleceń rynkowych)

if (OrderSelect (c_ticket, SELECT_BY_TICKET, MODE_TRADES)) {// wybrać kolejność biletu

if (OrderType () == OP_BUY) Cena = ofertę; // cena za zakupy

if (OrderType () == OP_SELL) price = Ask; // cena sprzedaży

for (i = 0; i <= count_Of_Trade_Try; i ++) {

if (OrderType () <= 1) // Jeśli zlecenie rynkowe - zamknąć go, jeśli odroczone - usunąć

ticket = OrderClose (OrderTicket (), OrderLots (), cena, poślizg, CLR_NONE); // zamknięcie zamówienia rynkowego

pozostałe

ticket = OrderDelete (OrderTicket ()); // usunąć oczekujące zamówienia

if (biletu) {// jeśli zamknięcie lub usunięcie powiodło - powrót prawdziwe i zamknięcia pętli

zwrotny (prawda);

przerwa;

} // end if (ticket)

err = GetLastError ();

jeśli (err!= 0) Drukuj ("Błąd:" + Market_Err_To_Str (err));

Sleep (Pause_Of_Trade_Try * 100); // jeśli błąd wstrzymuje przed próbą

} // koniec for (i = 0; i <= count_Of_Trade_Try; i ++)

} // end if (OrderSelect (c_ticket, SELECT_BY_TICKET, MODE_TRADES)) > powrót (fałsz); // return false (gdy zamknięcie lub usunięcie zamówienia i nie powiodło się)

} // koniec bool close_by_ticket (int c_ticket)

// |

kolejności funkcja zamykania przez jego numer (bilet) < |

// + --------------------------------------- + 4. Ostateczny kod robota

Dla uproszczenia, nie dodawać do pracy tej wersji modułu zarządzania kapitałem robota (zob. Poprzedni artykuł), pojawi się w następnym artykule. Również w tej wersji robota nie jest wliczone

Trailing Stop Loss funkcja , które również zostaną włączone do następnego kodu artykułu.

Teraz jest czas, aby zmontować powstałe moduły w jedną całość i uzupełnić brakujące łącza między nimi. To wszystko zostanie zrobione w predefiniowanej funkcji języka start ().

Sam kod jest przedstawiony poniżej, zawiera komentarze i szczególne trudności, których zrozumienie nie powinno być.

Kod źródłowy eksperta, zawierający szczegółowy opis i brakujące części funkcjonalne, można pobrać i przeanalizować.

5. Testowanie robotów

Robot będzie testowany na ramce trójkąta H4. Parametry wprowadzone domyślnie są używane. Jeśli zostaną wprowadzone zmiany, zostanie to zgłoszone oddzielnie.