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

MQL5 / Pułapki

EMPTY_VALUE i zepsuta skala wykresu

Wskaźnik z zerem zamiast wartości pustej spłaszcza skalę i rysuje pionowe kreski. Czym różni się zero od braku danych.

1 fragment kodu z tej strony przeszedł przez kompilator MetaEditor build 6090, 2026-08-05.

Tworzenie własnych wskaźników w MQL5 wydaje się na pierwszy rzut oka proste: deklarujesz bufory, ustawiasz właściwości i wypełniasz tablice wartościami w OnCalculate. Jednak błędne zarządzanie wartościami pustymi to jeden z najczęstszych powodów, dla których wskaźniki wizualnie "psują się", nachodzą na cenę lub powodują dziwne błędy w EA, które z nich korzystają.

Nie jest to NULL, nie jest to Zero. To EMPTY_VALUE.

W językach takich jak Python (z biblioteką Pandas) brak danych oznacza się jako NaN (Not a Number). W MQL5 rolę tę pełni stała EMPTY_VALUE, która jest zdefiniowana jako maksymalna wartość typu double (DBL_MAX - około 1.7976931348623157e+308).

Najczęstszym błędem początkujących jest inicjalizacja buforów zerami (0.0) w momentach, gdy obliczenia nie mają jeszcze zastosowania. Na przykład, jeśli masz wskaźnik wyliczający średnią ze 100 świec, przez pierwsze 99 świec wskaźnik nie ma wartości. Jeśli wstawisz tam 0.0, wykres automatycznie przeskaluje się od zera do aktualnej ceny (np. 1.1000 dla EURUSD), sprawiając, że świecenie staje się płaską linią u dołu ekranu.

EMPTY_VALUE i zepsuta skala wykresuWskaźnik z zerem zamiast wartości pustej spłaszcza skalę i rysuje pionowe kreski. Czym różni się zero od braku danych. Wpływ błędnej inicjalizacji na skalowanie wykresu BŁĄD: Użycie 0.0 jako pustej wartości 0.0 1.1000 (Cena) Cena spłaszczona POPRAWNIE: Użycie EMPTY_VALUE 1.1000 1.0900 1.0800 Prawidłowe proporcje

PlotIndexSetDouble i zarządzanie właściwościami

MQL5 pozwala na bardzo precyzyjne sterowanie zachowaniem buforów. Możesz określić, jaka wartość ma być traktowana jako "pusta" podczas rysowania linii. Domyślnie jest to EMPTY_VALUE, ale można to zmienić. Czasami chcemy narysować linię przerywaną – wtedy jako pustą wartość ustawiamy np. 0.0 przez właściwość PLOT_EMPTY_VALUE funkcji PlotIndexSetDouble.

double MyBuffer[];

int OnInit() {
    SetIndexBuffer(0, MyBuffer, INDICATOR_DATA);
    
    // Ustawiamy, że wartość 0.0 nie będzie rysowana na wykresie (przerwa w linii)
    // Przydatne np. dla wskaźników, które rysują się tylko w określonych godzinach
    PlotIndexSetDouble(0, PLOT_EMPTY_VALUE, 0.0);
    
    return(INIT_SUCCEEDED);
}

int OnCalculate(const int rates_total, const int prev_calculated, const datetime &time[], const double &open[], const double &high[], const double &low[], const double &close[], const long &tick_volume[], const long &volume[], const int &spread[]) {
    
    // Jeśli to pierwsze uruchomienie lub zmiana historii
    if(prev_calculated == 0) {
        // Zawsze czyść bufor na początku! Nie używaj ArrayInitialize(MyBuffer, 0)
        ArrayInitialize(MyBuffer, 0.0); // Używamy 0.0, bo ustaliliśmy je jako PLOT_EMPTY_VALUE
    }
    
    int start = MathMax(prev_calculated - 1, 0);
    
    for(int i = start; i < rates_total; i++) {
        if(i < 10) {
            MyBuffer[i] = 0.0; // Brak danych, nie rysuj
        } else {
            // Obliczenia wskaźnika
            double sum = 0;
            for(int j = 0; j < 10; j++) {
                sum += close[i - j];
            }
            MyBuffer[i] = sum / 10.0;
        }
    }
    
    return(rates_total);
}