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.
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.
#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.
#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));
}