Filtr wiadomości bez internetu
MetaTrader ma wbudowany kalendarz dostępny z poziomu kodu. Nie wymaga zapytań sieciowych ani listy dozwolonych adresów, a prawie nikt o nim nie wie.
5 fragmentów kodu z tej strony przeszło przez kompilator MetaEditor build 6090, 2026-08-05.
Typowe rozwiązanie problemu „nie handluj w czasie publikacji danych" wygląda tak: pobrać kalendarz z jakiejś strony przez WebRequest, przeparsować, zapisać do pliku. Wymaga to dodania adresu do listy w ustawieniach, działa tylko przy połączeniu i psuje się, gdy strona zmieni format.
Nie trzeba tego robić. Terminal ma kalendarz wbudowany i dostępny z poziomu MQL5, razem z prognozami, wartościami rzeczywistymi i oceną ważności.
Trzy funkcje, które wystarczą
| Funkcja | Do czego |
|---|---|
CalendarValueHistory | wszystkie wydarzenia z zadanego przedziału czasu |
CalendarEventById | opis wydarzenia: nazwa, ważność, kraj |
CalendarValueLast | wyłącznie to, co zmieniło się od poprzedniego sprawdzenia |
Pierwsza wystarcza do filtra czasowego, druga do rozpoznania, czy publikacja jest istotna, trzecia do reagowania na napływające wyniki.
Filtr
input int MinutPrzed = 30;
input int MinutPo = 15;
bool BlisokPublikacji(const string waluta)
{
MqlCalendarValue wartosci[];
datetime od = TimeCurrent() - MinutPo * 60;
datetime doo = TimeCurrent() + MinutPrzed * 60;
//--- pusty kod kraju, filtrujemy po walucie instrumentu
int ile = CalendarValueHistory(wartosci, od, doo, NULL, waluta);
if(ile <= 0)
return false;
for(int i = 0; i < ile; i++)
{
MqlCalendarEvent wydarzenie;
if(!CalendarEventById(wartosci[i].event_id, wydarzenie))
continue;
if(wydarzenie.importance != CALENDAR_IMPORTANCE_HIGH)
continue;
PrintFormat("Publikacja %s o %s - wstrzymuje wejscia",
wydarzenie.name,
TimeToString(wartosci[i].time, TIME_MINUTES));
return true;
}
return false;
}Waluta instrumentu bierze się z jego właściwości, więc filtr sam dopasowuje się do tego, na czym stoi ekspert:
string bazowa = SymbolInfoString(_Symbol, SYMBOL_CURRENCY_BASE);
string zysku = SymbolInfoString(_Symbol, SYMBOL_CURRENCY_PROFIT);
if(BlisokPublikacji(bazowa) || BlisokPublikacji(zysku))
return;Dla EURUSD sprawdzi to wydarzenia dla euro i dolara, dla złota — dla dolara. Bez wpisywania czegokolwiek na sztywno.
Wartości są przemnożone przez milion
To jest fakt, który zaskakuje każdego przy pierwszym użyciu i nie wynika z niczego oczywistego. Pola actual_value, forecast_value i prev_value są typu całkowitego i przechowują liczbę pomnożoną przez 1 000 000.
Do tego brak wartości nie jest zerem, tylko najmniejszą możliwą liczbą typu long. Wydarzenie, którego wynik jeszcze nie został opublikowany, ma tam LONG_MIN — i potraktowanie tego jak liczby daje wynik, który wygląda jak gigantyczny spadek.
double WartoscRzeczywista(const MqlCalendarValue &wartosc, bool &jest)
{
jest = (wartosc.actual_value != LONG_MIN);
if(!jest)
return 0.0;
return wartosc.actual_value / 1000000.0;
}Ważność ma cztery poziomy
CALENDAR_IMPORTANCE_NONE, _LOW, _MODERATE i _HIGH. Filtrowanie wyłącznie po najwyższym poziomie przepuszcza sporo publikacji, które realnie ruszają rynkiem — indeksy nastrojów, wystąpienia przedstawicieli banków centralnych. Z drugiej strony wpuszczenie poziomu niskiego zablokuje handel na pół dnia, bo drobnych odczytów jest kilkadziesiąt dziennie.
Rozsądny punkt wyjścia to poziom wysoki i umiarkowany, z parametrem pozwalającym użytkownikowi to zmienić.
Reagowanie na napływające wyniki
CalendarValueLast działa inaczej niż pozostałe: przyjmuje identyfikator zmiany i zwraca wyłącznie to, co pojawiło się po nim. Dzięki temu nie trzeba przy każdym wywołaniu przeglądać całego dnia.
ulong ostatniaZmiana = 0;
void OnTimer()
{
MqlCalendarValue nowe[];
int ile = CalendarValueLast(ostatniaZmiana, nowe, NULL, "USD");
if(ile <= 0)
return;
for(int i = 0; i < ile; i++)
if(nowe[i].actual_value != LONG_MIN)
PrintFormat("Nowy odczyt: wydarzenie %I64u, wartosc %.2f",
nowe[i].event_id, nowe[i].actual_value / 1000000.0);
}Zmienna ostatniaZmiana jest aktualizowana przez samą funkcję. Przy pierwszym wywołaniu z zerem dostaniesz komplet bieżących danych, przy kolejnych — tylko różnicę.
Czego kalendarz nie zrobi
Nie powie, jak rynek zareaguje. Nie zastąpi też filtra zmienności — publikacja o niskiej ważności potrafi ruszyć instrumentem mocniej niż wysoka, jeśli odczyt bardzo odbiegnie od prognozy. Do tego drugiego przydaje się porównanie actual_value z forecast_value, ale to już jest decyzja strategiczna, a nie techniczna.