[Python] Versuchen Sie, die FX-Systolenparameter durch zufällige Suche zu optimieren

FX Systre Parameteroptimierung in Python Also habe ich alle Parameterkombinationen des Handelssystems ausprobiert, um die optimale Lösung zu finden.

Wenn die Anzahl der Kombinationen klein ist, gibt es kein Problem mit Round-Robin, aber wenn die Anzahl der Kombinationen groß ist, wird es ziemlich schwierig. Der Optimierungsalgorithmus dafür ist [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). Ich wollte einen bekannten genetischen Algorithmus implementieren, habe aber vorher eine einfachere Zufallssuche in Python geschrieben.

Vorbereitung

Setzen Sie die Funktion zum Konvertieren von 1-Minuten-Daten in einen anderen Zeitrahmen und die technische Indexfunktion in Indikatoren.py sowie den vorherigen Backtest und die Funktion zum Auswerten in backtest.py. Die Quelle finden Sie unter GitHub. Der folgende Code erstellt 1-Stunden-Daten in ohlc.

import numpy as np
import pandas as pd
import indicators as ind #indicators.Import von 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) #7 Stunden Offset
ohlc = ind.TF_ohlc(dataM1, 'H') #Erstellung von Stundendaten

Handelssystemparameter zur Optimierung

In der vorherigen Optimierung haben wir optimiert, indem wir zwei Parameter innerhalb eines bestimmten Bereichs wie folgt geändert haben.

SlowMAperiod = np.arange(10, 61) #Bereich der langfristigen gleitenden Durchschnittsperiode
FastMAperiod = np.arange(5, 31)  #Bereich des kurzfristigen gleitenden Durchschnittszeitraums

Bei dieser Rate gibt es nur 1066 Möglichkeiten, aber ich werde die Anzahl der Kombinationen später ändern.

Zufällige Suche

Bei einer einfachen Zufallssuche sollten Parameterwerte nacheinander zufällig generiert und derjenige mit der höchsten Backtest-Bewertung übernommen werden, hier jedoch einmal, damit er auf genetische Algorithmen angewendet werden kann. Ich habe ungefähr 20 Parameterkombinationen in jeder Generation ausprobiert und versucht, sie für mehrere Generationen zu wiederholen.

def Optimize(ohlc, SlowMAperiod, FastMAperiod):
    def shift(x, n=1): return np.concatenate((np.zeros(n), x[:-n])) #Schaltfunktion

    SlowMA = np.empty([len(SlowMAperiod), len(ohlc)]) #Langfristiger gleitender Durchschnitt
    for i in range(len(SlowMAperiod)):
        SlowMA[i] = ind.iMA(ohlc, SlowMAperiod[i])

    FastMA = np.empty([len(FastMAperiod), len(ohlc)]) #Kurzfristiger gleitender Durchschnitt
    for i in range(len(FastMAperiod)):
        FastMA[i] = ind.iMA(ohlc, FastMAperiod[i])
    
    M = 20 #Anzahl der Personen
    Eval = np.zeros([M, 6])  #Bewertungsgegenstand
    Param = np.zeros([M, 2], dtype=int) #Parameter
    RandomSearch(Param, Eval[:,0], SlowMAperiod, FastMAperiod) #Parameterinitialisierung
    gens = 0 #Anzahl der Generationen
    while gens < 100:
        for k in range(M):
            i = Param[k,0]
            j = Param[k,1]
            #Einstiegssignal kaufen
            BuyEntry = (FastMA[j] > SlowMA[i]) & (shift(FastMA[j]) <= shift(SlowMA[i]))
            #Eingangssignal verkaufen
            SellEntry = (FastMA[j] < SlowMA[i]) & (shift(FastMA[j]) >= shift(SlowMA[i]))
            #Ausgangssignal kaufen
            BuyExit = SellEntry.copy()
            #Ausgangssignal verkaufen
            SellExit = BuyEntry.copy()
            #Backtest
            Trade, PL = Backtest(ohlc, BuyEntry, SellEntry, BuyExit, SellExit) 
            Eval[k] = BacktestReport(Trade, PL)
        #Generationswechsel
        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'])

Der Unterschied zum letzten Mal besteht darin, dass wir ein Array "Param" vorbereitet haben, um die Kombination von Parametern für jede Generation zu speichern. Dann wird der Parametersatz mit dem größten Bewertungswert (in diesem Fall Gesamtgewinn / -verlust) für jede Generation gespeichert (Elite-Save), und die verbleibenden Parameter werden wiederholt zufällig generiert.

Eine Funktion, die zufällig Parameter mit Elite-Speicher generiert, kann wie folgt geschrieben werden:

#Zufällige Suche mit Elite Save
def RandomSearch(Param, Eval, SlowMAperiod, FastMAperiod):
    Param = Param[np.argsort(Eval)[::-1]] #Sortieren
    NewParam = np.vstack((np.random.randint(len(SlowMAperiod), size=len(Eval)),
                          np.random.randint(len(FastMAperiod), size=len(Eval)))).T
    NewParam[0] = Param[0] #Elite speichern
    return NewParam

