L'apprentissage automatique dans la négociation : théorie, modèles, pratique et algo-trading - page 20

 
article intéressant https://geektimes.ru/post/144405/, peut-être que quelqu'un comprendra comment simuler ceci dans R
Прогнозирование финансовых временных рядов
Прогнозирование финансовых временных рядов
  • geektimes.ru
Только зарегистрированные пользователи могут оставлять комментарии. Войдите, пожалуйста. Пометьте топик понятными вам метками, если хотите или закрыть
 

J'ai commencé à expérimenter les clusters, sur la base des motifs que j'ai mentionnés précédemment. J'ai rencontré un problème - lorsque j'ai essayé de coller le prix des pièces qui correspondent à un cluster, les endroits collés étaient des écarts de prix (et c'est logique, mais cela ne m'est pas venu à l'esprit)) ) La question est de savoir comment combler ces lacunes

#  типа какая то цена
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:

J'ai aussi ce problème. En général, il suffit d'exécuter attributes(KZP) pour obtenir une liste des variables disponibles, puis de les parcourir, par exemple KZP$window etc. et de trouver les chiffres dont vous avez besoin. Mais ici, ces chiffres sont générés dans la fonction Résumé elle-même et ne sont stockés nulle part.

Voici un code source : https://cran.r-project.org/web/packages/kza/index.html, nous devrions exécuter quelque chose comme ceci :

A propos, cela peut vous être utile si vous utilisez des indicateurs, cette fonction détecte dans des données très bruyantes des composantes périodiques, période en somme, cette période est en constante évolution sur le marché.

L'idée est d'identifier en permanence cette période dominante et d'y adapter les indicateurs, et pas seulement avec des paramètres fixes comme tout le monde le fait. J'ai testé cette approche de manière très superficielle lors d'un rendez-vous aléatoire, et le résultat a été positif par rapport à l'approche habituelle. J'ai pris l'indicateur RSI, il a perdu avec des paramètres fixes, et il a gagné avec des paramètres adaptatifs. Si vous voulez l'utiliser, vous pouvez le faire et je serais très intéressé de lire le résultat de vos recherches.

 
mytarmailS:

J'ai commencé à expérimenter les clusters, sur la base des motifs que j'ai mentionnés précédemment. J'ai rencontré un problème - lorsque j'ai essayé de coller le prix des pièces qui correspondent à une grappe, les endroits collés étaient des écarts de prix (et c'est logique, mais cela ne m'a pas traversé l'esprit) :) ) La question est de savoir comment combler ces lacunes

Logarithme de la série de prix, puis conversion en une série de différences. Pour coller la série, ne laissez que les intervalles de la série qui correspondent à la condition trouvée. Puis faites une nouvelle série à partir de cette série par sommation. Et, si vous le souhaitez, exposez-le ensuite.
 
Anton Zverev:
Logarithmez la série de prix, puis convertissez-la en une série de différences. Pour coller la série, ne laissez que les intervalles qui correspondent à la condition trouvée. Puis faites une nouvelle série à partir de cette série par sommation. Et, si vous le souhaitez, exposez-le ensuite.
Merci, c'est à peu près comme ça que je l'imaginais, essayons.
 

J'ai appris d'autres choses intéressantes :

La fonction de tri des prédicteurs (designTreatmentsN$scoreFrame) postée précédemment ne donne clairement pas l'ensemble final de prédicteurs. Il ne supprime même pas les prédicteurs corrélés à 100%, et il peut supprimer quelque chose que vous voulez, et laisser des déchets. J'ai un peu compliqué leur méthode de tri - tout d'abord, je trie les prédicteurs à l'ancienne, via designTreatmentsN$scoreFrame (j'ai augmenté le seuil deux fois - 2/N, pour trier les prédicteurs potentiellement moins bons). Ensuite, je supprime tous les prédicteurs dont la corrélation est >0,99 (j'en ai beaucoup après la génération aléatoire des deltas et des sommes. Et je regarde la corrélation des prédicteurs entre eux, pas avec la variable cible). Ensuite, je recherche génétiquement le meilleur ensemble de prédicteurs restants.

J'essaie d'utiliser un autre élément de l'article sur les composantes principales. La fonction ci-dessous construit le modèle en composantes principales et renvoie le R^2 pour le cas où j'ai utilisé toutes les composantes principales trouvées. Il n'a pas d'échelle "Y" comme un autre exemple de l'article, mais cette méthode est plus rapide. Je l'utilise maintenant pour estimer l'ensemble des prédicteurs (probablement pour rien, je ne sais pas encore :) ). La dernière colonne du paramètre srcTable est la variable cible. Il peut y avoir des erreurs si le prédicteur a trop peu de valeurs, la fonction peut ne pas s'adapter à certaines données.

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)
}

