Nowa świeca w EA: jak wykryć ją poprawnie i tanio
W skrócie: funkcja OnTick wykonuje się przy każdym tiku, a sygnał strategii zwykle wystarczy policzyć raz na
świecę. Poprawne wykrycie to porównanie czasu otwarcia bieżącej świecy z zapamiętanym. Zła implementacja wygląda
dobrze, a w profilerze zajmowała mi 44% czasu całego OnTick. Poniżej wzorzec i trzy pułapki.
Wzorzec
Zapamiętuję czas otwarcia ostatnio widzianej świecy. W każdym tiku pobieram czas otwarcia świecy zerowej i jeśli jest inny, to jest nowa świeca: zapisuję go i zwracam prawdę. Tylko ten jeden raz. Czas, a nie liczba tików, bo liczba tików w świecy jest losowa i po restarcie terminala znika.
Nie opieram się na liczniku wolumenu. Metody typu “wolumen równy 1” zawodzą, gdy pierwszy tik świecy nie dotrze do bota, a to się zdarza na serwerach z opóźnieniami i w Testerze na świecach M1.
Pułapka 1: pierwsze wywołanie
Po starcie bota zapamiętany czas jest pusty, więc pierwsze wywołanie zawsze mówi “nowa świeca”, choć nic nowego nie nastąpiło. Czasem to dobrze, bo bot od razu ocenia rynek po restarcie. Czasem fatalnie, bo wchodzi w pozycję na świecy, która trwa od połowy. Ustalam to świadomie: albo oznaczam pierwszy raz jako “bez sygnału”, albo wymagam, by sygnał był jeszcze aktualny.
Pułapka 2: koszt wykrycia
Do pobrania czasu jednej świecy da się użyć funkcji kopiującej dane do tablicy. Działa, ale kopiuje całą tablicę
i omija wbudowaną pamięć podręczną serii czasowych. U mnie w jednym z botów (bot 9707_M1RangeBreakout_Youtube),
który miał trzy niezależne detektory, profiler MetaEditora pokazał, że samo wykrycie nowej świecy zjada 44,5% czasu
procesora w OnTick. Po zamianie na funkcję czasu otwarcia świecy, która korzysta z tej pamięci podręcznej, obciążenie
spadło, a zachowanie zostało identyczne.
To był dopiero pierwszy krok. W kolejnym bocie (bot 0510_EmaSarTrendEA) samo pobieranie czasu świecy nadal kosztowało
od 18% do 48% czasu OnTick. Zamiast pytać o czas w każdym tiku, dodałem prosty warunek: świeca nie może zmienić się
wcześniej niż czas otwarcia obecnej plus długość interwału. Do tego momentu detektor zwraca fałsz po jednym porównaniu
liczb, bez żadnego pytania o historię. Wynik jest dokładnie ten sam, bo nowa świeca przed upływem interwału
nie może się pojawić.
Wyjątek: interwał miesięczny. Miesiące mają różną długość, więc tam sprawdzam czas normalnie.
Pułapka 3: kilka interwałów w jednym bocie
Bot, który liczy wskaźniki na M5, a pozycję pilnuje co minutę (np. przesunięcie stopa na wejście), potrzebuje dwóch niezależnych detektorów, po jednym na interwał. Jeden wspólny zmienia stan przy pierwszym pytaniu i drugi druga część bota nigdy nie dostaje swojej “nowej świecy”. Każda sprawdzana rzecz ma własny zapamiętany czas.
Jak to sprawdzam
W Testerze tryb na świecach M1 daje jedno wywołanie na minutę, więc różnice w kosztach wykrycia widać dopiero na tikach albo w profilerze. Profiler pokazuje, ile procent czasu funkcji zajmuje każde wywołanie. Nie wpisuję pomiarów do kodu bota, bo każdy taki licznik też kosztuje czas, a profiler jest w MetaEditorze za darmo.
Checklista
- Nowa świeca to zmiana czasu otwarcia świecy zerowej, nie licznik tików ani wolumen.
- Świadomie obsłużone pierwsze wywołanie po starcie.
- Osobny detektor dla każdego interwału w bocie.
- Wykrycie nie pobiera tablic, tylko jedną wartość czasu.
- Sprawdziłem w profilerze, ile kosztuje samo wykrycie.
Powiązane
- Kompilacja z linii poleceń
- Wersjonowanie EA i changelog
- Pułapka 5 razy Point
- Pojęcia z artykułu: słowniczek, skorowidz
Ostrzeżenie: handel CFD i forex wiąże się z wysokim ryzykiem utraty kapitału. Artykuł ma charakter edukacyjny i nie jest rekomendacją inwestycyjną.