L'apprendimento automatico nel trading: teoria, modelli, pratica e algo-trading - pagina 20

 
articolo interessante https://geektimes.ru/post/144405/, forse qualcuno capirà come simulare questo in R
Прогнозирование финансовых временных рядов
Прогнозирование финансовых временных рядов
  • geektimes.ru
Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста. Пометьте топик понятными вам метками, если хотите или закрыть
 

Ho iniziato a sperimentare con i cluster, sulla base dei motivi che ho menzionato prima. Ho incontrato un problema - quando ho provato a incollare il prezzo dai pezzi che corrispondono a un cluster, i posti incollati erano vuoti di prezzo (e questo è logico, ma non mi è venuto in mente)) ) La domanda è come risolvere queste lacune

#  типа какая то цена
dat <- cumsum(rnorm(1000))+1000
plot(dat,t="l")


#  фун. матрицы хенкеля для имитации скользящего окна
hankel<- function(data, r=10) {
  do.call(cbind,
          lapply(0:(r-1),function(i) { data[(i+1):(length(data)-(r-1-i))]}))}
#  делаем аналог скользящего окна глубиной в 50
glubina <- 50
D <- hankel(dat,r = glubina)


#  скалирую и центрирую дату, проще сказать нормализирую
DC <- t(  apply(D, 1,    function(x) {  scale(x,T,T)  }    ))


library(SOMbrero)
#  тренирую сеть кохонена на данных чтоб получить кластера
TS <- trainSOM(DC,  dimension=c(3,3))

#  край матрицы будет вектор нашей цены без первых значений
dt <- D[,glubina] 
#  полученые кластера
cl <- TS$clustering

#  график цены , график кластеров этой цены
par(mfrow=c(2,1))
plot(dt,t="l")
plot(cl,t="l")
par(mfrow=c(1,1))


#  пробую посмотреть склееный график только одного кластера 
one_clust <- dt[cl==3]
#  график с разрывами в местах склейки
plot(one_clust,t="l")
 
Dr.Trader:

Anch'io ho questo problema. Di solito basta eseguire attributi(KZP) per ottenere una lista di variabili disponibili e poi semplicemente passare attraverso di esse, per esempio KZP$window ecc. e trovare i numeri di cui hai bisogno. Ma qui questi numeri sono generati nella funzione Riepilogo stesso e non sono memorizzati da nessuna parte.

Qui c'è un codice sorgente: https://cran.r-project.org/web/packages/kza/index.html, dovremmo eseguire qualcosa come questo:

A proposito, può essere utile per voi se usate gli indicatori, questa funzione rileva in un dato molto rumoroso componenti periodiche, periodo in breve, questo periodo è in costante cambiamento nel mercato.

L'idea è di identificare costantemente questo periodo dominante e adattare gli indicatori ad esso, non solo con parametri fissi come fanno tutti gli altri. Ho testato questo approccio molto superficialmente su un appuntamento casuale, e il risultato è stato positivo rispetto all'approccio abituale. Ho preso l'indicatore RSI, ha perso con i parametri fissi e ha guadagnato con quelli adattivi. Se volete usarlo, potete usarlo e sarei molto interessato a leggere il risultato della vostra ricerca

 
mytarmailS:

Ho iniziato a sperimentare con i cluster, sulla base dei motivi che ho menzionato prima. Ho incontrato un problema - quando ho provato a incollare il prezzo dai pezzi che corrispondono a un cluster, i posti incollati erano vuoti di prezzo (e questo è logico, ma non mi è venuto in mente)) ) La domanda è come risolvere queste lacune

Logaritmo della serie di prezzi, poi convertire in una serie di differenze. Per incollare la serie, lasciate solo gli intervalli della serie che corrispondono alla condizione trovata. Poi fare una nuova serie da questa serie attraverso la somma. E, se lo si desidera, esporlo dopo.
 
Anton Zverev:
Logaritmi la serie dei prezzi, poi la converta in una serie di differenze. Per incollare la serie, lasciate solo gli intervalli che corrispondono alla condizione trovata. Poi fare una nuova serie da questa serie attraverso la somma. E, se lo si desidera, esporlo dopo.
Grazie, è più o meno come me lo immaginavo, proviamo
 

