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ś.
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();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ć.