Alors qu'avant j'avais un R^2 d'environ 0,1, j'ai maintenant atteint 0,3. Ce n'est toujours pas suffisant, ils recommandent d'utiliser au moins 0,95. Une autre chose étrange est qu'avec R^2=0.1 j'avais 37% d'erreur dans le fronttest, alors qu'avec R^2=0.3 cette erreur est passée à 45%. Le problème vient peut-être du fait que j'ai ajouté plus de barres et plus d'indicateurs à l'ensemble des prédicteurs. Un pas en avant et deux pas en arrière, maintenant je dois analyser l'ensemble des indicateurs et supprimer ceux qui sont inutiles. Ou le modèle des composantes principales n'est tout simplement pas applicable au forex (difficile à vérifier, je dois d'abord atteindre R^2 > 0,95, et voir quel sera le résultat dans le fronttest, avec un modèle non entraîné il est trop tôt pour tirer des conclusions).

J'ai également comparé le paquet GA (génétique) et GenSA (recuit de gradient, d'après l'exemple d'Alexey). Les deux paquets ont atteint le même résultat. La génétique sait comment travailler en multithread, elle a donc gagné à temps. Mais GenSA semble gagner sur un seul fil. Il existe également une astuce pour mettre les résultats en cache, je pense qu'Alex l'appréciera :

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)
                                ) 

Le fait est que la fonction intermédiaire fitness_GenSA_bin_Memoise prend les données du cache si cet ensemble de prédicteurs a déjà été rencontré au moins une fois. Le fichier fitness_GenSA_bin doit contenir les calculs de la fonction de fitness eux-mêmes, et ne sera appelé qu'une seule fois pour chaque ensemble unique.

mytarmailS:

A propos, cela peut vous être utile si vous utilisez des indicateurs, cette fonction détecte les composantes périodiques dans une donnée très bruyante, période en somme, cette période est en constante évolution sur le marché.

L'idée est d'identifier en permanence cette période dominante et d'y adapter les indicateurs, et pas seulement avec des paramètres fixes comme tout le monde le fait. J'ai testé cette approche de manière très superficielle lors d'un rendez-vous aléatoire, et le résultat a été positif par rapport à l'approche habituelle. J'ai pris l'indicateur RSI, il a perdu avec des paramètres fixes, et il a gagné avec des paramètres adaptatifs. Si cela vous intéresse, vous pouvez l'utiliser. Je serai très intéressé de lire le résultat de vos recherches.

Pour l'instant, je me contente d'utiliser les paramètres standard pour les indicateurs. Si je dois utiliser un indicateur, il sera plus utile d'utiliser les paramètres standard pour le trading d'actions sur D1, mais ils doivent être ajustés. Je n'arrive pas à déplacer les résultats de D1 à H1, plus j'utilise d'indicateurs, plus je reste bloqué sur D1. Il s'avère que les paramètres des indicateurs doivent être modifiés en fonction de l'horizon temporel, et du temps, oui.

 
Dr. Trader:

J'ai appris d'autres choses intéressantes :

La fonction publiée précédemment pour éliminer les prédicteurs (designTreatmentsN$scoreFrame) ne donne clairement pas l'ensemble final de prédicteurs. Il ne supprime même pas les prédicteurs corrélés à 100%, et il peut supprimer quelque chose que vous voulez, et laisser des déchets. J'ai un peu compliqué leur méthode de tri - au début, je trie les prédicteurs à l'ancienne, via designTreatmentsN$scoreFrame (j'ai augmenté le seuil deux fois - 2/N, pour trier les prédicteurs potentiellement moins bons). Ensuite, je supprime tous les prédicteurs dont la corrélation est >0,99 (j'en ai beaucoup après la génération aléatoire des deltas et des sommes. Et je regarde la corrélation des prédicteurs entre eux, pas avec la variable cible). Ensuite, je recherche génétiquement le meilleur ensemble de prédicteurs restants.

J'essaie d'utiliser un autre élément de l'article sur les composantes principales. La fonction ci-dessous construit le modèle en composantes principales et renvoie le R^2 pour le cas où j'ai utilisé toutes les composantes principales trouvées. Il n'a pas d'échelle "Y" comme un autre exemple de l'article, mais cette méthode est plus rapide. Je l'utilise maintenant pour estimer l'ensemble des prédicteurs (probablement pour rien, je ne sais pas encore :) ). La dernière colonne du paramètre srcTable est la variable cible. Il peut y avoir des erreurs si le prédicteur a trop peu de valeurs, la fonction peut ne pas s'adapter à certaines données.

Alors qu'avant j'avais un R^2 d'environ 0,1, j'ai maintenant atteint 0,3. Ce n'est toujours pas suffisant, ils recommandent d'utiliser au moins 0,95. Une autre chose étrange est qu'avec R^2=0.1 j'avais 37% d'erreur dans le fronttest, alors qu'avec R^2=0.3 cette erreur est passée à 45%. Le problème vient peut-être du fait que j'ai ajouté plus de barres et plus d'indicateurs à l'ensemble des prédicteurs. Un pas en avant et deux pas en arrière, maintenant je dois analyser l'ensemble des indicateurs et supprimer ceux qui sont inutiles. Ou le modèle en composantes principales n'est tout simplement pas applicable au forex (difficile à vérifier, je dois d'abord obtenir un R^2 > 0.95, et voir quel sera le résultat dans le fronttest, avec un modèle non entraîné il est trop tôt pour tirer des conclusions).

