Wróć do katalogu
Season 39 7 Odcinki 30 min 2026

Zipline Backtesting Engine

Wersja 3.1 — Edycja 2026. Kompleksowy przewodnik na rok 2026 po opanowaniu silnika Zipline 3.1 do backtestingu i live tradingu w tradingu algorytmicznym.

Handel algorytmiczny Nauka o danych Analiza danych
Zipline Backtesting Engine
Teraz odtwarzane
Click play to start
0:00
0:00
1
Silnik do backtestingu sterowany zdarzeniami
W tym odcinku przedstawiamy Zipline, pythonowy silnik do backtestingu sterowany zdarzeniami. Słuchacze poznają podstawową architekturę, która zapobiega zjawisku look-ahead bias, oraz zrozumieją złożone zależności rozszerzeń C wymagane do stabilnej instalacji lokalnej.
4m 26s
2
Cykl życia algorytmu i zarządzanie stanem
Ten odcinek omawia główny cykl życia algorytmu w Zipline. Słuchacze dowiedzą się, jak zarządzać stanem podczas tysięcy zdarzeń handlowych za pomocą obiektu context oraz jak składać proste zlecenia.
4m 29s
3
Pakiety danych rynkowych i niestandardowe wczytywanie danych
Ten odcinek analizuje pakiety danych rynkowych (Market Data Bundles) i proces wczytywania danych. Słuchacze dowiedzą się, jak ominąć ładowanie ogromnych plików CSV poprzez wstępną kompilację danych cenowych i budowanie niestandardowych potoków wczytywania danych.
3m 56s
4
Algorithm API i interakcje z BarData
Ten odcinek zagłębia się w Algorithm API, skupiając się na obiekcie BarData i funkcjach harmonogramowania (scheduling functions). Słuchacze dowiedzą się, jak bezpiecznie odpytywać historię z określonego punktu w czasie (point-in-time) i automatyzować rebalansowanie portfela.
4m 34s
5
Niestandardowe kalendarze handlowe i rynki globalne
Ten odcinek wyjaśnia, jak skonfigurować niestandardowe kalendarze handlowe (Trading Calendars). Słuchacze nauczą się definiować godziny pracy giełd, zarządzać dniami wolnymi i tworzyć kalendarz 24/7 dla aktywów takich jak kryptowaluty.
4m 00s
6
Metryki ryzyka i wydajności oraz niestandardowa ewaluacja
Ten odcinek skupia się na śledzeniu i ocenie wydajności strategii. Słuchacze dowiedzą się, jak interpretować DataFrame z wynikami i podpinać się pod cykl życia symulacji, aby obliczać niestandardowe metryki ryzyka.
3m 44s
7
Rozszerzanie architektury Zipline
Ten finałowy odcinek omawia rozszerzalną architekturę Zipline. Słuchacze dowiedzą się, jak podmieniać główne komponenty i rejestrować niestandardowy blotter w celu integracji z live tradingiem.
4m 57s

Odcinki

1

Silnik do backtestingu sterowany zdarzeniami

4m 26s

