[PYTHON] [Apprentissage automatique] Prédiction FX à l'aide de l'arbre de décision

Apprentissage automatique et FX

Bonjour. C'est la première fois que je publie un article décent sur Qiita. Récemment, j'ai commencé à étudier l'apprentissage automatique. Il va sans dire que l'apprentissage automatique est utilisé dans de nombreux endroits. Filtrage des spams, recommandations de produits, etc ... Les exemples sont infinis. Même ainsi, je souhaitais prédire les cours des actions et les devises à l'aide de l'apprentissage automatique, donc aujourd'hui Je voudrais prédire FX en utilisant l'arbre __decision, qui est l'un de l'apprentissage automatique. Si vous pouvez prédire les cours des actions et les devises avec une bonne précision, vous pouvez gagner de l'argent sans rien faire, c'est donc une histoire très rêveuse. Cependant, en réalité, ce n'est pas si doux que cela puisse être facilement prédit, donc la motivation principale est d'appliquer l'apprentissage automatique que j'ai récemment étudié à quelque chose plutôt que de gagner ou de faire un profit. Alors tout d'abord, si vous lisez cet article __ "Je me fiche de l'apprentissage automatique, alors prévoyez les effets de change avec l'IA et dites-moi si le yen dollar de demain augmentera ou diminuera!" Il n'y a aucune information utile pour ceux qui disent. Pour ceux qui s'intéressent à l'apprentissage automatique et à la prédiction FX, cela peut être un peu amusant. C'est à peu près ça.

Qu'est-ce que FX?

Dans le cas des actions, nous savons tous que si vous achetez des actions et que le cours de l'action augmente, vous ferez un profit, et si le cours de l'action baisse, vous perdrez. Certaines personnes ne connaissent peut-être pas FX, donc je vais vous l'expliquer pour le moment. Par exemple, disons que vous négociez pour 100 yens par dollar. Disons que vous passez une commande «d'achat» de 1 $ dans cet état. Demain ce dollar

C'est vrai. Ce type de transaction d'échange s'appelle FX. Dans le cas du FX, vous pouvez appliquer un effet de levier, donc si vous multipliez l'effet de levier par 10, vous pouvez déplacer 10 fois plus d'argent. Dans ce cas, le profit est de 10 fois et la perte de 10 fois, alors soyez prudent. Dans le cas des transactions dollar-yen, on parle de dollar-yen. Si la valeur du dollar augmente comme 100 yens pour un dollar -> 110 yens, le dollar se raffermira (yen faible), et inversement si la valeur du dollar chute comme 100 yens pour un dollar -> 90 yens, le dollar s'affaiblira (yen fort). Ce sera. Je n'expliquerai plus le FX car il y a tellement de livres et de sites qui expliquent le FX d'une manière facile à comprendre, mais le fait est que vous pouvez faire un profit si vous pouvez prédire s'il augmentera ou baissera comme les actions __ à propos de ça.

Site référencé

J'ai fait référence à ici. Une explication détaillée de l'arbre de décision est également publiée ici, je ne l'expliquerai donc pas en détail dans cet article. En un mot, l'arbre de décision ne nécessite pas le travail de mise à l'échelle des quantités de caractéristiques appelées standardisation, et il est facile d'interpréter le processus dans lequel le résultat a été obtenu (c'est-à-dire l'interprétabilité). il y a. Voici un bref résumé de ce qui se passe sur la page liée.

C'est comme ça. La précision de la prédiction n'est pas si élevée car le but principal est de présenter comment appliquer l'apprentissage automatique (arbre de décision) au FX plutôt que de prévoir sérieusement.

Que voulez-vous faire sur cette page

