Primjena AutoML modela za predikciju cijena dionica

Primjena AutoML modela za predikciju cijena dionica

Prije pola godine sam napisao post o primjeni modela dubokog učenja na predikciju cijene dionice tehnike (THNK). U ovom postu ću primijeniti drugi, u posljednje vrijeme vrlo popularni pristup za predikciju općenito: automatsko strojno učenje (dalje AutoML). AutoML podrazumijeva primjenu skupa različitih vrsta modela strojnog učenja te izbor najboljeg modela ovisno o izabranoj loss funkciji. AumoML najčešće ne zahtijeva znanje o programiranju i razvoju modela. Potrebno je samo pripremiti podatke za analizu (učitavanje podatka, bavljenje sa nedostajućim vrijednostima i slično), te promijeniti AutoML funkciju na čistu matricu podatka.

Postoji nekoliko poznatih AutoML alata. Primjerice, Googleov CloudAutoML, H2O AutoML, AutoKeras i drugi. Detaljniji popis AutoML modela možete pogledati na poveznici. U ovom postu ćemo primijeniti manje poznati paket u razvoju - RemixAutoML. Paket ima više korisnih funkcija ovisno o tipu predikcije (regresija/klasifikacija, supervised/unsupervised learning i dr.). U ovom postu ćemo primijeniti AutoTS funkciju iz navedenog paketa. Funkcija testira 7 različitih modela (popis svih modela možete pogledati na spomenutoj poveznici). Za svaki model algoritam testira različite vremenske pomake, transformacije podataka, pomične presjeke i druge specifikacije. Sve ove parametre možete sami izabrati kada zovete AutoTS funkciju. Važan korak je i izbor evaluacijske mjere (u ovom postu ćemo koristiti MAPE). Kao što piše u samom opisu paketa, algoritam se sastoji od tri koraka:

  1. Izgradnja i evaluacija svih modela za n razdoblja u budućnosti.
  2. Izbor najboljeg modela i njegova primjena na cijelom skupu podataka.
  3. Generiranje predviđanja primjenom najboljeg modela za n razdoblja u budućnosti.

Za početak je potrebno učitati podatke i pripremiti ih za analizu. Za unos podataka možete koristi korake opisane u već spomenutom postu. U nastavku pretpostavljam da ste učitali podatke. AutoTS funkcija omogućuje samo univarijantnu analizu. Drugim riječima, argument AutoTS funkcije zahtijeva samo dva argumenta: kolonu datuma i jednu vremensku seriju.

Za predmetnu analizu ćemo ponovno koristiti dionicu Tehnike. Tablica se sastoji od 2408 opservacija (redova) i tri kolone: zadnja cijena za određeni dan, datum i simbol dionice. R korisnici će primijetiti jednu specifičnost: objekt sadrži klasu tbl_ts, odnosno objekt klase tsibble.

library(tidyverse)
library(kableExtra)
library(ggforce)
library(tsbox)
library(TTR)
library(PerformanceAnalytics)

glimpse(THNK)
## Observations: 2,409
## Variables: 3
## Key: simbol [1]
## $ zadnja <dbl> 11160, 11650, 11505, 11260, 11300, 11005, 11100, 11225,...
## $ datum  <date> 2008-01-02, 2008-01-03, 2008-01-04, 2008-01-07, 2008-0...
## $ simbol <chr> "THNK", "THNK", "THNK", "THNK", "THNK", "THNK", "THNK",...
class(THNK)
## [1] "tbl_ts"     "tbl_df"     "tbl"        "data.frame"

Budući da AutoTS funkcija iz RemixAutoML paketa procjenjuje univarijantni model, podaci su spremni za analizu. Potrebno je samo definirati argumente funkcije:

validation_index <- as.integer(nrow(THNK) * 0.1)
THNK_predvidjanja = RemixAutoML::AutoTS(
  data = THNK[, c("datum", "zadnja")],
  TargetName = "zadnja",
  DateName = "datum",
  FCPeriods = 7,
  HoldOutPeriods = validation_index,
  TimeUnit = "day",
  Lags = 10,
  NumCores = 8
)
## Registered S3 method overwritten by 'quantmod':
##   method            from
##   as.zoo.data.frame zoo
## Registered S3 methods overwritten by 'forecast':
##   method             from    
##   fitted.fracdiff    fracdiff
##   residuals.fracdiff fracdiff