J'ai également comparé le paquet GA (génétique) et GenSA (recuit de gradient, d'après l'exemple d'Alexey). Les deux paquets ont atteint le même résultat. La génétique sait comment travailler en multithread, elle a donc gagné à temps. Mais GenSA semble gagner sur un seul fil. Il existe également une astuce pour mettre les résultats en cache, je pense qu'Alex l'appréciera :

Le fait est que la fonction intermédiaire fitness_GenSA_bin_Memoise prend les données du cache si cet ensemble de prédicteurs a déjà été rencontré au moins une fois. Le fichier fitness_GenSA_bin doit contenir les calculs de la fonction de fitness eux-mêmes, et ne sera appelé qu'une seule fois pour chaque ensemble unique.

Pour l'instant, je n'utilise que des paramètres standard pour les indicateurs. Je pense qu'ils devraient être ajustés. Je suis d'accord, en général, si les indicateurs ont été développés principalement pour D1, ils seront plus utiles avec des paramètres standards uniquement sur cette période. Je n'arrive pas du tout à faire passer les résultats de D1 à H1, plus j'utilise les indicateurs, plus je reste bloqué sur D1. Il s'avère que les paramètres des indicateurs doivent être modifiés en fonction de l'horizon temporel, et du temps, oui.

Cool pour la mise en cache. J'ai essayé de l'écrire moi-même. Mais il existe une solution toute prête. Cueru. Merci, mec.

Et quelle fonction d'adaptation utilisez-vous en cas de dépassement ? J'ai raté celui-là. Dépendance linéaire ou statistique quelconque ?
 
Dr. Trader:

Il n'y a pas d'"échelle Y" comme dans un autre exemple de l'article,

Je pense que c'est le but de l'article. Je l'ai relu, c'est dit explicitement.

Pour en revenir au schéma général de préparation d'une liste de prédicteurs, cependant.

L'écran anti-bruit n'est qu'une partie du problème et ne résout pas le reste des problèmes et des recommandations dans ce domaine.

Si tout cela est accompli, l'algorithme suivant fonctionne en boucle, comme suit.

1. Nous prenons un ensemble de prédicteurs sélectionnés et traités. Cette liste est constante.

2. Pour la fenêtre actuelle, nous sélectionnons les prédicteurs par l'un des algorithmes. Par exemple, il y a deux algorithmes dans caret.

3. Ajustement du modèle.

4.

5. Déplacez la fenêtre et passez à l'étape 2.

Le nombre de prédicteurs de bruit était supérieur à 80 sur les premiers ensembles de prédicteurs que j'avais entre les mains !

L'algorithme standard sélectionne ensuite environ la moitié des prédicteurs restants que l'algorithme ne classe pas comme du bruit. Au fur et à mesure que la fenêtre se déplace, la composition de cette moitié change constamment. Mais l'erreur sur l'ensemble d'apprentissage et l'erreur en dehors de l'échantillon sont toujours à peu près égales. J'en conclus que mon modèle n'est pas surentraîné et que c'est une conséquence des algorithmes de sélection des prédicteurs décrits ci-dessus.

 

Et quelle fonction d'adaptation utilisez-vous lors du forçage brutal ?

J'ai utilisé pour former la forêt, et renvoyer une erreur sur l'échantillon de validation. En principe, cela a fonctionné - si la forêt se surentraîne, même un peu, l'erreur tend à 50%.

Maintenant, j'utilise GetPCrsquared(), le code ci-dessus. J'ai également votre exemple de feature_selector_modeller.txt, mais j'ai besoin de comprendre et d'obtenir le bon morceau de code là-bas, donc je ne l'ai pas encore testé sur mes données.

 
SanSanych Fomenko:

Je pense que c'est le sujet de l'article. Je l'ai relu, ça le dit explicitement.

J'ai aussi essayé l'échelle Y, le R^2 dans les deux cas (avec et sans échelle Y) a donné le même résultat (même si dans ces cas-là, des paquets différents sont utilisés !)

Je suppose que l'échelle Y peut donner le même bon résultat avec un nombre inférieur de composantes principales. Mais, si même en utilisant tous les composants le résultat n'est toujours pas satisfaisant (comme dans mon cas) - il n'y a pas de différence. De plus, il fonctionne plus rapidement, ce qui est plus important pour moi maintenant. Mais je n'ai pas prouvé par la théorie ou par la pratique si cette méthode est adaptée à la sélection des prédicteurs... Au début, j'ai eu l'idée de faire le modèle en composantes principales sur tous les prédicteurs et de sélectionner les prédicteurs en regardant les coefficients des composantes. Mais ensuite j'ai remarqué qu'en ajoutant des déchets - le R^2 du modèle diminue. Il serait logique d'essayer différents ensembles de prédicteurs et de rechercher ceux qui ont un R^2 plus élevé, mais il ne s'agit que d'une théorie.

Raison: