Jak wspomniano wcześniej, przez pozostałą część rozdziału będziemy pracować z implementacjami SMA. Aby je rozróżnić, będziemy zmieniać nazwę funkcji dla każdej kolejnej implementacji, zaczynając od sma_slow_1(). Wszystkie implementacje SMA otrzymają następujące parametry:
period : Aby określić, ile obserwacji ma być używanych dla SMA.
symbol: Aby oznaczyć składnik aktywów, dla którego chcemy wykonać obliczenia. W tym przykładzie opcje będą for lub for. Jednak gdy samodzielnie uruchomisz system, będziesz mógł go rozszerzyć o dowolny symbol kryptowaluty, który sobie zażyczysz.
data : Rzeczywiste dane zawierające szeregi czasowe cen dla każdego zasobu.
Zrobimy dwa założenia, że kolumna data – timestamp jest w porządku rosnącym i nie mamy luk w szeregach czasowych, co oznacza, że mamy dane cenowe z każdej minuty. To pozwala nam pominąć wszelkie procedury zamawiania i sprawdzić, czy SMA powinno zawierać wewnętrznie NA, gdy nie są dostępne żadne dane. Zauważ, że oba te założenia są spełnione przez naszą symulację danych. Teraz wyjaśnimy, jak sma_slow_1() działa. Zauważ, że jest to bardzo nieefektywna implementacja i zdecydowanie powinieneś unikać programowania w ten sposób. Są to jednak typowe błędy popełniane przez ludzi i będziemy je usuwać jeden po drugim, mierząc ich wpływ na szybkość kodu. Zobaczmy, jak to się robi, wykonując następujące kroki:
- Najpierw tworzymy pustą ramkę danych nazwaną result, który zawiera pojedynczą kolumnę o nazwie sma.
- Następnie wykonujemy pętlę po wszystkich wierszach danych; oznacza koniec lub prawy koniec rozważanego interwału SMA.
- Tworzymy liczbę całkowitą position, która jest taka sama jak end za każdym razem, gdy zaczynamy pętlę, a także obiekt sma, który będzie zawierał rzeczywiste obliczenia SMA dla pozycji końcowej, liczbę całkowitą n_accumulated, która śledzi liczbę zgromadzonych obserwacji oraz ramkę danych period_prices, która zawiera jedną kolumnę do przechowywania cen dla bieżącej kalkulacji SMA.
- Następnie sprawdzamy, czy obserwacja przy bieżącym end odpowiada temu symbol, co nas interesuje. Jeśli tak nie jest, po prostu ignorujemy tę iterację, ale jeśli tak, będziemy kumulować perdiod_prices zaczynając od pozycji end (pamiętaj, że position równa się end i temu punktowi) i cofając się do liczby skumulowanych cen jest równa period interesującej nas lub aktualnej position mniejszej niż 1 (co oznacza, że jesteśmy na początku szeregu czasowego). Aby to zrobić, używamy pętli while, która sprawdza warunek wspomniany wcześniej, zwiększa n_acumulated, gdy zostanie znaleziona obserwacja z tym samym symbol , a jej dane są dołączane do ramki danych period_prices, i zwiększa position niezależnie od tego, czy obserwacja była przydatna, abyśmy nie utknęli.
- Po zakończeniu pętli while wiemy, że albo zgromadziliśmy liczbę cen równą period, która nas interesuje, albo napotkaliśmy początek szeregu czasowego. W pierwszym przypadku obliczamy średnią takich cen poprzez iterację po ramce danych period_prices i przypisujemy ją jako wartość sma dla aktualnej pozycji end. W drugim przypadku po prostu rejestrujemy wartość NA, ponieważ nie byliśmy w stanie obliczyć pełnego SMA. Spójrz na następujący fragment kodu:
Jeśli implementacja wydaje się skomplikowana, to dlatego, że tak jest. Gdy zaczniemy ulepszać nasz kod, zostanie on oczywiście uproszczony, co ułatwi jego zrozumienie.
- Teraz chcemy faktycznie zobaczyć, że to działa. Aby to zrobić, wprowadzamy plik sma-slow.R do pamięci (która zawiera wszystkie powolne implementacje), a także dane, jak pokazano w poniższym fragmencie kodu:
source(„./sma-slow.R”)
data_original <- read.csv(„.data.csv”)
Zwróć uwagę, że bierzemy tylko pierwsze 100 obserwacji, które odpowiadają 50 minutom akcji cenowej Bitcoin (pamiętaj, że te 100 obserwacji zawiera tylko 50 dla Bitcoin; pozostałe 50 dotyczą Litecoina). Widzimy, że SMA (5) dla Bitcoin ma sens, w tym pierwsze cztery NA (możesz sprawdzić liczby ręcznie, ale pamiętaj, aby wykorzystać dane i wyniki do własnej symulacji danych):
data <- data_original[1:100, ]
symbol <- „BTC”
period <- 5
sma-1 <= sma_slow_1(period, symbol, data)
sma_1
#> sma
#> 1 NA
#> 2 NA
#> 3 NA
#> 4 NA
#> 5 7999,639
#> 6 7997.138
#> 7 8000.098
#> 8 8001.677
#> 9 8000.633
#> 10 8000.182
(Obcięte wyjście)
Zanim zrozumiemy, jak naprawić ten kod, musimy zrozumieć, dlaczego R może być powolne, a także jak zmierzyć wpływ, jaki wywieramy, gdy go ulepszamy.