Funkcija zahtijeva definiranje tablice podataka, naziv kolone koja sadrži numeričke vrijednosti i naziv kolone koja sadrži datum. Nadalje, mogu se definirati: broj razdoblja predviđanja (u našem slučaju 7), dio uzorka koji će se koristiti za validaciju (u našem slučaju 10%), vremenska jedinica, broj vremenskih pomaka koji će se procjenjivati (u našem slučaju 10) te broj jezgri. Napominjem da je funkcija računski zahtjevna, a ukupno vrijeme ovisi o broju jezgri koju imate na računalu. Ukratko, algoritam automatski izabire najbolji model s jednom varijablom - zadnjom cijenom dionice testirajući različite transformacije vremenske serije, različiti broj vremenskih pomaka (engl. lagova) i različite pomične presjeke. Svi ovi parametri su izabrani na optimalan način, to jest izabran je model sa najmanjom srednjom apsolutnom postotnom pogreškom (MAE).

Funkcija AutoTS vraća nekoliko zanimljivih objekata. Za početak pogledajmo uspješnost svakog testiranog modela. Najbolji model je TBATS, odnosno “Exponential smoothing state space model with Box-Cox transformation, ARMA errors, Trend and Seasonal components”. Više o modelima možete pronaći u sljedećoj knjizi.

THNK_predvidjanja$EvaluationMetrics %>%
  kable(format = "html", caption = "Tablica: Performanse svih prikazanih modela") %>%
  kable_styling(font_size = 12)
Table 1: Tablica: Performanse svih prikazanih modela
ModelName MeanResid MeanPercError MAPE MAE MSE ID
TBATS -8.52 -0.07974 0.27590 38.4951 2595.537 1
TBATS_ModelFreq -8.52 -0.07974 0.27590 38.4951 2595.537 2
TBATS_TSC -11.00 -0.09575 0.27743 39.4035 2596.944 3
TBATS_ModelFreqTSC 5.64 0.02952 0.27809 34.7974 2924.326 4
NN_ModelFreq -1.55 -0.01956 0.27939 35.9194 3192.301 5
NN_ModelFreqTSC -6.46 -0.05502 0.28842 38.4218 3236.530 6
NN_TSC -51.67 -0.22548 0.40567 78.4375 8863.493 7
NN -45.97 -0.19934 0.40624 75.9578 8336.874 8
ETS 35.11 0.37679 0.51392 47.4776 4561.571 9
ETS_ModelFreq 35.78 0.38746 0.52281 47.8989 4615.524 10
ETS_ModelFreqTSC 35.83 0.38824 0.52347 47.9295 4619.466 11
ARFIMA_TSC -383.36 -0.73758 0.73758 383.3606 159405.494 12
TSLM_ModelFreqTSC 966.19 -1.15099 1.15099 966.1852 960264.030 13
ARIMA 634.09 -1.50019 2.21338 634.0910 552318.241 14
TSLM_TSC 680.24 -2.05732 2.50652 709.2551 699197.568 15
ARIMA_ModelFreqTSC 219.46 1.07221 4.84723 219.4586 71782.139 16
ARIMA_TSC 211.14 1.71224 5.11974 211.1361 67423.707 17
ARIMA_ModelFreq 639.65 -5.28628 5.85379 639.6531 565656.781 18

Funkcija također vraća grafikon koji prikazuje predikcije za sljedećih n dana:

THNK_predvidjanja$TimeSeriesPlot + 
  labs(x = NULL, y = "Zadnja", title = "Procjena za sljedećih 5 dana najboljeg modela",  caption = NULL) +
  ggforce::facet_zoom(xlim = c(Sys.Date() - 7, Sys.Date() + length(THNK_predvidjanja$Forecast)), 
                      ylim = c(min(gather(THNK_predvidjanja$Forecast, datum, vrijednosti, -Date)$vrijednosti), 
                               max(gather(THNK_predvidjanja$Forecast, datum, vrijednosti, -Date)$vrijednosti)),
                      horizontal = FALSE) + 
  theme_light()

pocetna_cijena <- as.numeric(THNK[nrow(THNK), "zadnja"])
predvidena_cijena <- as.numeric(THNK_predvidjanja$Forecast[nrow(THNK_predvidjanja$Forecast), 2])
promjena_cijene <- round(((predvidena_cijena - pocetna_cijena) / pocetna_cijena) * 100, 2)

Najbolji model prikazan na grafikonu (TBATS) pokazuje rast cijene od 2.24%.

Investitore često zanima kakva je uspješnost modela u prošlosti (backtesting). Kao pokazatelj uspješnosti, poželjno je izraditi korelacijsku matricu:

