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

MQL5 / Pułapki

Skąd się bierze przewaga z przyszłości

Najczęstsza przyczyna backtestów, których nie da się powtórzyć na rachunku: odczyt sygnału ze świecy, która jeszcze się nie zamknęła.

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

Look-ahead bias to sytuacja, w której kod przy podejmowaniu decyzji korzysta z informacji, której w tym momencie jeszcze nie było. W MQL5 nie trzeba do tego żadnej egzotyki — wystarczy odczytać wartość ze świecy o indeksie 0.

Dlaczego świeca 0 kłamie

Świeca o indeksie 0 jest w budowie. Jej maksimum, minimum i zamknięcie zmieniają się do końca okresu. Wskaźnik policzony na tej świecy zmienia się razem z nią.

Sygnał, który pojawił się w połowie świecy, może zniknąć przed jej zamknięciem. Na wykresie historycznym po fakcie widać już tylko wersję ostateczną — tę, której w chwili decyzji nie znałeś.

Warunek zależny od świecy w budowie
double bufor[];
ArraySetAsSeries(bufor, true);
CopyBuffer(uchwyt, 0, 0, 2, bufor);

if(bufor[0] > iClose(_Symbol, _Period, 0))   // obie wartości jeszcze się zmienią
   Kup();
Warunek na danych ostatecznych
if(bufor[1] > iClose(_Symbol, _Period, 1))   // świeca domknięta, wartości niezmienne
   Kup();

Jak to wygląda w wynikach

Kod czytający świecę 0 daje różne wyniki w zależności od modelu ticków użytego w testerze — bo to model decyduje, jak wygląda ścieżka ceny wewnątrz świecy. Ten sam ekspert, ten sam okres, trzy przebiegi, trzy różne krzywe kapitału. Kod czytający wyłącznie świece domknięte jest na model odporny: przy każdym modelu daje ten sam zestaw transakcji.

To jest zresztą najprostszy test na obecność problemu. Nie potrzebujesz analizy kodu — wystarczy uruchomić ten sam test dwa razy przy różnych modelach.

Inne odmiany tego samego problemu

Odwołanie do maksimum całego okresu. iHigh(_Symbol, PERIOD_D1, 0) wewnątrz dnia zwraca maksimum osiągnięte dotychczas, a nie maksimum dnia. Ludzie piszą warunki, jakby to była druga wartość.

Wskaźniki przerysowujące. Część wskaźników — zwłaszcza oparte o ekstremum w oknie wokół bieżącej świecy, jak ZigZag — zmienia już narysowane wartości, gdy pojawią się nowe dane. W teście historycznym widać wersję ostateczną. Na rachunku nigdy jej nie zobaczysz w chwili decyzji.

Normalizacja na całym zbiorze. Skalowanie danych przez wartość policzoną z całego okresu testu wprowadza do każdej pojedynczej decyzji informację z jej przyszłości. Problem znany z uczenia maszynowego, w kodzie strategii występuje równie często.

Co z tego wynika dla sposobu pisania kodu

Przyjmij prostą regułę: indeks 0 służy wyłącznie do odczytu ceny bieżącej przy składaniu zlecenia. Każdy warunek wejścia i wyjścia opieraj na indeksie 1 albo wyższym. Kosztuje to jedną świecę opóźnienia i usuwa całą klasę wyników, których nie da się powtórzyć.

Powiązane