Optimisation des paramètres du système FX en Python J'ai donc essayé toutes les combinaisons de paramètres du système commercial pour trouver la solution optimale.
Si le nombre de combinaisons est petit, il n'y a pas de problème avec le round robin, mais si le nombre de combinaisons est grand, cela devient assez difficile. L'algorithme d'optimisation pour cela est [Metahuristics](https://ja.wikipedia.org/wiki/%E3%83%A1%E3%82%BF%E3%83%92%E3%83%A5% E3% 83% BC% E3% 83% AA% E3% 82% B9% E3% 83% 86% E3% 82% A3% E3% 82% AF% E3% 82% B9). Je voulais implémenter un algorithme génétique bien connu, mais avant cela, j'ai écrit une recherche aléatoire plus simple en Python.
Mettez la fonction pour convertir les données d'une minute en une autre période et la fonction d'index technique dans indicateurs.py, et le backtest précédent et la fonction pour l'évaluer dans backtest.py. La source peut être trouvée sur GitHub. Le code suivant créera des données d'une heure dans ʻohlc`.
import numpy as np
import pandas as pd
import indicators as ind #indicators.Importation de py
from backtest import Backtest,BacktestReport
dataM1 = pd.read_csv('DAT_ASCII_EURUSD_M1_2015.csv', sep=';',
names=('Time','Open','High','Low','Close', ''),
index_col='Time', parse_dates=True)
dataM1.index += pd.offsets.Hour(7) #Décalage de 7 heures
ohlc = ind.TF_ohlc(dataM1, 'H') #Création de données horaires
Dans l'optimisation précédente, nous avons optimisé en modifiant deux paramètres dans une certaine plage comme suit.
SlowMAperiod = np.arange(10, 61) #Gamme de période moyenne mobile à long terme
FastMAperiod = np.arange(5, 31) #Gamme de période moyenne mobile à court terme
À ce rythme, il n'y a que 1066 façons, mais je changerai le nombre de combinaisons plus tard.
Dans une recherche aléatoire simple, les valeurs des paramètres doivent être générées aléatoirement dans l'ordre et celle avec l'évaluation de backtest la plus élevée doit être adoptée, mais ici, une fois afin qu'elle puisse être appliquée aux algorithmes génétiques. J'ai essayé environ 20 combinaisons de paramètres dans chaque génération et essayé de le répéter pendant plusieurs générations.
def Optimize(ohlc, SlowMAperiod, FastMAperiod):
def shift(x, n=1): return np.concatenate((np.zeros(n), x[:-n])) #Fonction Shift
SlowMA = np.empty([len(SlowMAperiod), len(ohlc)]) #Moyenne mobile à long terme
for i in range(len(SlowMAperiod)):
SlowMA[i] = ind.iMA(ohlc, SlowMAperiod[i])
FastMA = np.empty([len(FastMAperiod), len(ohlc)]) #Moyenne mobile à court terme
for i in range(len(FastMAperiod)):
FastMA[i] = ind.iMA(ohlc, FastMAperiod[i])
M = 20 #Nombre d'individus
Eval = np.zeros([M, 6]) #Élément d'évaluation
Param = np.zeros([M, 2], dtype=int) #Paramètres
RandomSearch(Param, Eval[:,0], SlowMAperiod, FastMAperiod) #Initialisation des paramètres
gens = 0 #Nombre de générations
while gens < 100:
for k in range(M):
i = Param[k,0]
j = Param[k,1]
#Acheter le signal d'entrée
BuyEntry = (FastMA[j] > SlowMA[i]) & (shift(FastMA[j]) <= shift(SlowMA[i]))
#Vendre un signal d'entrée
SellEntry = (FastMA[j] < SlowMA[i]) & (shift(FastMA[j]) >= shift(SlowMA[i]))
#Acheter un signal de sortie
BuyExit = SellEntry.copy()
#Vendre un signal de sortie
SellExit = BuyEntry.copy()
#Backtest
Trade, PL = Backtest(ohlc, BuyEntry, SellEntry, BuyExit, SellExit)
Eval[k] = BacktestReport(Trade, PL)
#Changement de génération
Param = RandomSearch(Param, Eval[:,0], SlowMAperiod, FastMAperiod)
gens += 1
Slow = SlowMAperiod[Param[:,0]]
Fast = FastMAperiod[Param[:,1]]
return pd.DataFrame({'Slow':Slow, 'Fast':Fast, 'Profit': Eval[:,0], 'Trades':Eval[:,1],
'Average':Eval[:,2],'PF':Eval[:,3], 'MDD':Eval[:,4], 'RF':Eval[:,5]},
columns=['Slow','Fast','Profit','Trades','Average','PF','MDD','RF'])
La différence avec la dernière fois est que nous avons préparé un tableau «Param» pour stocker la combinaison de paramètres pour chaque génération. Ensuite, l'ensemble de paramètres avec la valeur d'évaluation la plus élevée (profit / perte total dans ce cas) est sauvegardé (sauvegarde élite) pour chaque génération, et les paramètres restants sont générés de manière aléatoire à plusieurs reprises.
Une fonction qui génère de manière aléatoire des paramètres avec un stockage élite peut être écrite comme suit:
#Recherche aléatoire avec sauvegarde élite
def RandomSearch(Param, Eval, SlowMAperiod, FastMAperiod):
Param = Param[np.argsort(Eval)[::-1]] #Trier
NewParam = np.vstack((np.random.randint(len(SlowMAperiod), size=len(Eval)),
np.random.randint(len(FastMAperiod), size=len(Eval)))).T
NewParam[0] = Param[0] #Sauvegarde élite
return NewParam
La méthode consiste à trier les valeurs d'évaluation et à redéfinir le paramètre 0. Lorsque vous faites cela, vous obtenez:
result = Optimize(ohlc, SlowMAperiod, FastMAperiod)
result.sort_values('Profit', ascending=False)
Slow | Fast | Profit | Trades | Average | PF | MDD | RF | |
---|---|---|---|---|---|---|---|---|
0 | 27 | 8 | 2507.1 | 264.0 | 9.496591 | 1.423497 | 485.1 | 5.168213 |
15 | 18 | 5 | 944.1 | 428.0 | 2.205841 | 1.110187 | 693.1 | 1.362141 |
19 | 48 | 14 | 825.4 | 238.0 | 3.468067 | 1.131883 | 927.7 | 0.889727 |
16 | 42 | 29 | 720.4 | 308.0 | 2.338961 | 1.094974 | 1011.8 | 0.711998 |
8 | 44 | 25 | 589.3 | 246.0 | 2.395528 | 1.089205 | 1141.1 | 0.516432 |
6 | 60 | 25 | 588.8 | 120.0 | 4.906667 | 1.126946 | 1025.0 | 0.574439 |
4 | 22 | 5 | 493.5 | 124.0 | 3.979839 | 1.105354 | 1106.3 | 0.446082 |
11 | 26 | 7 | 391.2 | 206.0 | 1.899029 | 1.069326 | 1099.8 | 0.355701 |
17 | 13 | 7 | 343.2 | 152.0 | 2.257895 | 1.069697 | 990.9 | 0.346352 |
18 | 45 | 20 | 174.5 | 160.0 | 1.090625 | 1.032210 | 1118.4 | 0.156026 |
12 | 38 | 20 | 169.8 | 170.0 | 0.998824 | 1.029754 | 939.8 | 0.180677 |
3 | 21 | 11 | 148.6 | 460.0 | 0.323043 | 1.016830 | 1203.1 | 0.123514 |
5 | 34 | 13 | -342.0 | 170.0 | -2.011765 | 0.939258 | 1160.8 | -0.294624 |
7 | 42 | 22 | -374.4 | 156.0 | -2.400000 | 0.933744 | 1189.6 | -0.314728 |
1 | 51 | 20 | -441.4 | 160.0 | -2.758750 | 0.922788 | 1089.9 | -0.404991 |
9 | 58 | 27 | -1485.5 | 222.0 | -6.691441 | 0.787506 | 2394.0 | -0.620510 |
10 | 19 | 25 | -1620.0 | 234.0 | -6.923077 | 0.775828 | 1845.7 | -0.877716 |
13 | 33 | 16 | -1625.0 | 400.0 | -4.062500 | 0.827957 | 2307.7 | -0.704164 |
2 | 44 | 24 | -1885.7 | 508.0 | -3.712008 | 0.828287 | 2652.2 | -0.710995 |
14 | 55 | 12 | -2048.3 | 398.0 | -5.146482 | 0.776908 | 2813.6 | -0.728000 |
De cette manière, la solution optimale a été recherchée, mais elle est naturelle car nous avons essayé 20 individus pendant 100 générations, soit près de 2000 fois.
Puisqu'il n'y a que deux paramètres cette fois, le nombre de combinaisons n'augmente pas tellement,
SlowMAperiod = np.arange(10, 161) #Gamme de période moyenne mobile à long terme
FastMAperiod = np.arange(5, 131) #Gamme de période moyenne mobile à court terme
Augmentons-le à 19 026 façons comme ça. Le résultat est
Slow | Fast | Profit | Trades | Average | PF | MDD | RF | |
---|---|---|---|---|---|---|---|---|
0 | 52 | 48 | 2003.4 | 190.0 | 10.544211 | 1.426773 | 1106.4 | 1.810738 |
5 | 125 | 26 | 1312.6 | 58.0 | 22.631034 | 1.513939 | 896.4 | 1.464302 |
16 | 49 | 47 | 1203.9 | 62.0 | 19.417742 | 1.448046 | 773.0 | 1.557439 |
11 | 56 | 55 | 989.6 | 116.0 | 8.531034 | 1.245266 | 922.0 | 1.073319 |
14 | 52 | 34 | 704.0 | 62.0 | 11.354839 | 1.261632 | 527.2 | 1.335357 |
13 | 152 | 36 | 545.5 | 75.0 | 7.273333 | 1.133198 | 936.5 | 0.582488 |
2 | 140 | 58 | 457.4 | 196.0 | 2.333673 | 1.085960 | 867.1 | 0.527505 |
18 | 40 | 109 | 308.1 | 88.0 | 3.501136 | 1.073977 | 1435.0 | 0.214704 |
6 | 75 | 107 | 255.1 | 78.0 | 3.270513 | 1.066815 | 1145.1 | 0.222775 |
3 | 158 | 85 | 172.7 | 122.0 | 1.415574 | 1.036899 | 1530.6 | 0.112832 |
12 | 68 | 32 | -622.3 | 90.0 | -6.914444 | 0.836838 | 1629.9 | -0.381803 |
10 | 120 | 111 | -638.0 | 37.0 | -17.243243 | 0.787057 | 1233.4 | -0.517269 |
8 | 153 | 30 | -667.3 | 35.0 | -19.065714 | 0.776284 | 1558.8 | -0.428086 |
7 | 43 | 74 | -749.0 | 39.0 | -19.205128 | 0.770245 | 1766.8 | -0.423930 |
15 | 63 | 104 | -774.3 | 92.0 | -8.416304 | 0.835339 | 1692.6 | -0.457462 |
9 | 154 | 56 | -1296.9 | 58.0 | -22.360345 | 0.675945 | 1733.3 | -0.748226 |
1 | 152 | 24 | -1315.2 | 74.0 | -17.772973 | 0.664627 | 2130.3 | -0.617378 |
19 | 155 | 27 | -1363.8 | 60.0 | -22.730000 | 0.672006 | 1474.4 | -0.924986 |
17 | 109 | 40 | -1478.5 | 62.0 | -23.846774 | 0.651379 | 1784.5 | -0.828523 |
4 | 148 | 122 | -1957.4 | 100.0 | -19.574000 | 0.626400 | 2171.4 | -0.901446 |
Recommended Posts