C'est un rêve que tout le monde a. (Peut-être juste moi)
** Cette fois, nous avons construit un modèle de classification qui prédit si le taux dollar-yen augmentera, baissera ou restera le même dans une forêt aléatoire. ** **
Tout d'abord, pourquoi avez-vous choisi le modèle de classification (c'est-à-dire la classification ternaire selon laquelle le taux augmente, diminue ou reste le même) au lieu du modèle de régression (c'est-à-dire le modèle qui estime le taux avec Don Pisha)? Il existe plusieurs raisons.
・ L'évaluation du modèle de classification est plus intuitive que celle du modèle de régression (cette fois, la matrice de confusion a été calculée). ・ Il n'y a que trois actions que les humains exécutent réellement dans fx (acheter, vendre, ne rien faire), n'est-ce pas bon pour la classification? ・ Random forest Je voulais juste l'implémenter.
C'est pourquoi j'ai choisi la prédiction de classification.
(Si vous y réfléchissez plus tard, le volume des transactions est également important dans le commerce de transit. Étant donné que le taux spécifique est important pour déterminer le volume des transactions, je me demande si un modèle de régression permettant de prédire le taux avec précision était meilleur Je me demande. Je réessayerai la prochaine fois.)
Que dois-je faire avec la quantité de fonctionnalités lors de la configuration d'un modèle de prédiction de taux pour fx? Ensuite, si vous pensez à ce que les humains utilisent réellement pour acheter et vendre des dollars et des yens, la quantité de fonctionnalités peut vous venir à l'esprit.
L'analyse que les humains effectuent lors du trading avec fx est grossièrement divisée en analyse technique et analyse fondamentale. L'analyse technique consiste à prédire les mouvements de prix en examinant ce que l'on appelle des graphiques. D'autre part, l'analyse fondamentale consiste à prédire les mouvements de prix à partir de l'actualité et des affaires mondiales.
Cette fois, nous utiliserons l'analyse technique, qui est facile à intégrer en tant que fonctionnalité d'apprentissage automatique. La raison pour laquelle il est facile d'importer est que l'analyse technique ne traite que des nombres et est facile à programmer.
D'un autre côté, si vous souhaitez incorporer des fondamentaux (comme le text mining), c'est difficile et les fondamentaux sont souvent utilisés pour acheter et vendre dans une perspective à long terme, nous ne les utiliserons donc pas.
Maintenant que la politique a été décidée, recherchons l'ensemble de données. Cette fois, nous avons utilisé les données quotidiennes des 20 dernières années sur investment.com. Environ 250 jours (les transactions fx sont uniquement en semaine) x 20 ans à 5000 données peuvent être collectées.
import pandas as pd
df = pd.read_csv("USD_JPY.csv")
Comme mentionné ci-dessus, cette fois, nous utiliserons la valeur numérique de l'analyse technique comme quantité de caractéristiques. Plus précisément, j'ai utilisé cinq des bandes SMA5, SMA20, RSI14, MACD et Bollinger (2σ). Veuillez google pour les caractéristiques détaillées de chaque indicateur technique. ** Cependant, lors de la sélection d'un index technique à utiliser comme quantité de caractéristiques, il est important de faire attention à ne pas analyser statistiquement mais à éviter autant que possible le multico (colinéarité multiple), donc technique qui ne se corrèle pas autant que possible. Veuillez sélectionner un index. ** **
Pour le calcul des indicateurs techniques, utilisez une bibliothèque appelée talib, ce qui est extrêmement pratique. Il calculera l'indice technique d'un seul coup.
Ici, les valeurs techniques sont utilisées telles quelles pour RSI et MACD, mais les valeurs pour SMA et Bollinger band ne le sont pas. (Par exemple, même si la valeur SMA est 105, elle ne convient pas comme quantité de caractéristiques car on ne sait pas si la valeur de 105 est élevée ou basse telle quelle.) Par conséquent, en divisant les valeurs de SMA et de bande de Bollinger par la valeur de close, nous les convertirons en valeurs relatives et comparables avant de les utiliser comme quantités de caractéristiques.
Je pense qu'il existe de nombreuses autres façons de le faire, alors essayez celles que vous préférez!
import talib as ta
import numpy as np
#Utilisez le taux de clôture pour tous les calculs ultérieurs
close = np.array(df["le dernier prix"])
#Créer un dataframe vide pour mettre les fonctionnalités
df_feature = pd.DataFrame(index=range(len(df)),columns=["SMA5/current", "SMA20/current","RSI","MACD","BBANDS+2σ","BBANDS-2σ"])
#Ci-dessous, l'indice technique (quantité de fonctionnalités utilisée dans cet apprentissage) est calculé en utilisant talib et df_caractéristique caractéristique
#La moyenne mobile simple utilise le rapport entre la valeur moyenne mobile simple et le cours de clôture de la journée en tant que quantité de caractéristiques.
df_feature["SMA5/current"]= ta.SMA(close, timeperiod=5) / close
df_feature["SMA20/current"]= ta.SMA(close, timeperiod=20) / close
#RSI
df_feature["RSI"] = ta.RSI(close, timeperiod=14)
#MACD
df_feature["MACD"], _ , _= ta.MACD(close, fastperiod=12, slowperiod=26, signalperiod=9)
#Bande de Bollinger
upper, middle, lower = ta.BBANDS(close, timeperiod=20, nbdevup=3, nbdevdn=3)
df_feature["BBANDS+2σ"] = upper / close
df_feature["BBANDS-2σ"] = lower / close
Comme mentionné ci-dessus, les données des enseignants pour ce modèle sont les trois valeurs [haut, bas et (presque) inchangé]. Par conséquent, les données des enseignants sont créées en utilisant le ratio ci-dessus dans les données téléchargées à partir de investment.com.
Les fonctions spécifiques utilisées pour le créer sont les suivantes.
def classify(x):
#Par rapport à la veille-0.2%Groupe 0 si
if x <= -0.2:
return 0
#Par rapport à la veille, 0.2%<x<0.2%Puis groupe 1
elif -0.2 < x < 0.2:
return 1
#Par rapport à la veille, 0.2%Groupe 2 ci-dessus
elif 0.2 <= x:
return 2
Pourquoi avez-vous divisé la veille par -0,2% et 0,2%?
・ 100 (yen / dollar) x 0,002 = 0,2 (yen / dollar) = 20 pips, et j'ai pensé que cette valeur était appropriée comme valeur pour juger si le taux bougeait. ** ・ En divisant la veille en trois groupes de -0,2% et 0,2%, les données seront presque pour le moment. (Figure ci-dessous) **
À partir de la gauche, il s'agit du nombre de données du groupe 0, du groupe 1 et du groupe 2. Il est divisé presque également. Il est très important d'utiliser une forêt aléatoire pour que les classes de données sur les enseignants soient uniformément réparties. (Bien sûr, vous pouvez le faire même si les classes ne sont pas également réparties, mais vous devez le pondérer. Pour plus de détails, cet article est facile à comprendre. .)
Faites attention à ce qui précède et créez des données sur les enseignants.
df["Le ratio de la veille_float"] = df["Le ratio de la veille%"].apply(lambda x: float(x.replace("%", "")))
#Le ratio de la veille%Comment classer. Divisez les échantillons de chaque classe aussi égaux que possible
def classify(x):
if x <= -0.2:
return 0
elif -0.2 < x < 0.2:
return 1
elif 0.2 <= x:
return 2
df["Le ratio de la veille_classified"] = df["Le ratio de la veille_float"].apply(lambda x: classify(x))
#Décalez les données que vous voulez être enseignant d'un jour (je pense que vous pouvez les comprendre si vous pensez à la signification)
df_y = df["Le ratio de la veille_classified"].shift()
Faites un peu de traitement. Par exemple, si vous utilisez SMA5 pour calculer le montant de la fonction, la valeur sera NaN pendant les 4 premiers jours. (Parce qu'il faut au moins 5 jours de données pour calculer la moyenne sur 5 jours) Comme vous pouvez le voir, NaN est inclus au début des données de fonctionnalité, nous allons donc le supprimer.
df_xy = pd.concat([df_feature, df_y], axis=1)
df_xy = df_xy.dropna(how="any")
Ceci termine le prétraitement. Puisqu'une forêt aléatoire est utilisée cette fois, la normalisation / standardisation n'est pas nécessaire.
Tout ce que vous avez à faire est d'apprendre. Il peut être intéressant d'expérimenter en modifiant les paramètres de la forêt aléatoire ... Les hyper paramètres de la forêt aléatoire sont faciles à comprendre dans cet article.
De plus, les hyper paramètres ont été optimisés à l'aide d'Optuna. Lorsque vous utilisez optuna, sachez que la fonction objectif est définie pour renvoyer ce que vous souhaitez minimiser.
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score
import optuna
X_train, X_test, Y_train, Y_test = train_test_split(df_xy[["SMA5/current", "SMA20/current","RSI","MACD","BBANDS+2σ","BBANDS-2σ"]],df_xy["Le ratio de la veille_classified"], train_size=0.8)
def objective(trial):
min_samples_split = trial.suggest_int("min_samples_split", 2,16)
max_leaf_nodes = int(trial.suggest_discrete_uniform("max_leaf_nodes", 4,64,4))
criterion = trial.suggest_categorical("criterion", ["gini", "entropy"])
n_estimators = int(trial.suggest_discrete_uniform("n_estimators", 50,500,50))
max_depth = trial.suggest_int("max_depth", 3,10)
clf = RandomForestClassifier(random_state=1, n_estimators = n_estimators, max_leaf_nodes = max_leaf_nodes, max_depth=max_depth, max_features=None,criterion=criterion,min_samples_split=min_samples_split)
clf.fit(X_train, Y_train)
return 1 - accuracy_score(Y_test, clf.predict(X_test))
study = optuna.create_study()
study.optimize(objective, n_trials=100)
print(1-study.best_value)
print(study.best_params)
La précision lorsque les hyper paramètres sont optimisés est
0.6335025380710659 Puisqu'il s'agit d'une classification à trois valeurs, je pense que c'est un assez bon résultat. C'est environ deux fois plus bon que lorsque vous le sélectionnez au hasard.
Si le mouvement des prix est prédit avec 60% de chances, la valeur attendue sera positive même si vous considérez le spread!
Considérez une matrice de confusion de classification multiclasse!
Afin de réaliser un profit avec Fx, il est souhaitable que le rapport de ① et ⑨ soit élevé. En regardant la matrice de confusion, 1 + 9 = 48,9%, ce qui représente près de la moitié. En outre, ce que vous voulez éviter le plus, ce sont les modèles ③ et ⑦ (le modèle que vous aviez prévu d'augmenter mais qui a en fait diminué, et le modèle que vous avez prévu de diminuer mais qui a augmenté). Ces deux valeurs sont assez faibles de ③ + ⑦ = 7,3%.
** À partir des considérations ci-dessus, nous pouvons voir que le modèle appris cette fois peut être rentable. ** **
De plus, l'hyper paramètre lorsque la précision est maximisée est
{'min_samples_split': 8,
'max_leaf_nodes': 40.0,
'criterion': 'entropy',
'n_estimators': 310.0,
'max_depth': 7}
était. La relation entre les hyperparamètres et la précision est la suivante.
(* Notez que subjectif_value = 1 --accuracy! (Spécifications Optuna))
La couleur plus claire de la figure ci-dessus est la plus grande précision. Certes, on peut lire que max_depth est d'environ 7, max_leaf_nodes est d'environ 30 à 40 et n_estimators est d'environ 300.
Jusqu'à présent, nous avons classé trois valeurs, mais classons-les en deux valeurs, augmentation ou diminution du taux.
Ne modifiez que 3. la fonction de classification pour la création des données des enseignants.
def classify(x):
if x <= 0:
return 0
else:
return 1
Si vous construisez un modèle de la même manière et optimisez les hyper paramètres avec optuna ...
accuracy=0.7766497461928934
** Je suis aussi très riche avec ça (yeux blancs)! ** **
De cette façon, il peut être intéressant non seulement de changer la méthode de division des données, mais aussi de jouer avec les indicateurs techniques utilisés!
Recommended Posts