C'est un endroit comme ça. En ce qui concerne l'augmentation des caractéristiques, nous avons appris des centaines de jours de données sur la page ci-dessus, mais nous utilisons le "prix ouvert", le "prix de clôture", le "prix élevé" et le "prix bas" comme caractéristiques lors de la prévision. Il n'y en a que quatre. En d'autres termes, au moment de décider si le yen dollar de demain augmentera ou baissera, il n'est décidé que par le chandelier du «jour». Cependant, lorsque les traders prennent réellement des décisions, ils utilisent souvent divers indicateurs techniques tels que les moyennes mobiles (valeurs moyennes des n derniers jours), les bandes de Bollinger et les MACD. Donc, cette fois, en plus des quatre qualités ci-dessus, __ "Moyenne et variance des cours de clôture sur 5, 25, 50 et 75 jours" , __ "Prix d'ouverture, de clôture et prix élevés sur les 3 derniers jours" , Prix bas " etc. Je voudrais ajouter du nouveau. Ces valeurs sont liées aux indicateurs techniques mentionnés précédemment. Vous ne savez pas de quoi vous parlez? Lors de la prédiction du yen dollar de demain, il est préférable de se référer non seulement aux mouvements de prix d'aujourd'hui, mais aussi aux valeurs moyennes des derniers jours à quelques semaines et à combien elles ont fluctué, n'est-ce pas? C'est. Pour le mettre dans une analogie très déroutante "Le riz d'aujourd'hui était du riz au curry préparé par ma mère. D'après les tendances passées, le riz du lendemain après le riz au curry sera probablement un hamburger, alors demain sera un hamburger!" Est la méthode que nous faisons ci-dessus. Ce que je veux faire "Le riz d'aujourd'hui était du curry et du riz. Hier c'était de la viande, mais la semaine dernière, il y avait beaucoup de nourriture chinoise. Je suppose que d'après le menu d'aujourd'hui et les tendances des dernières semaines ... demain, c'est le hamburger!" Je me sens comme. C'est difficile à comprendre.

Essayez de mettre en œuvre avec jupyter

Préparation

Tout comme la page ci-dessus, jupyter utilise Python pour gribouiller. La page est presque la même que la page présentée ci-dessus, mais je vais le faire dans l'ordre. Tout d'abord, importez diverses bibliothèques requises.

import pandas as pd
import numpy as np 
#Bibliothèque de visualisation de données
import matplotlib.pyplot as plt
#Bibliothèque d'apprentissage automatique
from sklearn.tree import DecisionTreeClassifier
from sklearn import tree
from sklearn.metrics import confusion_matrix
from sklearn.metrics import accuracy_score
#importer graphviz
import graphviz
#Pour la recherche de grille et la validation croisée
from sklearn.model_selection import cross_val_score
from sklearn.model_selection import GridSearchCV

Les deux derniers sont nécessaires lors de la recherche de grille et de la vérification des intersections. Chargez ensuite les données. Cette fois, nous avons préparé des données csv pour 2 ans de 2017 à 2019. Je négocie avec un logiciel appelé MT4, et j'y ai apporté les données fournies au format csv.

#Lisez le fichier CSV. 2017-2 ans de 2019
df = pd.read_csv('usd_jpy_api_2017_2019.csv')
#Vérifiez les 5 dernières lignes
df.tail()

Les 5 premières lignes ressemblent à ceci. Il représente le temps, le prix de clôture, le prix d'ouverture, le prix élevé, le prix bas et le volume de négociation de chaque transaction. スクリーンショット 2020-01-04 15.28.06.png

Étant donné que le travail jusqu'à présent est la page présentée ci-dessus, je vais l'ignorer grossièrement, mais je donnerai l'étiquette de réponse correcte avec 0, 1 selon que le cours de clôture du dernier jour augmentera.

#Cours de clôture le jour suivant-Calculez la différence au cours de clôture du jour
#shift(-1)Rapprochez-vous d'un
df['close+1'] = df.close.shift(-1)
df['diff'] = df['close+1'] - df['close']
#Fermer le dernier jour+1 devient NaN, alors coupez-le
df = df[:-1]

Vérifions le rapport entre les données en hausse et en baisse.