W tym odcinku przedstawiamy Zipline, pythonowy silnik do backtestingu sterowany zdarzeniami. Słuchacze poznają podstawową architekturę, która zapobiega zjawisku look-ahead bias, oraz zrozumieją złożone zależności rozszerzeń C wymagane do stabilnej instalacji lokalnej.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Zipline Backtesting Engine, odcinek 1 z 7. Większość algorytmów tradingowych wygląda świetnie na papierze, ale na prawdziwych rynkach natychmiast traci pieniądze. Głównym winowajcą jest zazwyczaj look-ahead bias. Twój kod przypadkowo podgląda jutrzejszą cenę zamknięcia, żeby wykonać dzisiejszy trade. Event-Driven Backtesting Engine w Zipline 3.0 całkowicie temu zapobiega. W standardowym, wektoryzowanym backtesterze ładujesz ogromny dataframe z historycznymi cenami i aplikujesz operacje pandas na całej osi czasu jednocześnie. Jest to szybkie, ale ma poważne wady, jeśli chodzi o symulowanie rzeczywistości. Możesz łatwo napisać logikę, która triggeruje zlecenie kupna dzisiaj na podstawie średniej kroczącej, która przypadkowo zawiera dane z przyszłego tygodnia. Zipline odbiera ci tę możliwość, zmuszając cię do korzystania ze ścisłego strumienia event-driven. Symuluje prawdziwą giełdę finansową. Kiedy odpalasz backtest, silnik działa jak rygorystyczny strażnik czasu. Przechodzi przez historię krok po kroku, tick po ticku, albo minuta po minucie. Na każdym kroku odpala event. Twój kod otrzymuje tylko te dane, które są dostępne w tej konkretnej mikrosekundzie. Sprawdzasz obecny state, składasz zlecenia, a potem czekasz, aż silnik przesunie zegar. Nie możesz wybiec w przyszłość, ponieważ przyszłe dane nie zostały jeszcze zestreamowane do silnika. Taka architektura gwarantuje, że twój backtest odzwierciedla rzeczywiste ograniczenia live tradingu. Jednak przetwarzanie finansowej osi czasu event po evencie w czystym Pythonie tworzy ogromny bottleneck. Możesz przetwarzać lata danych cenowych o rozdzielczości minutowej dla tysięcy pojedynczych akcji. Żeby ten event loop był obliczeniowo opłacalny, Zipline w dużej mierze przerzuca pracę na C-extensions. Główny silnik opiera się na prekompilowanych rutynach, żeby przetwarzać liczby na tyle szybko, by miało to sens. To poleganie na C-extensions wprowadza poważny punkt tarcia. Postawienie solidnego środowiska quantowego od zera jest powszechnie znane jako niezwykle trudne. Zipline nie jest samodzielnym narzędziem w Pythonie. Wymaga głębokiej integracji z bibliotekami naukowymi na poziomie systemu. Na przykład korzysta z TA-Lib, standardowej biblioteki do generowania technicznych wskaźników rynkowych. Opiera się również na paczkach, które wymagają LAPACK i BLAS do ciężkich obliczeń algebry liniowej. To złożone, legacy codebasy w C i Fortranie. Jeśli spróbujesz zbudować to środowisko za pomocą prostej komendy pip install, prawie na pewno zderzysz się ze ścianą błędów kompilacji. Pip pobiera kod źródłowy dla tych zależności i próbuje je skompilować lokalnie. To wymaga, żeby twój system operacyjny miał już poprawnie skonfigurowany kompilator C, kompilator Fortrana i odpowiednie systemowe pliki nagłówkowe. Większość podstawowych systemów operacyjnych nie ma tego out of the box. Dlatego dokumentacja Zipline wyraźnie zaleca używanie condy zamiast pipa. Conda to nie tylko package manager dla Pythona. To menedżer środowisk i binarek na poziomie systemu. Kiedy tworzysz środowisko conda i instalujesz Zipline przez kanał conda-forge, nie kompilujesz niczego ze źródeł. Conda pobiera prekompilowane binarki dla twojego konkretnego systemu operacyjnego. Bezproblemowo ogarnia C-extensions, TA-Lib i LAPACK. Drzewo zależności jest rozwiązywane za ciebie, dając ci stabilne środowisko gotowe do developmentu algorytmów. Oto kluczowy wniosek. Ten rygorystyczny event loop, który sprawia, że Zipline jest matematycznie uczciwy, to dokładnie to, co zmusza go do polegania na ciężkich, skompilowanych zależnościach w C, żeby działać w dużej skali. Rozumiejąc tę architekturę, rozumiesz, dlaczego instalacja jest skomplikowana i dlaczego conda to jedyny sensowny sposób na zbudowanie twojego środowiska. Jeśli chcesz pomóc nam tworzyć ten podcast, możesz nas wesprzeć, wyszukując DevStoriesEU na Patreonie. To wszystko w tym odcinku. Dzięki za słuchanie i buduj dalej!
2

Cykl życia algorytmu i zarządzanie stanem

4m 29s