Die Methode besteht darin, die Auswertungswerte zu sortieren und den 0. Parameter erneut einzustellen. Wenn Sie dies tun, erhalten Sie:

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

Auf diese Weise wurde nach der optimalen Lösung gesucht, aber es ist nur natürlich, dass 20 Personen seit 100 Generationen, dh fast 2000 Mal, vor Gericht gestellt wurden.

Da es diesmal nur zwei Parameter gibt, nimmt die Anzahl der Kombinationen nicht so stark zu,

SlowMAperiod = np.arange(10, 161) #Bereich der langfristigen gleitenden Durchschnittsperiode
FastMAperiod = np.arange(5, 131)  #Bereich des kurzfristigen gleitenden Durchschnittszeitraums

Erhöhen wir es auf 19.026 Möglichkeiten. Ergebnis ist

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
Daher konnte die optimale Lösung nicht gefunden werden. Wenn Sie dies jedoch mehrmals wiederholen, wird die optimale Lösung gefunden. Wenn die Kombination per Round-Robin verwaltet werden kann, ist es möglich, durch zufällige Suche eine vernünftige Lösung zu finden.

Recommended Posts

[Python] Versuchen Sie, die FX-Systolenparameter durch zufällige Suche zu optimieren
[Python] Versuchen Sie, die FX-Systolenparameter mit einem genetischen Algorithmus zu optimieren
Versuchen Sie es mit Python.
Sequentielle Suche mit Python
Dichotomie mit Python
Dichotomie mit Python 3
Probieren Sie die Python-Ausgabe mit Haxe 3.2 aus
Vollbit-Suche mit Python
Backtesting von FX Systre mit Python (2)
Versuchen Sie, Python mit Try Jupyter auszuführen
Suchmaschinen arbeiten mit Python
Suche nach Twitter-Tweets mit Python
Versuchen Sie die Gesichtserkennung mit Python
Optimieren Sie die Websuche mit Python
Versuchen Sie es mit Python + Beautiful Soup
Testen mit Zufallszahlen in Python
Versuchen Sie, Facebook mit Python zu betreiben
Zufallsgenerator für französische Zahlen mit Python
Versuchen Sie die Singularwertzerlegung mit Python
Versuchen Sie die Gesichtserkennung mit Python + OpenCV
Versuchen Sie die Frequenzsteuerungssimulation mit Python
Versuchen Sie, Farbfilme mit Python zu reproduzieren
Versuchen Sie, sich mit Python bei qiita anzumelden
Versuchen Sie eine Formel mit Σ mit Python
Versuchen Sie, mit Binärdaten in Python zu arbeiten
Durchsuche das Labyrinth mit dem Python A * -Algorithmus
Versuchen Sie, Python mit Google Cloud-Funktionen zu verwenden
Versuchen Sie HTML-Scraping mit der Python-Bibliothek
Versuchen Sie, Python von Ruby aus mit Sparsamkeit aufzurufen
Versuchen Sie, eine Karte mit Python + Cartopy 0.18.0 zu zeichnen
[Fortsetzung] Versuchen Sie den Zugriff auf das SPS-Register mit Python
Versuchen Sie, Python: Lambda zuzuweisen oder zu wechseln
[Für Anfänger] Versuchen Sie Web Scraping mit Python
Versuchen Sie Python
Versuchen Sie, FX mit LSTM mithilfe von Keras + Tensorflow Teil 3 vorherzusagen (versuchen Sie, alle Parameter zu treffen).
nginxparser: Versuchen Sie, die nginx-Konfigurationsdatei mit Python zu analysieren
CSV-Ausgabe der Google-Suche mit [Python]! 【Einfach】
Suchen und laden Sie YouTube-Videos automatisch mit Python herunter
Kausales Denken und kausale Suche von Python (für Anfänger)
Probieren Sie es mit Word Cloud Japanese Python JupyterLab.
Versuchen Sie, Google Chrome mit Python und Selenium auszuführen
Versuchen Sie, das Mensch-Maschine-Diagramm mit Python zu lösen
Versuchen Sie, mit Python eine Lebenskurve zu zeichnen
Versuchen Sie, in Python einen "Entschlüsselungs" -Code zu erstellen
Versuchen Sie, Python-Dokumente automatisch mit Sphinx zu generieren
Versuchen Sie, mit Mongo in Python auf dem Mac zu arbeiten
[Python3] [Ubuntu16] [Docker] Versuchen Sie die Gesichtserkennung mit OpenFace
Versuchen Sie, mit Python eine Diedergruppe zu bilden
Versuchen Sie, Fische mit Python + OpenCV2.4 (unvollendet) zu erkennen.
Führen Sie eine Twitter-Suche in Python durch und versuchen Sie, Sätze mit der Markov-Kette zu generieren.
Versuchen Sie, eine vollständige Suche nach der Sequenz durchzuführen, die bei Wettbewerbsprofis mit Python häufig vorkommt