Przejdź do treści
MQL5 · MetaTrader 5 · po polsku
kod odczarowany

MQL5 / Inżynieria

Komunikacja między ekspertem a wskaźnikiem

Zmienne globalne terminala, bufory wskaźnika i zdarzenia niestandardowe. Trzy sposoby przekazania danych i ich koszty.

2 fragmenty kodu z tej strony przeszły przez kompilator MetaEditor build 6090, 2026-08-05.

Jednym z najczęściej powielanych błędów architektonicznych w MQL5 jest próba zmuszenia wskaźnika do bezpośredniego zarządzania pozycjami lub otwierania zleceń. Z definicji wskaźnik powinien być "głuchy" na handel i służyć wyłącznie do analizy danych. Problem pojawia się, gdy wskaźnik wykryje sygnał (np. przecięcie MACD) i musi poinformować o tym Eksperta (EA). Wielu programistów używa do tego globalnych zmiennych terminala (GlobalVariableSet), co wiąże się z opóźnieniami dyskowymi i problemami ze synchronizacją. Rozwiązaniem jest wzorzec "Publisher-Subscriber" z wykorzystaniem EventChartCustom.

Architektura zdarzeń niestandardowych

MQL5 posiada wbudowany, niezwykle szybki system kolejki zdarzeń. Wskaźnik może wygenerować zdarzenie użytkownika (z dowolnym kodem liczbowym i wartościami double/string), które zostanie natychmiast wrzucone do kolejki zdarzeń wykresu. Jeśli na tym samym wykresie znajduje się EA, może ono nasłuchiwać tego zdarzenia w funkcji OnChartEvent.

Komunikacja między ekspertem a wskaźnikiemZmienne globalne terminala, bufory wskaźnika i zdarzenia niestandardowe. Trzy sposoby przekazania danych i ich koszty. Przepływ zdarzeń: Wskaźnik -> Kolejka -> EA Wskaźnik (OnCalculate) Ekspert (EA) (OnChartEvent) Kolejka Zdarzeń Wykresu EventChartCustom() Dostarczenie zdarzenia Brak zapisu na dysk. Brak pollingu. Komunikacja w pamięci RAM.

Implementacja Wzorca

Kluczowe jest zdefiniowanie unikalnego identyfikatora zdarzenia (np. 1001), aby nie pomylić go ze zdarzeniami systemowymi (jak kliknięcie myszką, które ma ID 8). Dodatkowo, jako parametry możemy przekazać cenę sygnału oraz symbol.

Wskaźnik: wysyła zdarzenie
#define EVENT_BUY_SIGNAL 1001

int OnCalculate(const int rates_total,
                const int prev_calculated,
                const int begin,
                const double &price[])
  {
   if(rates_total < 2)
      return 0;

   if(SprawdzPrzeciecie())
      EventChartCustom(0, EVENT_BUY_SIGNAL, (long)TimeCurrent(),
                       price[rates_total - 1], _Symbol);

   return rates_total;
  }

Ekspert stojący na tym samym wykresie odbiera zdarzenie w OnChartEvent. Numer zdarzenia własnego liczy się od CHARTEVENT_CUSTOM, więc obie strony muszą używać tej samej stałej.

Ekspert: odbiera zdarzenie
#define EVENT_BUY_SIGNAL 1001

void OnChartEvent(const int id, const long &lparam,
                  const double &dparam, const string &sparam)
  {
   if(id != CHARTEVENT_CUSTOM + EVENT_BUY_SIGNAL)
      return;

   PrintFormat("sygnal ze wskaznika: %s, cena %.5f, czas %s",
               sparam, dparam, TimeToString((datetime)lparam));
  }