Ten odcinek omawia główny cykl życia algorytmu w Zipline. Słuchacze dowiedzą się, jak zarządzać stanem podczas tysięcy zdarzeń handlowych za pomocą obiektu context oraz jak składać proste zlecenia.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Silnik do backtestów Zipline, odcinek 2 z 7. Ustawiasz prosty licznik w swojej logice tradingowej używając globalnej zmiennej w Pythonie, a w połowie backtestu nagle się on resetuje albo rzuca błędem. W backtestingu opartym na zdarzeniach, standardowe zmienne globalne to pułapka. Aby przetrwać tysiące symulowanych zdarzeń rynkowych, potrzebujesz bezpiecznego sposobu na śledzenie stanu. I tu właśnie wkracza do gry cykl życia algorytmu Zipline i zarządzanie stanem. Każdy algorytm w Zipline wymaga co najmniej dwóch podstawowych funkcji: initialize oraz handle data. Zipline to system sterowany zdarzeniami. Przechodzi przez dane historyczne chronologicznie, wyzwalając zdarzenie dla każdego przedziału czasu. Funkcja initialize uruchamia się dokładnie raz, na samym początku backtestu. Przyjmuje jeden argument o nazwie context. Pomyśl o obiekcie context jak o trwałej pamięci twojego algorytmu. Pod spodem to zwykły słownik w Pythonie, ale działa jak dedykowany namespace. Zamiast deklarować standardowe zmienne globalne, przypisujesz swój stan bezpośrednio do obiektu context. Jeśli chcesz śledzić konkretny walor, na przykład akcje Apple, wyszukujesz go w funkcji initialize i przypisujesz do context kropka asset. Dzięki temu masz pewność, że referencja przetrwa od pierwszego do ostatniego dnia backtestu. Kolejna jest funkcja handle data. Jest ona wywoływana za każdym razem, gdy pojawia się nowe zdarzenie rynkowe, na przykład nowa dzienna świeca. Przyjmuje dwa argumenty: context oraz data. Obiekt context już znasz. To z niego odczytujesz stan, który wcześniej ustawiłeś, albo aktualizujesz bieżące zmienne. Drugi argument, data, reprezentuje obecne środowisko rynkowe. To twoja soczewka na symulację w tym konkretnym momencie. Używasz obiektu data, aby sprawdzić, czy dany walor jest w tej chwili zbywalny, pobrać jego aktualną cenę, albo zażądać historycznego okna cenowego. Weźmy na warsztat standardową strategię przecięcia dwóch średnich kroczących. W funkcji initialize definiujesz swój docelowy walor i przypisujesz go do obiektu context. Wewnątrz handle data, prosisz obiekt data o ceny z ostatnich trzydziestu dni, aby obliczyć krótką średnią kroczącą, oraz z ostatnich trzystu dni dla długiej średniej kroczącej. Porównujesz obie średnie. Jeśli krótka średnia przebije od dołu długą średnią, to jest to sygnał kupna. Wykonujesz to wywołując funkcję order, przekazując context kropka asset oraz docelową liczbę akcji. Trading to tylko połowa roboty. Musisz też śledzić, jak twoje wskaźniki zachowują się w czasie. Zipline udostępnia wbudowaną funkcję o nazwie record. Na końcu bloku handle data wywołujesz funkcję record i przekazujesz jej krótką średnią kroczącą, długą średnią kroczącą oraz aktualną cenę. Zipline zbiera te zapisane wartości w każdym kroku i dołącza je do końcowego dataframe'u z wynikami, zwracanego na koniec backtestu. Kiedy twój kod jest gotowy, masz dwa sposoby na jego uruchomienie. Pierwszy to użycie wiersza poleceń. Przekazujesz swój skrypt w Pythonie do polecenia zipline run, określając daty początkową i końcową, kapitał początkowy oraz plik wyjściowy na wyniki. To idealne rozwiązanie dla zautomatyzowanych pipeline'ów lub zdalnego uruchamiania. Druga metoda jest interaktywna. Jeśli korzystasz z Jupyter Notebooks, możesz użyć wbudowanego magic command dla Zipline. Wpisując procent procent zipline na samej górze komórki w notatniku, definiujesz i wykonujesz algorytm inline, przekazując daty i kapitał jako argumenty do magic command. Wyniki są wstrzykiwane bezpośrednio do lokalnego dataframe'u, gotowe do natychmiastowej analizy. Oto kluczowy wniosek. Zipline zmusza cię do podzielenia algorytmu na dwa odrębne obiekty: context dla stanu wewnętrznego, który kontrolujesz, oraz data dla zewnętrznego środowiska rynkowego. Szanuj tę granicę, a twoje zarządzanie stanem pozostanie idealnie zsynchronizowane przez tysiące transakcji. To tyle na dzisiaj. Do usłyszenia następnym razem!
3

Pakiety danych rynkowych i niestandardowe wczytywanie danych

3m 56s