#Vérifiez le rapport de données de montée et de descente
m = len(df['close'])
#df['diff']>0 renvoie vrai ou faux pour toutes les lignes. df[(df['diff'] > 0)]Avec dff>Sortie de toutes les colonnes en réduisant à 0
print(len(df[(df['diff'] > 0)]) / m * 100)
print(len(df[(df['diff'] < 0)]) / m * 100)
52.16284987277354
47.837150127226465

Il y a plusieurs jours où il a légèrement augmenté. Supprimez ensuite les colonnes indésirables et nommez la cible de l'étiquette.

df.rename(columns={"diff" : "target"}, inplace=True)
#Supprimer les colonnes inutiles
del df['close+1']
del df['time']
#Tri des colonnes
df = df[['target', 'volume', 'open', 'high', 'low', 'close']]
#Sortez les 5 premières lignes
df.head()
スクリーンショット 2020-01-04 15.38.30.png

Ajout d'identité

À partir de là, nous calculerons les nouvelles fonctionnalités et les ajouterons.

#Calcul de la moyenne mobile, 5 jours, 25 jours, 50 jours, 75 jours
#Calculez également std. (=A les mêmes informations que le groupe de Bollinger)
#Données sécurisées pendant 75 jours
for i in range(1, 75):
    df['close-'+str(i)] = df.close.shift(+i)
#Calculer la valeur moyenne mobile et std,S'il y a même un Nan dans le réglage skipna, il retournera Nan.
nclose = 5    
df['MA5'] = df.iloc[:, np.arange(nclose, nclose+5)].mean(axis='columns', skipna=False)
df['MA25'] = df.iloc[:, np.arange(nclose, nclose+25)].mean(axis='columns', skipna=False)
df['MA50'] = df.iloc[:, np.arange(nclose, nclose+50)].mean(axis='columns', skipna=False)
df['MA75'] = df.iloc[:, np.arange(nclose, nclose+75)].mean(axis='columns', skipna=False)

df['STD5'] = df.iloc[:, np.arange(nclose, nclose+5)].std(axis='columns', skipna=False)
df['STD25'] = df.iloc[:, np.arange(nclose, nclose+25)].std(axis='columns', skipna=False)
df['STD50'] = df.iloc[:, np.arange(nclose, nclose+50)].std(axis='columns', skipna=False)
df['STD75'] = df.iloc[:, np.arange(nclose, nclose+75)].std(axis='columns', skipna=False)
#Supprimer les colonnes supplémentaires après le calcul
for i in range(1, 75):
    del df['close-'+str(i)]
#Changements par rapport au jour précédent de chaque ligne moyenne (vous pouvez voir si la ligne moyenne mobile est à la hausse ou à la baisse)
#shift(-1)Rapprochez-vous d'un
df['diff_MA5'] = df['MA5'] - df.MA5.shift(1) 
df['diff_MA25'] = df['MA25'] - df.MA25.shift(1) 
df['diff_MA50'] = df['MA50'] - df.MA50.shift(1) 
df['diff_MA75'] = df['MA50'] - df.MA50.shift(1) 
#Ouvert il y a jusqu'à 3 jours, close, high,Je veux ajouter du bas à mon identité
for i in range(1, 4):
    df['close-'+str(i)] = df.close.shift(+i)
    df['open-'+str(i)] = df.open.shift(+i)
    df['high-'+str(i)] = df.high.shift(+i)
    df['low-'+str(i)] = df.low.shift(+i)
#Supprimer la ligne contenant NaN
df = df.dropna()
#Décidez du nombre de jours à utiliser
nday = 500
df = df[-nday:]
#df.head()
df
スクリーンショット 2020-01-04 15.41.59.png

Le côté droit est coupé, mais il ressemble à ceci.

--MA est la moyenne mobile. Par exemple, MA5 est le cours de clôture moyen des 5 derniers jours à compter de cette date. --close-n représente le cours de clôture il y a n jours (idem pour open, high et low) --STD est l'écart type ――Je voulais savoir si la moyenne mobile pointe vers le haut ou vers le bas, j'ai donc ajouté le changement par rapport à la veille avec le nom diff_.