Ho imparato un altro paio di cose interessanti:

La funzione precedentemente postata per setacciare i predittori (designTreatmentsN$scoreFrame) chiaramente non dà l'insieme finale dei predittori. Non rimuove nemmeno i predittori correlati al 100%, in più potrebbe rimuovere qualcosa che volete, oltre a lasciare spazzatura. Ho complicato un po' il loro metodo di setacciamento - all'inizio sto setacciando i predittori nel vecchio modo, tramite designTreatmentsN$scoreFrame (ho aumentato la soglia due volte - 2/N, per setacciare meno predittori potenzialmente buoni). Poi rimuovo tutti i predittori che correlano >0,99 (ne ho molti dopo la generazione casuale di delta e somme. E guardo la correlazione dei predittori tra loro, non con la variabile obiettivo). Poi cerco geneticamente il miglior set di predittori rimanenti.

Cerco di usare qualcos'altro dall'articolo sui componenti principali. La funzione qui sotto costruisce il modello a componenti principali e restituisce R^2 per il caso in cui ho usato tutte le componenti principali trovate. Non ha la "scala Y" come un altro esempio dell'articolo, ma questo modo è più veloce. Ora lo uso per stimare il set di predittori (probabilmente per niente, non lo so ancora :) ). L'ultima colonna del parametro srcTable è la variabile target. Ci possono essere errori se il predittore ha troppo pochi valori, la funzione può non adattarsi ad alcuni dati.

library('caret')
GetPCrsquared <- function(srcTable){
        targetName <- tail(colnames(srcTable),1)
        origVars <- setdiff(colnames(srcTable), targetName)
        # can try variations such adding/removing non-linear steps such as "YeoJohnson"
        prep <- preProcess(srcTable[,origVars], method = c("zv", "nzv", "center", "scale", "pca"))
        prepared <- predict(prep,newdata=srcTable[,origVars])
        newVars <- colnames(prepared)
        prepared$target <- srcTable$target
        modelB <- lm(paste(targetName, paste(newVars,collapse=' + '),sep=' ~ '),data=prepared)
        return(summary(modelB)$r.squared)
}

Mentre prima avevo un R^2 di circa 0,1, ora ho raggiunto 0,3. Non è ancora sufficiente, raccomandano di usare almeno lo 0,95. Un'altra cosa strana è che con R^2=0.1 avevo il 37% di errore nel fronttest, mentre con R^2=0.3 questo errore è cresciuto al 45%. Forse il problema è che ho aggiunto più barre e più indicatori al set di predittori. Un passo avanti e due indietro, ora ho bisogno di analizzare l'intero set di indicatori e rimuovere quelli non necessari. Oppure il modello delle componenti principali semplicemente non è applicabile al forex (difficile da verificare, prima ho bisogno di raggiungere R^2 > 0.95, e vedere quale sarà il risultato in fronttest, con un modello non addestrato è troppo presto per trarre conclusioni).