Ten odcinek analizuje pakiety danych rynkowych (Market Data Bundles) i proces wczytywania danych. Słuchacze dowiedzą się, jak ominąć ładowanie ogromnych plików CSV poprzez wstępną kompilację danych cenowych i budowanie niestandardowych potoków wczytywania danych.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Zipline Backtesting Engine, odcinek 3 z 7. Twoja logika tradingowa może być całkowicie bezbłędna, ale jeśli będziesz ładować do pamięci ogromne pliki CSV za każdym razem, gdy odpalasz symulację, twoja prędkość iteracji drastycznie spadnie. Wąskim gardłem rzadko jest twój algorytm. Jest nim twój data pipeline. Zipline rozwiązuje ten problem, korzystając z Market Data Bundles i Custom Ingestion. Data bundle to zbiór cen aktywów i metadanych, który został wstępnie skompilowany do wysoce zoptymalizowanego formatu storage'u. Zamiast parsować surowe pliki tekstowe podczas działania, Zipline odczytuje dane ze skompresowanego binarnego storage'u i szybkiej lokalnej bazy danych. To oddzielenie przetwarzania danych od egzekucji strategii sprawia, że backtesty są wyjątkowo szybkie. Odpalasz tę kompilację z linii komend za pomocą polecenia zipline ingest, po którym podajesz nazwę bundle'a. Zipline jest dostarczany z domyślnym bundle'em o nazwie Quandl, który pobiera standardowe, historyczne, dzienne dane giełdowe z internetu i zapisuje je bezpośrednio na twoim lokalnym dysku. Większość profesjonalnych środowisk opiera się na komercyjnych danych. Aby użyć własnych danych, musisz zbudować customowy bundle. Stworzenie customowego bundle'a wymaga napisania funkcji ingest. Ta funkcja działa jak dedykowany translator między twoim źródłem surowych danych a wewnętrznym formatem storage'u Zipline. I tu jest kluczowa sprawa. Funkcja ingest nie zwraca customowego datasetu. Zamiast tego, Zipline przekazuje do twojej funkcji wiele obiektów typu writer, a twój kod ładuje surowe dane do tych writerów. Sygnatura funkcji ingest wymaga konkretnych parametrów do obsługi tego routingu. Przyjmuje konfigurację środowiska, kalendarz tradingowy, sesję początkową i końcową oraz obiekty writer. Dwa kluczowe obiekty, z którymi będziesz wchodzić w interakcję, to asset database writer i daily bar writer. Asset database writer obsługuje twoje metadane. Przekazujesz mu ustrukturyzowaną tabelę zawierającą twoje symbole, ich daty początkowe i końcowe oraz nazwy giełd. Writer kompiluje to do lokalnej bazy danych, dzięki czemu silnik dokładnie wie, które aktywa istnieją podczas dowolnej sesji tradingowej. Daily bar writer przetwarza właściwe price action. Dostarczasz mu iterator, który zwraca bloki danych cenowych. Każdy blok zawiera wewnętrzny identyfikator aktywa sparowany z tabelą jego danych open, high, low, close i volume. Writer bierze te bloki i kompresuje je na dysku. Zipline zapewnia wbudowany mechanizm do obsługi standardowych płaskich plików za pomocą bundle'a katalogu CSV, powszechnie nazywanego csvdir. Konfigurujesz swoje własne dane, zapisując pojedyncze pliki CSV w jednym folderze, nazywając każdy plik jego tickerem. Następnie rejestrujesz ten katalog w specjalnym skrypcie konfiguracyjnym Zipline, zwanym plikiem extension. Rejestracja po prostu łączy twoją customową nazwę bundle'a z podległą funkcją ingest, aby narzędzie linii komend wiedziało o jej istnieniu. Kiedy odpalasz zipline ingest z twoją nową customową nazwą, system kieruje funkcję ingest na twój folder. Przechodzi w pętli przez pliki CSV, wyciąga metadane, karmi nimi asset database writer i pompuje historyczne wiersze cenowe do daily bar writera. Powolne, kosztowne parsowanie tekstu odbywa się dokładnie raz. Po procesie ingest, twoje własne dane są trwale przechowywane w zoptymalizowanym formacie, natychmiast dostępne dla tysięcy szybkich iteracji backtestów. Prawdziwą siłą custom ingestion jest to, że ściśle oddziela przygotowanie danych od egzekucji strategii, gwarantując, że powolna logika parsowania nigdy nie zanieczyści twojego środowiska testowego. To wszystko na dzisiaj. Do usłyszenia następnym razem!
4

Algorithm API i interakcje z BarData

4m 34s