Pour le moment, j'ai choisi les données pour 500 jours. Il était correct de le spécifier lors de la première lecture des données, mais lors du calcul de la moyenne sur 75 jours, des données remontant à 75 jours sont nécessaires, donc 500 jours de données seront utilisés une fois le calcul terminé. J'utilise. Vous disposez désormais de 500 lignes et 30 colonnes de données.

Apprendre l'arbre de décision

Maintenant que nous sommes prêts, divisons-le en train, testons-le et évaluons-le.

n = df.shape[0]
p = df.shape[1]
print(n,p)
#Divisé en données d'entraînement et données de test. Ne pas mélanger
train_start = 0
train_end = int(np.floor(0.8*n))
test_start = train_end + 1
test_end = n
data_train = np.arange(train_start, train_end)
data_train = df.iloc[np.arange(train_start, train_end), :]
data_test = df.iloc[np.arange(test_start, test_end), :]
#Vérifiez la taille des données d'entraînement et des données de test
print(data_train.shape)
print(data_test.shape)

Cette fois, il a été divisé à 8: 2.


(400, 30)
(99, 30)

Ensuite, la partie de l'étiquette de réponse correcte est séparée et l'apprentissage est effectué avec l'arbre de décision. L'hyper paramètre max_depth, qui indique la profondeur de l'arbre, est mis à 5 pour le moment, mais la valeur appropriée sera déterminée par la recherche de grille après cela.

#Cible séparée
X_train = data_train.iloc[:, 1:]
y_train = data_train.iloc[:, 0]
X_test = data_test.iloc[:, 1:]
y_test = data_test.iloc[:, 0]
#Formation du modèle technique décisif
clf_2 = DecisionTreeClassifier(max_depth=5)

L'arbre de décision est enfin sorti. Effectuez une validation croisée et une recherche dans la grille avec k = 10.


#max avec recherche de grille_Déterminez les paramètres optimaux pour la profondeur
#k=Effectuer également la vérification des intersections de division 10 k
params = {'max_depth': [2, 5, 10, 20]}

grid = GridSearchCV(estimator=clf_2,
                    param_grid=params,
                    cv=10,
                    scoring='roc_auc')
grid.fit(X_train, y_train)
for r, _ in enumerate(grid.cv_results_['mean_test_score']):
    print("%0.3f +/- %0.2f %r"
          % (grid.cv_results_['mean_test_score'][r],
             grid.cv_results_['std_test_score'][r] / 2.0,
             grid.cv_results_['params'][r]))
print('Best parameters: %s' % grid.best_params_)
print('Accuracy: %.2f' % grid.best_score_)

La sortie ressemble à ceci. Lorsque la profondeur est de 10, le taux de réponse correct est le plus élevé, soit 69%.

0.630 +/- 0.05 {'max_depth': 2}
0.679 +/- 0.06 {'max_depth': 5}
0.690 +/- 0.06 {'max_depth': 10}
0.665 +/- 0.05 {'max_depth': 20}
Best parameters: {'max_depth': 10}
Accuracy: 0.69

Évaluation avec données de test

Le taux de réponse correct indiqué ci-dessus est simplement le taux de réponse correct dans les données d'entraînement, alors essayons de prédire les données de test.

#Apprenez à utiliser les paramètres les mieux adaptés à la recherche de grille
clf_2 = grid.best_estimator_
clf_2 = clf_2.fit(X_train, y_train)
clf_2

Vous pouvez voir que les paramètres sont définis comme ceci.

DecisionTreeClassifier(class_weight=None, criterion='gini', max_depth=10,
                       max_features=None, max_leaf_nodes=None,
                       min_impurity_decrease=0.0, min_impurity_split=None,
                       min_samples_leaf=1, min_samples_split=2,
                       min_weight_fraction_leaf=0.0, presort=False,
                       random_state=None, splitter='best')