Ho anche confrontato il pacchetto GA (genetica) e GenSA (gradient annealing, dall'esempio di Alexey). Entrambi i pacchetti hanno ottenuto lo stesso risultato. La genetica sa come lavorare in multi-thread, quindi ha vinto in tempo. Ma GenSA sembra vincere su un solo filo. C'è anche un trucco per memorizzare i risultati nella cache, penso che Alex lo apprezzerà:

fitness_GenSA_bin <- function(selectionForInputs){
        testPredictorNames <- predictorNames[ which(selectionForInputs == TRUE) ]
        #do  the fitness calculation
}

library(memoise)
fitness_GenSA_bin_Memoise <- memoise(fitness_GenSA_bin)

fitness_GenSA <- function(selectionForInputs){
        selectionForInputs[selectionForInputs>=0.5] <- TRUE
        selectionForInputs[selectionForInputs<0.5] <- FALSE
        return(fitness_GenSA_bin_Memoise(selectionForInputs))
}

library(GenSA, quietly=TRUE)
GENSA <- GenSA(fn = fitness_GenSA,
                                lower = rep(0, length(predictorNames)),
                                upper = rep(1, length(predictorNames)),
                                control=list(smooth=FALSE, verbose=TRUE)
                                ) 

Il punto è che la funzione intermedia fitness_GenSA_bin_Memoise prende i dati dalla cache se tale insieme di predittori è già stato incontrato almeno una volta. Il fitness_GenSA_bin dovrebbe contenere i calcoli della funzione di fitness stessa, e sarà chiamato solo una volta per ogni set unico.

mytarmailS:

A proposito, può essere utile per voi se usate gli indicatori, questa funzione rileva le componenti periodiche in un dato molto rumoroso, periodo in breve, questo periodo cambia costantemente nel mercato.

L'idea è di identificare costantemente questo periodo dominante e adattare gli indicatori ad esso, non solo con parametri fissi come fanno tutti gli altri. Ho testato questo approccio molto superficialmente su un appuntamento casuale, e il risultato è stato positivo rispetto all'approccio abituale. Ho preso l'indicatore RSI, ha perso con i parametri fissi e ha guadagnato con quelli adattivi. Se ti interessa puoi usarlo, sarò molto interessato a leggere il risultato della tua ricerca

Per ora sto usando solo i parametri standard per gli indicatori. Se ho intenzione di utilizzare un indicatore, sarà più utile utilizzare i parametri standard per il trading di azioni su D1, ma devono essere regolati. Non sono in grado di spostare i risultati da D1 a H1, più indicatori uso, più mi blocco su D1. Si scopre che i parametri dell'indicatore devono essere cambiati a seconda del timeframe, e del tempo, sì.

 
Dr.Trader:

Ho imparato un altro paio di cose interessanti:

La funzione precedentemente postata per setacciare i predittori (designTreatmentsN$scoreFrame) chiaramente non dà l'insieme finale dei predittori. Non rimuove nemmeno i predittori correlati al 100%, in più potrebbe rimuovere qualcosa che volete, oltre a lasciare spazzatura. Ho complicato un po' il loro metodo di setacciamento - all'inizio sto setacciando i predittori nel vecchio modo, tramite designTreatmentsN$scoreFrame (ho aumentato la soglia due volte - 2/N, per setacciare meno predittori potenzialmente buoni). Poi rimuovo tutti i predittori che correlano >0,99 (ne ho molti dopo la generazione casuale di delta e somme. E guardo la correlazione dei predittori tra loro, non con la variabile obiettivo). Poi cerco geneticamente il miglior set di predittori rimanenti.

Cerco di usare qualcos'altro dall'articolo sui componenti principali. La funzione qui sotto costruisce il modello a componenti principali e restituisce R^2 per il caso in cui ho usato tutte le componenti principali trovate. Non ha la "scala Y" come un altro esempio dell'articolo, ma questo modo è più veloce. Ora lo uso per stimare il set di predittori (probabilmente per niente, non lo so ancora :) ). L'ultima colonna del parametro srcTable è la variabile target. Ci possono essere errori se il predittore ha troppo pochi valori, la funzione può non adattarsi ad alcuni dati.

Mentre prima avevo un R^2 di circa 0,1, ora ho raggiunto 0,3. Non è ancora sufficiente, raccomandano di usare almeno lo 0,95. Un'altra cosa strana è che con R^2=0.1 avevo il 37% di errore nel fronttest, mentre con R^2=0.3 questo errore è cresciuto al 45%. Forse il problema è che ho aggiunto più barre e più indicatori al set di predittori. Un passo avanti e due indietro, ora ho bisogno di analizzare l'intero set di indicatori e rimuovere quelli non necessari. Oppure il modello delle componenti principali semplicemente non è applicabile al forex (difficile da verificare, prima ho bisogno di raggiungere R^2 > 0.95, e vedere quale sarà il risultato in fronttest, con un modello non addestrato è troppo presto per trarre conclusioni).

Ho anche confrontato il pacchetto GA (genetica) e GenSA (gradient annealing, dall'esempio di Alexey). Entrambi i pacchetti hanno ottenuto lo stesso risultato. La genetica sa come lavorare in multi-thread, quindi ha vinto in tempo. Ma GenSA sembra vincere su un solo filo. C'è anche un trucco per memorizzare i risultati nella cache, penso che Alex lo apprezzerà:

Il punto è che la funzione intermedia fitness_GenSA_bin_Memoise prende i dati dalla cache se tale insieme di predittori è già stato incontrato almeno una volta. Il fitness_GenSA_bin dovrebbe contenere i calcoli della funzione di fitness stessa, e sarà chiamato solo una volta per ogni set unico.

Finora, sto usando solo parametri standard per gli indicatori. Sono d'accordo, in generale, se gli indicatori sono stati sviluppati principalmente per D1, saranno più utili con parametri standard solo su questo timeframe. Non sono affatto in grado di spostare i risultati da D1 a H1, più uso gli indicatori, più mi blocco su D1. Si scopre che i parametri dell'indicatore devono essere cambiati a seconda del timeframe, e del tempo, sì.

Bello il caching. Ho provato a scriverlo io stesso. Ma c'è una soluzione pronta. Cueru. Grazie, amico.

E quale funzione di fitness usa quando si fa l'overshooting? Mancava quello. Dipendenza lineare o statistica di qualche tipo?
 
Dr.Trader:

Non c'è una "scala Y" come da un altro esempio dell'articolo,

Penso che questo sia il punto centrale dell'articolo. L'ho riletto, lo dice esplicitamente.

Tornando allo schema generale della preparazione di una lista di predittori, però.

Lo screening del rumore è solo una parte del problema e non risolve il resto dei problemi e delle raccomandazioni in questo settore.

Se tutto questo è compiuto, allora il prossimo algoritmo di lavoro è in un ciclo, come segue.

1. prendiamo un insieme selezionato ed elaborato di predittori. Questa lista è costante.

2. Per la finestra corrente, selezioniamo i predittori con uno degli algoritmi. Per esempio, ci sono due algoritmi in caret.

3. Adattamento del modello.

4.

5. Spostare la finestra e andare al punto 2.

Il numero di predittori di rumore era più di 80 su quei set iniziali di predittori che avevo in mano!

L'algoritmo standard seleziona quindi circa la metà dei predittori rimanenti che l'algoritmo non classifica come rumore. Mentre la finestra si muove, la composizione di questa metà cambia costantemente. Ma sempre l'errore sul set di allenamento e l'errore fuori dal campione sono più o meno uguali. Da cui concludo che il mio modello non è sovrallenato e questo è una conseguenza degli algoritmi di selezione dei predittori descritti sopra.

 

E quale funzione di fitness usate quando forzate in modo brutale?

Ho usato per addestrare la foresta, e restituire un errore sul campione di convalida. In linea di principio, ha funzionato - se la foresta si sovrallena anche solo un po', l'errore tende al 50%.

Ora uso GetPCrsquared(), quel codice sopra. Ho anche il tuo esempio da feature_selector_modeller.txt, ma ho bisogno di capire e ottenere il giusto pezzo di codice lì, quindi non l'ho ancora testato sui miei dati.

 
SanSanych Fomenko:

Credo che l'articolo parli proprio di questo. L'ho riletto, lo dice esplicitamente.

Ho provato anche la scala Y, R^2 in entrambi i casi (con e senza scala Y) è uscito lo stesso (anche se in questi casi si usano pacchetti diversi!)

Immagino che la scala Y possa dare lo stesso buon risultato con un minor numero di componenti principali. Ma, se anche usando tutti i componenti il risultato non è ancora soddisfacente (come nel mio caso) - non c'è differenza. Inoltre funziona più velocemente, il che è più importante per me ora. Ma non ho provato né con la teoria né con la pratica se questo metodo è adatto alla selezione dei predittori... All'inizio ho avuto l'idea di fare il modello a componenti principali su tutti i predittori e selezionare i predittori guardando i coefficienti delle componenti. Ma poi ho notato che con l'aggiunta di spazzatura - R^2 del modello scende. Sarebbe logico provare diversi set di predittori e cercare quelli con un R^2 più alto, ma è ancora solo una teoria.