Ten odcinek zagłębia się w Algorithm API, skupiając się na obiekcie BarData i funkcjach harmonogramowania (scheduling functions). Słuchacze dowiedzą się, jak bezpiecznie odpytywać historię z określonego punktu w czasie (point-in-time) i automatyzować rebalansowanie portfela.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Zipline Backtesting Engine, odcinek 4 z 7. Splity aktywów i dywidendy mogą błyskawicznie zdezaktualizować twoją historię cen. Jeśli akcja przejdzie split dwa do jednego, naiwna pętla backtestingu pomyśli, że cena właśnie spadła o pięćdziesiąt procent. Unikniesz tego, korzystając z Algorithm API i interakcji z BarData, które automatycznie obsługują korekty point-in-time. W Zipline rdzeń logiki twojego algorytmu wchodzi w interakcję z obiektem, zazwyczaj nazywanym data, który jest instancją BarData. Jest on przekazywany do twoich event handlerów, takich jak twój główny data handler czy scheduled functions. Jego głównym zadaniem jest serwowanie danych o cenach i wolumenie dokładnie w takiej postaci, w jakiej były dostępne w danym momencie symulacji, co całkowicie zapobiega zjawisku look-ahead bias. Kiedy wywołujesz data dot current, przekazujesz mu asset i pole, takie jak price lub volume. Zwraca ci najnowszą wartość dostępną w tej konkretnej minucie lub dniu symulacji. Kiedy potrzebujesz lookback window do obliczenia średniej kroczącej lub historycznej zmienności, wywołujesz data dot history. Podajesz mu asset, pole, liczbę barów i częstotliwość, na przykład jeden dzień lub jedną minutę. Oto kluczowa sprawa. Zarówno current, jak i history automatycznie korygują zwracane dane o akcje korporacyjne, ale tylko do obecnego czasu symulacji. Twoje średnie kroczące nie odchylą się drastycznie w dniu ex-dividend, ponieważ historyczne ceny są korygowane tak, aby idealnie pasowały do obecnej ramki cenowej. Otrzymujesz matematycznie ciągły szereg czasowy bez konieczności samodzielnego zarządzania mnożnikami akcji korporacyjnych. Zanim podejmiesz działania na podstawie tych danych cenowych, musisz zweryfikować, czy dany asset jest w ogóle zbywalny w tym konkretnym momencie. Przekazanie twojego assetu do data dot can trade sprawdza, czy giełda jest otwarta dla tego assetu i czy jest on aktywnie notowany. Jeśli akcja została wczoraj wycofana z giełdy, albo nie miała jeszcze swojego IPO, funkcja zwraca false. Kolejna rzecz to data dot is stale. Jeśli asset jest bardzo niepłynny i nie był przedmiotem obrotu podczas obecnego baru, Zipline zastosuje forward-fill na ostatniej znanej cenie, aby zapobiec błędom brakujących danych. Jednak jeśli uruchomisz strategię mean-reversion na cenach po forward-fill, będziesz handlować na ghost data. Data dot is stale zwraca true, jeśli cena, którą widzisz, jest przeniesiona z poprzedniego okresu, a nie pochodzi ze świeżej transakcji. Sprawdzenie zarówno tradability, jak i staleness przed złożeniem zlecenia zapobiega ogromnej klasie błędów symulacji. To tyle, jeśli chodzi o wejścia, przejdźmy do execution timing. Domyślnie Zipline wywołuje twój główny data handler przy każdym pojedynczym barze symulacji. Jeśli uruchamiasz strategię na poziomie minutowym, wykonywanie złożonej logiki rebalansowania co sześćdziesiąt sekund spowolni twój backtest do żółwiego tempa i wygeneruje nierealistyczne koszty transakcyjne. Rozwiązaniem jest metoda schedule function. Używasz jej w fazie inicjalizacji algorytmu, aby zarejestrować konkretną customową funkcję, która ma się uruchamiać według precyzyjnego harmonogramu. Przyjmuje ona trzy główne argumenty. Po pierwsze, funkcję, którą chcesz uruchomić. Po drugie, date rule. Po trzecie, time rule. Załóżmy, że chcesz przeprowadzić rebalansowanie portfela dokładnie trzydzieści minut przed zamknięciem rynku. Przekazujesz swoją funkcję rebalansowania jako pierwszy argument. Dla date rule używasz metody pomocniczej date rules dot every day. Dla time rule używasz time rules dot market close, przekazując trzydzieści minut jako argument offset. Teraz, zamiast odpalać się setki razy dziennie, twoja logika rebalansowania uruchamia się dokładnie raz, tuż przed końcem sesji handlowej. Rozdzielenie obiektu BarData do bezpiecznego dostępu do danych i scheduling API do execution timing gwarantuje, że rdzeń logiki twojego algorytmu uruchamia się tylko wtedy, kiedy powinien, używając cen, które faktycznie istniały w tym konkretnym momencie. Chciałbym poświęcić chwilę, żeby podziękować ci za słuchanie — to bardzo nam pomaga. Miłego dnia!
5

Niestandardowe kalendarze handlowe i rynki globalne

4m 00s