Visualisons-le car c'est un gros problème. Puisque max_depth = 10, ce sera un gâchis. .. Si vous ne découpez que la partie supérieure, cela ressemble à ceci. Dans ce cas, on peut voir que le prix haut il y a trois jours est divisé selon qu'il est de 82,068 ou plus ou moins, puis le seuil est déterminé par le prix bas du jour et divisé. Le fait qu'il soit acheté sous forme de gini signifie que la division est effectuée de sorte que la valeur de la pureté de gini devient petite. La valeur = part indique le nombre de montées et de descentes.

スクリーンショット 2020-01-04 16.01.03.png

Vérifions le taux de réponse correct du test.

pred_test_2 = clf_2.predict(X_test)
#Taux d'exactitude des données de test
accuracy_score(y_test, pred_test_2)
0.555555555555

Hmm. .. C'est comme ... pour tout le travail acharné, mais c'est comme ça. Voyons également quelles fonctionnalités sont importantes (impotance des fonctionnalités).

#Afficher des qualités importantes
importances = clf_2.feature_importances_
indices = np.argsort(importances)[::-1]

for f in range(X_train.shape[1]):
    print("%2d) %-*s %f" % (f + 1, 30, 
                            df.columns[1+indices[f]],
                            importances[indices[f]]))    

J'ai essayé de calculer la moyenne mobile et ainsi de suite, mais au final, il semble que le mouvement des prix la veille ou la veille soit important.

 1) low                            0.407248
 2) close                          0.184738
 3) low-1                          0.078743
 4) high-3                         0.069653
 5) high                           0.043982
 6) diff_MA5                       0.039119
 7) close-3                        0.035420
 8) STD50                          0.035032
 9) diff_MA25                      0.029473
10) MA75                           0.028125
11) MA50                           0.009830
12) open-3                         0.009540
13) STD25                          0.009159
14) low-3                          0.007632
15) high-1                         0.007632
16) volume                         0.004674
Puisqu'il est 0 ci-dessous, il est omis

Jouez avec différentes valeurs

Résumons à nouveau les conditions de cette vérification

--__ Période d'agrégation : 500 jours jusqu'au 31 décembre 2019 -- Classificateur : Arbre de décision -- paramètre _: max_depth = 10 -- Vérification d'intersection : 10 divisions -- Formation et test fractionné : 8: 2 -- Résultat __: Taux de réponse correcte 0,55 Ici, les paramètres de l'arbre de décision ont été décidés par la recherche de grille, donc j'ai pensé que c'était correct, mais j'ai essayé parce que la période d'agrégation et le rapport de division semblaient être falsifiés.

--_ Résultat de la modification du rapport de division à 9: __ → Taux de réponse correct: __ 61% __ (max_depth = 20) --__ Résultat d'une période totale de 200 jours __ → Taux de réponse correcte: __ 56% __ (max_depth = 10) est devenu. Le taux de réponse correcte est d'environ 50 à 60%. La recherche de grille est refaite à chaque fois que les conditions sont modifiées, mais environ max_depth = 10-20 était le meilleur score.

Ce que j'ai appris cette fois

――Si vous faites de votre mieux pour faire des prédictions basées sur les données quotidiennes du yen dollar, vous obtiendrez une précision d'environ 50 à 60%.

Ce que je veux faire dans le futur

C'est plus long que prévu. .. fin

Recommended Posts

