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:
- Izgradnja i evaluacija svih modela za n razdoblja u budućnosti.
- Izbor najboljeg modela i njegova primjena na cijelom skupu podataka.
- 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)
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)
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.
Preplatite se
Preplatite se putem newslettera ili RSS feeda