Ten odcinek wyjaśnia, jak skonfigurować niestandardowe kalendarze handlowe (Trading Calendars). Słuchacze nauczą się definiować godziny pracy giełd, zarządzać dniami wolnymi i tworzyć kalendarz 24/7 dla aktywów takich jak kryptowaluty.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Zipline Backtesting Engine, odcinek 5 z 7. Twój algorytm wykrywa idealny sygnał wyjścia i odpala ogromne zlecenie sprzedaży. Problem w tym, że jest sobota. Jeśli twój backtesting engine nie wie, że giełda jest zamknięta, to zlecenie albo wykona się na widmowym rynku, albo zcrashuje całą twoją symulację. Custom Trading Calendars mapują rzeczywistość globalnych godzin rynkowych, żeby zapobiec dokładnie takiemu scenariuszowi. Trading calendar w Zipline to absolutne source of truth dla sesji rynkowych. Dyktuje on, kiedy dane mogą być ingestowane, a zlecenia procesowane. Domyślnie Zipline zakłada standardowy harmonogram amerykańskiej giełdy akcji. Jeśli chcesz handlować międzynarodowymi akcjami, futuresami czy alternatywnymi aktywami, musisz zdefiniować specyficzne zasady tych giełd. Robisz to, tworząc customową klasę, która dziedziczy po bazowej klasie Trading Calendar z Zipline. Musisz skonfigurować tylko kilka konkretnych properties, żeby ustalić granice dnia handlowego. Po pierwsze, ustawiasz open time. Dyktuje to dokładną godzinę i minutę, o której rynek zaczyna akceptować zlecenia. Po drugie, ustawiasz close time, oznaczający ostatnią minutę sesji handlowej. Po trzecie, definiujesz regular holidays. To kolekcja konkretnych dat, kiedy giełda jest całkowicie zamknięta, takich jak święta narodowe. Zipline nie wykonuje całej tej kalkulacji dat od zera. Mocno wykorzystuje bibliotekę pandas, a konkretnie klasy Holiday Calendar i Custom Business Day z pandasa. Kiedy dostarczasz swoją listę regular holidays, w zasadzie wypełniasz obiekt Holiday Calendar z pandasa. Zipline łączy tę logikę pandasa z twoimi zdefiniowanymi open i close times, żeby wygenerować potężny, pre-kalkulowany index każdej pojedynczej, prawidłowej minuty handlowej dla całego czasu trwania twojego backtestu. Ta kalkulacja upfront jest kluczowa. Oznacza to, że twój algorytm nie ewaluuje skomplikowanej matematyki dat podczas każdego pojedynczego ticku symulacji. Po prostu odpytuje wysoce zoptymalizowany array. To jest ta część, która ma znaczenie. Nie wszystkie rynki śpią. Jeśli symulujesz trade'y na kryptowalutach, standardowe założenia o weekendach zrujnują twój data alignment. Musisz zbudować ciągły kalendarz dwadzieścia cztery na siedem. Przejdźmy przez proces budowania takiego kalendarza, który nazwiemy TFS Exchange Calendar. Definiujesz swoją nową klasę i dziedziczysz po standardowej klasie bazowej. Dla open time podajesz północ. Dla close time podajesz dwudziestą trzecią pięćdziesiąt dziewięć, co daje ci pełny cykl dobowy. Ponieważ giełdy kryptowalut nie obchodzą tradycyjnych świąt, ustawiasz property regular holidays, żeby zwracało pustą listę. Ostatnim krokiem jest dostosowanie harmonogramu tygodniowego. Tradycyjne trading calendars używają obiektu Custom Business Day z pandasa, skonfigurowanego ściśle od poniedziałku do piątku. Dla twojego kalendarza TFS, nadpisujesz to property weekmask, żeby jawnie uwzględniało sobotę i niedzielę. Kiedy klasa jest gotowa, rejestrujesz ją w środowisku Zipline używając customowego identyfikatora typu string. Od tego momentu zarówno twoje bundle do data ingestion, jak i twoje algorytmy handlowe będą rozpoznawać ciągły harmonogram. Zlecenia będą procesowane sekwencyjnie bez pomijania weekendów, a dane na poziomie minut będą idealnie mapować się na rzeczywiste timestampy. Jeśli reguły twojego kalendarza są źle skonfigurowane, twoje dane cenowe się rozjadą, a twoje performance metrics będą całkowicie fikcyjne. Granice czasowe dyktują każdą akcję w silniku event-driven, a trading calendars to dokładnie ten sposób, w jaki egzekwujesz te granice. To wszystko w tym odcinku. Dzięki za wysłuchanie i keep building!
6

Metryki ryzyka i wydajności oraz niestandardowa ewaluacja

3m 44s