stock_test <- THNK %>%
  dplyr::mutate(real_promjena = zadnja - dplyr::lag(zadnja)) %>%
  dplyr::mutate(real_class = ifelse(real_promjena > 0, 1, 0)) %>%
  dplyr::bind_cols(., predvidanja = THNK_predvidjanja$TimeSeriesModel$fitted) %>%
  dplyr::mutate(predikcija = zadnja - predvidanja) %>%
  dplyr::mutate(predikcija_class = ifelse(predikcija > 0, 1, 0)) %>%
  dplyr::filter(complete.cases(.)) %>%
  dplyr::slice((nrow(.) - validation_index):nrow(.)) # ostaviti samo test set
xtab <- table(factor(stock_test$real_class), factor(stock_test$predikcija_class))
c_matrix <- caret::confusionMatrix(xtab, positive = "1")
c_matrix_merge <- t(cbind.data.frame(data.frame(as.list(c_matrix$overall)), data.frame(as.list(c_matrix$byClass))))
c_matrix_merge <- data.frame(Pokazatelj = rownames(c_matrix_merge), Vrijednost = c_matrix_merge)
c_matrix_merge %>%
  kable(format = "html", caption = "Tablica: Matrica grešaka", row.names = FALSE) %>%
  kable_styling(font_size = 12, full_width = FALSE)
Table 2: Tablica: Matrica grešaka
Pokazatelj Vrijednost
Accuracy 0.9585062
Kappa 0.9167760
AccuracyLower 0.9250172
AccuracyUpper 0.9799256
AccuracyNull 0.5311203
AccuracyPValue 0.0000000
McnemarPValue 0.7518296
Sensitivity 0.9646018
Specificity 0.9531250
Pos.Pred.Value 0.9478261
Neg.Pred.Value 0.9682540
Precision 0.9478261
Recall 0.9646018
F1 0.9561404
Prevalence 0.4688797
Detection.Rate 0.4522822
Detection.Prevalence 0.4771784
Balanced.Accuracy 0.9588634

Tablica pokazuje različite mjere koje sadrži matrica grešaka. Za kreiranje matrice promatrane su samo predikcije iz testnog skupa. Objašnjenje pojedinih mjera mogu se pronaći na sljedećoj poveznici. Komentirat ću dvije vrlo često korištene mjera. Prva mjera je mjera točnosti (accuracy), koja pokazuje udio točnih klasifikacija u ukupnim klasifikacijama. Druga je osjetljivost (Sensitivity), koja pokazuje udio točnih pozitivnih klasifikacija od ukupno točnih klasifikacija.

Uspješnost na test skupu možemo i vizualno pokazati pomoću paketa PerformanceAnalytics, odnsno funkcije charts.PerformanceSummary. Funkcija ima minimalno jedan argument - matricu prinosa. Koristit ću dva vektora prinosa. Jedan je vektor prinosa pod pretpostavkom držanja dionice THNK cijelo promatrano razbolje, a drugi vektor podrazumijeva kupnju i prodaju ovisno o predikcijama modela koje smo koristili.

prinosi <- THNK %>% 
  dplyr::bind_cols(., predvidanja = THNK_predvidjanja$TimeSeriesModel$fitted) %>%
  dplyr::mutate(signal = ifelse((predvidanja - dplyr::lag(zadnja)) > 0, 1, 0)) %>% 
  dplyr::mutate(prinos = ROC(zadnja), 
                prinos_strategija = ROC(zadnja) * signal) %>% 
  dplyr::filter(!is.na(prinos_strategija)) %>% 
  dplyr::slice((nrow(.) - validation_index):nrow(.)) %>% # ostaviti samo test set
  dplyr::select(prinos, prinos_strategija, datum, simbol)
charts.PerformanceSummary(tsbox::ts_xts(prinosi))
## [time]: 'datum'

Slika pokazuje znatno bolje performanse aktivne strategije (trgovanje na temelju modela) nego pasivne strategije. Kumulativni prinosi ne uzimaju u obzir provizije koje se plaćaju brokerima za trgovanje. Međutim, teško je vjerovati da bi prinos pojeo ekstra prinos.

Zaključno, investitori koji vjeruju da je tržište neefikasno u tolikoj mjeri da se cijene mogu predvidjeti na temelju prošlih zaključnih cijena (što ne vjerujem), imaju vrlo snažan alat za ostvarivanje prinosa većih od tržišnih - AutoML modele. Ubuduće ću pokušati koristiti veći broj nezavisnih varijabli i vidjeti mogu li se dodatno poboljšati performanse modela.



Comments powered by Talkyard.

Preplatite se

Preplatite se putem newslettera ili RSS feeda

Vidi također