[Apprentissage automatique] Prédiction FX à l'aide de l'arbre de décision
[Apprentissage automatique] Étudions l'arbre de décision
Machine Learning: Supervisé - Arbre de décision
Prédiction de survie Titanic à l'aide de l'outil de gestion du flux de travail d'apprentissage automatique Kedro
[Apprentissage automatique] Comprendre les arbres de décision de scikit-learn et des mathématiques
Apprentissage automatique ③ Résumé de l'arbre de décision
Développement d'applications à l'aide d'Azure Machine Learning
Apprentissage automatique
[Apprentissage automatique] Classification des sujets LDA à l'aide de scikit-learn
[Apprentissage automatique] Apprentissage supervisé utilisant l'estimation de la densité du noyau
Prévision du cours des actions à l'aide de l'apprentissage automatique (édition de retour)
[Apprentissage automatique] Analyse de régression à l'aide de scicit learn
Une histoire sur l'apprentissage automatique simple avec TensorFlow
Astuces de fourniture de données utilisant deque dans l'apprentissage automatique
[Apprentissage automatique] Apprentissage supervisé utilisant l'estimation de la densité du noyau Partie 2
[Apprentissage automatique] Apprentissage supervisé utilisant l'estimation de la densité du noyau Partie 3
Jusqu'au lancement d'un site de triple prédiction de course de bateaux utilisant l'apprentissage automatique et Flask
Division des données de formation en apprentissage automatique et apprentissage / prédiction / vérification
J'ai essayé d'implémenter diverses méthodes d'apprentissage automatique (modèle de prédiction) en utilisant scicit-learn
[Memo] Apprentissage automatique
Classification de l'apprentissage automatique
Essayez d'utiliser le bloc-notes Jupyter à partir d'Azure Machine Learning
Exemple d'apprentissage automatique
[Apprentissage automatique] Extraire des mots similaires mécaniquement en utilisant WordNet
Raisonnement causal utilisant l'apprentissage automatique (organisation des méthodes de raisonnement causal)
Ce que j'ai appris sur l'IA / l'apprentissage automatique avec Python (1)
Créez des projets d'apprentissage automatique à une vitesse explosive à l'aide de modèles
Essayez de prédire le taux de change (FX) avec un apprentissage automatique non approfondi
Ce que j'ai appris sur l'IA / l'apprentissage automatique avec Python (3)
Apprentissage automatique avec des images de catégorie Caffe -1 à l'aide du modèle de référence
Les débutants en apprentissage automatique essaient de créer un arbre de décision
Prédiction de données chronologiques par AutoML (apprentissage automatique automatique)
Tech-Circle Commençons le développement d'applications à l'aide de l'apprentissage automatique (auto-apprentissage)
[Apprentissage automatique] Essayez de détecter des objets à l'aide de la recherche sélective
[Apprentissage automatique] Classification de texte à l'aide du modèle Transformer (classificateur basé sur l'attention)
Mémo de construction d'environnement d'apprentissage automatique par Python
Ce que j'ai appris sur l'IA / l'apprentissage automatique avec Python (2)
J'ai essayé de compresser l'image en utilisant l'apprentissage automatique
Résumé du didacticiel d'apprentissage automatique
Apprentissage automatique ⑤ Résumé AdaBoost
Apprentissage automatique: supervisé - AdaBoost
Machine de vecteur de support d'apprentissage automatique
Étudier l'apprentissage automatique ~ matplotlib ~
Régression linéaire d'apprentissage automatique
Mémo du cours d'apprentissage automatique
Bibliothèque d'apprentissage automatique dlib
Apprentissage automatique (TensorFlow) + Lotto 6
Apprenez en quelque sorte le machine learning
Bibliothèque d'apprentissage automatique Shogun
Défi de lapin d'apprentissage automatique
Introduction à l'apprentissage automatique
Apprentissage automatique: k-voisins les plus proches
Qu'est-ce que l'apprentissage automatique?
Les débutants en Python publient des applications Web à l'aide de l'apprentissage automatique [Partie 1] Introduction
Prédiction des ondes sinusoïdales à l'aide de RNN dans la bibliothèque d'apprentissage en profondeur Keras
Ce que j'ai appris sur l'IA / l'apprentissage automatique avec Python (4)
Lancement d'un environnement d'apprentissage automatique à l'aide de Google Compute Engine (GCE)
J'ai essayé d'utiliser Tensorboard, un outil de visualisation pour l'apprentissage automatique
[Apprentissage automatique] Sélection de fonctionnalités de variables catégorielles à l'aide du test du chi carré