Ten odcinek skupia się na śledzeniu i ocenie wydajności strategii. Słuchacze dowiedzą się, jak interpretować DataFrame z wynikami i podpinać się pod cykl życia symulacji, aby obliczać niestandardowe metryki ryzyka.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Zipline Backtesting Engine, odcinek 6 z 7. Obliczanie złożonych metryk ryzyka na każdym ticku może strasznie spowolnić twój backtest. Chcesz, żeby twoje symulacje były szybkie, ale musisz też dokładnie wiedzieć, jak twoja strategia zachowuje się pod obciążeniem. Możesz tak naprawdę wyłączyć domyślne śledzenie podczas debugowania albo napisać mocno zoptymalizowane, własne trackery. Ten odcinek omawia Risk Performance Metrics i Custom Evaluation. Zipline grupuje swoje wbudowane obliczenia ryzyka i wydajności w strukturę zwaną Metric Set. Domyślny Metric Set automatycznie generuje standardowe statystyki, takie jak beta, współczynnik Sharpe'a i całkowite zwroty. Po zakończeniu symulacji, Zipline pakuje wszystkie te obliczenia w performance DataFrame. Każda śledzona metryka staje się kolumną, a każdy wiersz reprezentuje krok czasowy w twojej symulacji. Jeśli nie potrzebujesz wszystkich tych domyślnych metryk, możesz przekazać okrojony Metric Set podczas uruchamiania silnika, co znacznie oszczędza czas przetwarzania. Gdy domyślne metryki nie odzwierciedlają twojego konkretnego modelu ryzyka, definiujesz customową metrykę. Robisz to, tworząc subclassę bazowego obiektu metryki Zipline. Napisanie customowej metryki oznacza podpięcie się bezpośrednio pod wewnętrzny zegar symulacji. Masz pełną kontrolę nad tym, kiedy wykonuje się twoja logika, implementując trzy konkretne metody cyklu życia: start of simulation, end of session i end of bar. W metodzie start of simulation inicjalizujesz zmienne i ustawiasz stan początkowy. Metoda end of session odpala się raz, na zamknięcie dnia handlowego. Metoda end of bar wykonuje się po każdej pojedynczej aktualizacji ceny, co jest kluczowe dla strategii minutowych. Za każdym razem, gdy odpala się jeden z tych czasowych hooków, Zipline przekazuje mu dwa wymagane argumenty: ledger i packet. Ledger przechowuje aktualny, matematyczny stan twojej symulacji. Zawiera bieżącą wartość portfela, salda gotówkowe i wszystkie otwarte pozycje. Traktujesz ledger jako dane read-only. Packet z kolei to pusty dictionary, reprezentujący payload danych dla tego konkretnego kroku czasowego. To do packetu zapisujesz dane. Każda para key-value, którą przypiszesz do dictionary packetu, natychmiast staje się kolumną w twoim końcowym performance DataFrame. Prześledźmy, jak monitorować maksymalny intraday drawdown za pomocą hooka end of bar. Najpierw definiujesz swoją customową klasę metryki. W metodzie start of simulation tworzysz dwie zmienne: jedną do śledzenia najwyższej wartości portfela, jaką do tej pory zaobserwowano, i drugą dla obecnego maximum drawdown. Obie zaczynają od zera. I tu jest kluczowa sprawa. Ponieważ spadki intraday są niewidoczne, jeśli sprawdzasz tylko dzienne ceny zamknięcia, musisz wykonać swoją logikę wewnątrz metody end of bar. W tej metodzie odczytujesz bieżącą wartość portfela z argumentu ledger. Jeśli bieżąca wartość jest wyższa niż twoja zarejestrowana najwyższa wartość, aktualizujesz high water mark. Jeśli jest niższa, obliczasz procentowy spadek. Jeśli ten spadek przekracza twój zarejestrowany maximum drawdown, aktualizujesz zmienną maximum drawdown. Na koniec bierzesz swoją zmienną maximum drawdown i przypisujesz ją do klucza w argumencie packet. Dzięki zapisywaniu do packetu na końcu każdego bara, twój końcowy performance DataFrame będzie zawierał szczegółowy, minutowy zapis najgorszego spadku intraday. Customowe metryki to w zasadzie po prostu obserwatorzy odczytujący ledger symulacji i zapisujący do wyjściowego packetu, co daje ci pełną kontrolę nad tym, co i kiedy jest mierzone. To wszystko w tym odcinku. Dzięki za wysłuchanie i koduj dalej!
7

Rozszerzanie architektury Zipline

4m 57s

Ten finałowy odcinek omawia rozszerzalną architekturę Zipline. Słuchacze dowiedzą się, jak podmieniać główne komponenty i rejestrować niestandardowy blotter w celu integracji z live tradingiem.

