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.
, 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.
// |
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 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 , 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). * / 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.
Zamknięcie transakcji, „rynek”
Take Profit
gdy zamknięcie kolejności rynku bierze się pod uwagę poziom maksymalny dopuszczalny poślizg (slipage)