Pobierz
Cześć, tu Alex z DEV STORIES DOT EU. Zipline Backtesting Engine, odcinek 7 z 7. Spędzasz miesiące na doskonaleniu algorytmu w symulatorze, ale prawdziwy rynek nie akceptuje symulowanych zleceń. Zipline został zaprojektowany głównie do backtestingu, ale jego modułowa architektura sprawia, że możesz całkowicie ominąć wewnętrzną symulację i routować bezpośrednio do prawdziwego execution engine. Rozszerzenie architektury Zipline umożliwia to przejście. Domyślnie, Zipline działa w zamkniętej pętli. Przekazujesz mu historyczne dane cenowe, on oblicza sygnały i wewnętrznie dopasowuje twoje zlecenia do przeszłego zachowania rynku. System celowo izoluje twój algorytm od zewnętrznych sieci. Ale nowoczesny system transakcyjny w końcu musi zacząć komunikować się ze światem zewnętrznym. Potrzebujesz sposobu na podmianę wewnętrznych komponentów symulacji na customowe moduły, które obsługują dane live i prawdziwy kapitał. Zipline radzi sobie z tym wymaganiem poprzez mechanizm rozszerzeń zbudowany wokół konkretnego pliku inicjalizacyjnego o nazwie extension dot py. Ten plik działa jak lokalny rejestr dla twojego środowiska. Kiedy framework Zipline startuje, natychmiast szuka tutaj zdefiniowanych przez użytkownika override'ów. Używasz tego pliku do rejestrowania nowych data bundles, customowych modeli prowizji i alternatywnych execution engines. Najbardziej krytycznym komponentem, który musisz podmienić do handlu live, jest Blotter. Blotter działa jako wewnętrzny system zarządzania zleceniami. Śledzi otwarte zlecenia, anuluje je na żądanie i przetwarza trade fills. Domyślny symulacyjny blotter udaje, że realizuje transakcje w oparciu o historyczny wolumen i algorytmy slippage'u. Aby handlować live, musisz to całkowicie ominąć. Osiągniesz to, pisząc customową klasę Blottera. Zamiast symulować egzekucję, metody twojej klasy wykonują wywołania sieciowe do API prawdziwego brokera. Kiedy algorytm żąda transakcji, twój customowy blotter formatuje to żądanie w live order i przesyła je na giełdę. Oto kluczowa sprawa. Nie modyfikujesz ani jednej linijki oryginalnego kodu źródłowego Zipline, żeby to zaimplementować. Definiujesz swoją customową klasę blottera we własnym workspace. Następnie otwierasz extension dot py. Importujesz funkcję rejestracji blottera z modułu utilities Zipline. Przekazujesz do tej funkcji unikalny string z nazwą twojego brokera, razem z twoją customową klasą blottera. To globalnie rejestruje twój execution engine. Na koniec, kiedy odpalasz swój skrypt transakcyjny z command line'a albo notebooka, po prostu podajesz string z nazwą twojego customowego blottera jako parametr startowy. Framework automatycznie podmienia wewnętrzne mechanizmy. Dokładnie ten sam algorytm, który działał w symulacji, teraz obraca prawdziwym kapitałem live. Wspieranie takiego poziomu modułowości wymaga bardzo stabilnego fundamentu. Zipline mocno opiera się na szybkich numerycznych dataframe'ach i relacyjnych bazach danych do przenoszenia informacji między algorytmem a blotterem. Wraz z wydaniem Zipline 3.0, główna architektura otrzymała znaczący update strukturalny, żeby zmodernizować ten fundament. Cała platforma została zmigrowana, aby wspierać Pandas 2.0 i SQLAlchemy 2.0. Upgrade do Pandas 2.0 przynosi znacznie lepsze zarządzanie pamięcią i szybsze czasy egzekucji dla ogromnych tablic time series, które Zipline przetwarza przy każdym ticku. SQLAlchemy 2.0 całkowicie modernizuje sposób, w jaki silnik komunikuje się z bazami danych SQL pod spodem. Wymusza bardziej restrykcyjne i jawne ścieżki egzekucji zapytań, kiedy system zarządza metadanymi aktywów i zapisuje wyniki transakcji. Te fundamentalne upgrade'y gwarantują, że niezależnie od tego, czy odpalasz potężny historyczny backtest, czy routujesz live orders przez customowe rozszerzenie brokera, silnik działa na nowoczesnym standardzie infrastruktury danych Pythona. Dzięki oddzieleniu logiki transakcyjnej od mechaniki egzekucji, architektura gwarantuje, że twój algorytm pozostaje całkowicie nietknięty, podczas gdy warstwa egzekucji pod spodem dostosowuje się do rzeczywistości. Gorąco zachęcam cię do przejrzenia oficjalnej dokumentacji i spróbowania napisania własnych rozszerzeń hands-on. Jeśli masz pomysły na to, co powinniśmy omówić w następnej kolejności, wejdź na DEV STORIES DOT EU, żeby zasugerować tematy do naszych przyszłych serii. Dzięki za spędzenie ze mną tych kilku minut. Do usłyszenia następnym razem, trzymaj się.