Jump to content

Sinn (und Unsinn) von Backtests?


PeWi
 Share

Recommended Posts

Nachdem hier im Coinforum immer mal wieder das Thema Backtest kurz aufflackert, und ich mich seit Jahren mit Backtests beschäftige, möchte ich ein paar Punkte aus meiner Erfahrung niederschreiben und freue mich über Hinweise, Korrekturen, Verbesserungen und überhaupt eine rege Diskussion ...


Disclaimer: Ich spreche hier immer vom Level, den man als interessierter Amateur erreicht. Echte Profis können das vermutlich besser.


Aufgrund der Länge unterteile ich meine Niederschrift in mehrere Posts.

Edited by PeWi
Überflüssige Leerzeilen entfernt
  • Love it 1
  • Thanks 1
  • Like 2
Link to comment
Share on other sites

1) Was sind Backtests?

 Mit einem Backtest wird eine Strategie auf historischen Daten eines bestimmten Zeitraums ausgeführt. Typischerweise wird das Verhalten während dieses Testzeitraumes anhand mehrerer bis vieler Kennzahlen analysiert und präsentiert.

 Solche Kennzahlen sind mindestens Gewinn und Verlust und üblicherweise minimal eine Kennzahl wie das Sharpe Ratio; oft sind es aber deutlich mehr Kennzahlen bis hin zur statistischen Auswertung sämtlicher Trades.

 Verbreitet ist das vor allem unter Betreibern automatisierten Trading, man kann einen Backtest prinzipiell aber auch per Hand anhand der Kursdaten und der Strategiekriterien auf dem Papier durchführen.

 

2) Welchen Nutzen hat ein Backtest?

 Ein guter Backtest zeigt einem das grundlegende Verhalten seiner Strategie auf, man bekommt ein erstes Gefühl dafür, was sie taugt, und bei welchen Kursverhältnissen sie gut oder schlecht performt.

 
Ohne Backtest muss man die Strategie im Livebetrieb kennenlernen, und das dauert u.U. ziemlich lange. Meinen ersten ausgefeilteren Bot habe ich im Bärenmarkt entwickelt und konnte ihn über Monate hinweg gut gegen fallende Kurse härten, wusste aber die ganze Zeit über nicht, wie er sich dann bei steigenden Kursen schlagen würde.

Bei Backtests kann man üblicherweise den Testzeitraum auswählen, und damit kann man die Strategie in einer Vielzahl von unterschiedlichen Marktbedingungen ausprobieren. Im Livebetrieb würde das Jahre dauern, ähnlich umfangreiche Erfahrungen zu bekommen.

 
Ein zweiter, wichtiger Aspekt ist, dass man beim Austesten seiner Strategie durch Backtests kein echtes Geld riskieren muss. Ein Backtest ist ja immer nur eine Simulation.

 Das lässt sich im Livebetrieb stark mildern, indem man mit sehr kleinen Positionsgrößen arbeitet. Je nach Zahl der gleichzeitigen laufenden Tests und den eigenen finanziellen Verhältnissen kann das verschmerzbar sein oder immer noch wehtun.

 Ein Teil der Bots bietet im Livebetrieb zusätzlich die Möglichkeit des Paper Tradings an, d.h. die Kauf- und Verkaufsorders werden nicht tatsächlich ausgeführt, sondern nur simuliert. Ohne Backtest bleibt dennoch das Problem, dass es sehr lange dauert, genügend viele Erfahrungen mit der Strategie zu sammeln.

 Eine Gegenanzeige zum zweiten Punkt: Gerade bei manuell ausgeführtem Trading wird oft bewusst empfohlen, mit echtem Geld zu arbeiten. Es ist viel leichter, sich bei Spielgeld an die Strategie zu halten als bei echtem Geld. Der durchschnittliche Mensch neigt laut Studien dazu, Gewinne vorschnell zu nehmen und Verluste in der Hoffnung auf `nen Turnaround zu lange laufen zu lassen.

(Einer der Gründe, warum ich auf Bots setze - das nimmt die Emotionen weitgehend raus.)

  • Like 1
Link to comment
Share on other sites

3) Kann man alles backtesten?


Keinesfalls, es gibt einiges an Strategien, die sich überhaupt nicht vernünftig backtesten lassen.

Das betrifft vor allem zwei Umstände. Manche Strategien benötigen Daten, die man üblicherweise nicht oder nur sehr teuer bekommt wie z.B. ein zeitlich und preislich fein aufgelöstes Orderbuch. Oder die Strategie hängt sehr davon ab, dass man besser und schneller ist als Konkurrenten.

Arbitrage z.B. betrifft gleich beide Punkte und ist somit nicht backtestbar.


Allgemein: Je kürzer die Zeitbasis ist, auf der die Strategie arbeitet, desto schwieriger wird ein Backtest. Eine Strategie, die auf Stundencandles oder noch größeren Zeiträumen arbeitet, ist weit einfach backzutesten als eine, die auf 1-min-Candles beruht.


Zusätzlich: Je größer die eigenen Positionen werden, desto schwieriger werden brauchbare Tests, weil man durch große Orders das Orderbuch merklich beeinflusst und damit den Kurs verzerrt. Das lässt sich im Backtest kaum simulieren.

Was „große Orders“ sind, ist im Kryptomarkt stark relativ. Bei hoch liquiden Coins wie BTC und ETH kann man auf großen Börsen üblicherweise sechsstellige Orders praktisch ohne Kursbeeinflussung unterbringen, bei kleinen „Shitcoins“ und/oder kleinen Börsen können auch dreistellige Orders schon kritisch werden.

 

 

 

  • Like 1
Link to comment
Share on other sites

4) Wie genau sind Backtests?

 
Wenn man die jeweilige Strategie überhaupt backtesten kann:

Schwierig - typischerweise nicht so dolle. Zumindest das, was man als interessierter Amateur so hinbekommt. (Was echte Profis können, kann ich nicht beurteilen.)

Wer also einen Bot über ein paar Monate laufen lässt und anschließend diesen Zeitraum nochmal durch einen Backtest jagt, wird meiner Erfahrung nach deutlich divergierende Ergebnisse erhalten, sowohl, was die konkreten Trades betrifft als auch das Ergebnis (Profit, Sharpe Ratio, ...).

 

Das hat verschiedene Gründe.

Zum einen die subtilen Gründe wie die üblicherweise fehlende Einbeziehung von Orderbuch und Konkurrenten. Die machen für Strategien auf großen Candles und begrenzten Einsatz wahrscheinlich wenig aus.

 
Meiner Vermutung nach entstehen die wesentlichen Abweichungen eher durch das Backtest-Design selber.


Üblicherweise rechnet man nach jeder fertigen Candle diverse Indikatoren aus und schickt die dann an die Exchange. D.h. man rechnet mit dem letzten Close-Preis und bekommt dann für die nachfolgende Bot-Order  irgendeinen Preis nach dem Open der neuen Candle. Gerade, wenn sich im Preis einiges tut, und der Bot darauf reagiert, entstehen durch diesen zeitlichen Versatz u.U. merkliche Differenzen.

Das betrifft vor allem schnelle Strategien (kurze Candles) und langsame Programme. Bis alle Daten geholt und alle Indikatoren berechnet sind, ist die nächste Candle schon fast rum.


Ein zweites Problem, das einem möglicherweise gar nicht gleich auffällt, ist dass sich kleine Unterschiede (auch Rundungsfehler) über die Zeit gewaltig aufschaukeln können - Stichwort Schmetterlingseffekt.


Dazu eine Anekdote von meinem eigenen Bot: Beim Test einer neuen Strategie bekam ich bei jedem Durchlauf deutlich unterschiedliche Ergebnisse bei eigentlich völlig gleichen Bedingungen. Nach längerem Suchen nach eigenen Bugs kam ich schließlich darauf, dass von mir verwendete Sprache Go bei Hashmaps absichtlich (durch Hinzufügen eines Zufallselementes) die Reihenfolge der enthaltenen Objekte verwürfelt. Sprich, mein Bot hat bei dem einem Backtest die Coins in der Reihenfolge A bekommen und beim nächsten Backtest in der Reihenfolge B etc. Und dadurch, dass bei dieser Strategie nur weniger Positionen als mögliche Coins erlaubt waren, hat sich die Reihenfolge der Coin-Orders (und dadurch auch das Ergebnis) völlig unterschiedlich entwickelt. Wenn sich mehrere Coins angeboten haben, aber nicht mehr genügend Order-Slots frei waren, dann wurde je nach Coinreihenfolge mal Coin A, mal Coin B oder mal Coin C genommen - kein Wunder, dass die Backtests über die Zeit dann deutlich auseinanderliefen.

(Bei Strategien, die die Coins nach irgendwelchen Kriterien ranken, wird die Hashmap-Reihenfolge durchs Sortieren überschrieben; die liefern dann bei jedem Backtest die gleichen Trades und das gleiche Ergebnis ab.)

 

Daraus habe ich für mich das Fazit gezogen, dass ein Backtest per se ungenau ist und auch im Nachhinein nie die Realität widerspiegeln kann. Ein Backtestlauf ist quasi lediglich das Ziehen einer Möglichkeit aus den vielen Möglichkeiten und Ergebnissen, die durch die verschiedenen Unterschiede (Reihenfolge, Konkurrenten, Orderbuch, ...) entstehen.

Und wenn man diese Verwürfelungen zulässt, dann bekommt man eine Bandbreite an Ergebnissen und kann eher abschätzen, in welchem Bereich ein späteres Ergebnis schwanken kann.

 

Edited by PeWi
klarer formuliert
  • Like 1
Link to comment
Share on other sites

5. Wozu dann überhaupt Backtests?

 
Ich nutze seit der Erfahrung aus 4) Backtests nicht mehr als Voraussage, wie der Bot später im Echtbetrieb laufen sollte, sondern mehr zum grundsätzlichen Testen von Strategie-Ideen und zum Aussortieren schlechter Einstellungen.


Erfahrungsgemäß und auch in der Literatur beschrieben ist der Livebetrieb immer schlechter als der Backtest. Damit ändert sich auch die Aussage des Backtests - er kann nicht sagen, was man in realiter mit der Strategie schaffen könnte oder sollte, sondern er kann nur die verschiedenen Strategien und Einstellungen relativ ranken.

Verständlicher formuliert: Gute Ergebnisse im Backtest werden im Livebetrieb schlechter sein - wie viel ist ungewiss. Aber schlechte Ergebnisse im Backtest werden in realiter noch schlechter sein.

 Man kann also mit einem Amateur-Backtest wie meinem nicht prognostizieren, was der Bot tatsächlich erwirtschaften kann, aber man kann damit durchaus die schlechten Ideen und die schlechten Parameter-Einstellungen erkennen und aussortieren.

 Was den Backtest mit guten Ergebnissen übersteht, könnte tauglich sein und ist es ggfs. wert, es mit kleinem Geld mal live auszuprobieren.

 

Und dazu benutze ich meine Backtests hauptsächlich, und dafür finde ich sie auch sinnvoll.

 Konkrete Prognosen für die Zukunft und den späteren Ertrag mit echtem Geld finde ich dagegen hochgradig unseriös!

 

  • Like 1
Link to comment
Share on other sites

6) Welche Arten von Backtests gibt es?

 
Die simple Ausführung eines Backtests lässt dich deine Strategie mit den gewählten Parametern ausführen und zeigt dir dann an, was im Testzeitraum rausgekommen wäre. (Mit den Einschränkungen aus 4) und 5)!)


Etwas fortgeschrittenere Backtests enthalten gerne Optimierungen. Sprich, man kann für einen oder mehrere Strategieparameter Wertebereiche vorgeben, und der Backtest rattert alle Kombinationen durch und spuckt aus, welches die beste Kombinationen für den Testzeitraum gewesen wäre.

 Das ist oft gefährlich, denn meistens wird einfach nur der Endkontostand als Kriterium für die beste Parameterkombination genommen. Zum einen sind die Ergebnisse typischerweise nicht belastbar (siehe 4) und 5)), und zum anderen landet man damit in der großen Backtest-Falle namens Overfitting. (Siehe 8).)

 
Weiter fortgeschrittenere Backtests erlauben zusätzliche Freiheiten, z.B. mehrere Testzeiträume gleichzeitig, wählbare Kriterien, auf die optimiert werden soll, und Maßnahmen, die Overfitting einschränken sollen.

 

  • Like 1
Link to comment
Share on other sites

7) Fehlerquellen

 
Backtest-Ergebnisse nutzen nur etwas, wenn sie nicht aufgrund von Fehlern verfälscht sind. Die meisten Fehler fallen in fünf große Fehlerklassen.

 
a) Vergessen von Fee und Slippage

Das ist der simpelste Fehler. Jeder Kauf und Verkauf kostet Gebühren, und wenn man die nicht berücksichtigt, ergibt sich ein geschöntes Bild. Gerade bei schnellen Strategien mit vielen, schnellen Trades spielen die Gebühren eine große Rolle, und manch eine Strategie, die ohne Gebühren stabil profitabel wäre, rutscht mit den Gebühren in die Minuszone.

Slippage: Der angezeigte Kurs ist die Spitze des Orderbuchs. Bei illiquiden Coins kann diese Spitze ziemlich dünn sein, und um die Menge an Coins kaufen oder verkaufen zu können, die dem gewünschten Betrag entspricht, muss man auch Angebote aus der zweiten und dritten Reihe des Orderbuchs bedienen. Damit bekommt man schlechtere Kurse, und gerade bei kleinen Coins kann dieser Kursunterschied deutlich über ein Prozent ausmachen, was tödlich für Strategien ist, die viele kleine Trades machen wollen.

Im Gegensatz zur Fee ist die Slippage sehr variabel und hängt vom konkreten Coin, der eigenen Positionsgröße, der Tageszeit und der allgemeinen Aktivität am Markt ab. Die Slippage kann man somit nur raten, und ihre Wirkung auf die Ergebnisse ist in realiter oft schlimmer als die Fees. Am besten konzentriert man sich auf hochliquide Coins und hält seine Ordergrößen im Zaum - andernfalls muss man genau hinschauen und genau wissen, was man tut!

 
b) Unterschiede zwischen Bot- und Backtest-Source:

Wenn man für den Backtest nicht weitgehend die Originalsourcen des Bots nutzen kann, sondern viele Teile nachprogrammieren muss, dann wird es sehr schwer, diese beiden Pfade dauerhaft konsistent zu halten, so dass Bot und Backtest für gleiche Kurse wirklich genau das gleiche tun. Gerade, wenn man anfängt, kleine Optimierungen und Änderungen einzupflegen, dann kann man fast darauf wetten, dass man die eine andere Kleinigkeit irgendwann im anderen Zweig einzupflegen vergisst oder versehentlich einen subtilen Unterschied einbaut.

In Summe laufen Backtest-Verhalten und Bot-Verhalten damit immer weiter auseinander; die Backtests werden damit unbrauchbar.

Die Konsequenz daraus ist, seinen Source so zu bauen, dass möglichst viel für Bot und Backtest gleichermaßen genutzt werden kann. Lieber ein paar if-Verzweigungen in den Funktionen, als die Funktionen doppelt halten.


c) Programmfehler:

Fehler im Sourcecode des Backtests ruinieren die Aussagekraft der Ergebnisse etwas bis vollkommen. Ein Beispiel wäre, dass ein Coin aufgrund eines Bugs im Backtest überhaupt nicht verwendet wird. Oder dass aufgrund von Rundungsfehlern oder fehlenden Prüfungen der Backtest gleichzeitige Orders gestattet, die minimal bis deutlich über der vorgegebenen Balance liegen.

Besonders tückisch ist der Off-By-One-Fehler. Preis- und Indikatordaten werden im Programm oft in Arrays gehalten, und wenn aufgrund eines Bugs der Arrayindex um eins nach oben verrutscht, dann kann der Backtest um eine Candle in die Zukunft sehen. Mit etwas Erfahrung erkennt man das an den Ergebnissen relativ schnell, weil der Backtest dann typischerweise nur minimale Drawdown ausweist und in quasi allen Marktsituationen satte Gewinne macht. Wenn das Ergebnis zu gut scheint, um wahr zu sein, dann ist es auch nicht wahr.

 
d) Datenfehler

Auch wenn der Source fehlerfrei ist, kann der Backtest falsch sein. Wenn z.B. Kraken wegen Wartungsarbeiten o.ä. down ist, gibt es für diese Zeiten keine Candles. Sprich, die für den Backtest heruntergeladenen Candles haben an der Stelle einfach ein „Loch“, was zu mannigfaltigen Fehlern im Backtest führen kann.

Oder einzelne Werte einzelner Candles stimmen nicht; es kommt durchaus vor, dass Exchanges oder Datendienste Fehler in ihren Daten haben. Mal ist der Open-Wert viel zu niedrig oder zu hoch, mal der Close-Wert, mal steht Null drin. Wenn der Backtest in genau dieser Candle kauft oder verkauft, dann ergeben sich ebenfalls völlig unrealistische Gewinne oder Verluste.

Es empfiehlt sich, die Candledaten in einer Tabellenverarbeitung zu visualisieren, dem Auge fallen Brüche und Ausreißer gut auf. Solche Fehlstellen muss man anschließend korrigieren, oder gleich den betreffenden Coin ausschließen, wenn’s bei ihm öfter vorkommt.

 
e) Overfitting

Overfitting ist ein so grundlegendes und großes Problem für alle Optimierungsversuche, so dass ihm ein eigenes Kapitel gewidmet ist.

 

  • Like 1
Link to comment
Share on other sites

8 ) Was ist Overfitting, und was kann man dagegen tun?

 
Overfitting bedeutet anschaulich gesprochen, dass eine Optimierung nicht dazu führt, dass die Strategie „sinnvoll“ besser wird, sondern dass sie anfängt, „auswendig“ zu lernen. Das ist ziemlich schlecht, denn die auswendig gelernten Kurse sind Vergangenheit und kommen im Livebetrieb nie so wieder. Die Strategie hat folglich Antworten auf Fragen gelernt, die nie mehr gestellt werden; ihr Wissen ist somit weitgehend nutzlos.

In Konsequenz werden die echten Live-Ergebnisse um so schlechter, je mehr die Strategie die Backtest-Daten auswendig gelernt hat.


Um mal einen holprigen Vergleich zu bringen: Wenn ich immer die gleiche Strecke mit dem Auto fahre, dann kann ich sie irgendwann „blind“ fahren. Das hilft mir aber nichts, wenn ich dann eine andere Strecke fahren muss.

 
Wie kann eine Strategie beim Optimieren überhaupt „auswendig lernen“?

Jede Strategie hat üblicherweise Stellschrauben, d.h. Parameter, die man so oder anders wählen kann. Bei einer simplen EMA-Kreuzungs-Strategie z.B. sind das die Periodenlängen des kurzen und des langen EMAs; bei einer simplen RSI-Bollinger-Strategie wären es bereits fünf Parameter (Periodenlänge des RSI, Über- und Unterkauft-Bereich, Periodenlänge Bollingerbänder und wie viel Standardabweichungen der Bänder).

Der berühmter Mathematiker, Physiker und Computer-Pionier John von Neumann hat mal gesagt:
„Mit vier Parametern kann ich einen Elefanten fitten, und mit fünf mit seinem Rüssel wackeln lassen.“


Das heißt, dass man mit den Stellschrauben/Parametern der Strategie die Strategie an die Kurse im Testzeitraum anpassen kann. Je mehr Parameter eine Strategie hat, desto genauer kann man sie anpassen.

 Ein bisschen Anpassung ist ja nicht verkehrt - bei obiger EMA-Kreuzungs-Strategie sind viel zu kurze EMAs sicherlich untauglich und viel zu lange auch. Irgendwo im mittleren Periodenbereich liegen sinnvolle Werte. Suche ich aber das absolute Optimum, dann bekomme ich ein Parameter-Paar für den Testzeitraum A, vermutlich ein anderes für den Testzeitraum B und ein drittes für C.

 Sprich, das absolute Optimum in den Backtestergebnissen ist immer unbrauchbar für andere Zeiten bzw. den späteren Livebetrieb. Gesucht sind Werte, die idealerweise überall „halbwegs“ funktionieren.

 
Overfitting ist im übrigen keine theoretische Gefahr, sondern
eine mit Sicherheit auftretende, sobald man mit Optimierungen anfängt.


Was kann man dagegen tun?


Es gibt mehrere Möglichkeiten:

 
a) Möglichst wenig Parameter in der Strategie verwenden.

Je weniger Einstellschräubchen, desto weniger genau können die Parameter an den Testzeitraum angepasst werden.

Meiner Erfahrung nach funktionieren heutzutage simple Strategien allerdings kaum mehr.


b) Nicht auf den Gewinn optimieren, sondern auf das Sharpe Ratio

Eine Kennzahl wie das Sharpe Ratio ist weniger anfällig für Overfitting als der Gewinn. Für einen hohen Gewinn reicht im Extremfall ein einziger Glückstreffer, für ein gutes Sharpe Ratio sind dagegen viele gute Treffer nötig.

In einem Paper einer Universität über Trading mit Methoden künstlicher Intelligenz schrieben die Autoren explizit, dass sich ihre Ergebnisse deutlich verbessert hätten, als sie ihr Optimierungskriterium vom Gewinn auf das Sharpe Ratio umgestellt hatten.


c) Mehrere verschiedene Testzeiträume verwenden und die Ergebnisse mitteln.

Ein Parametersatz, der für den Zeitraum X merklich overfittet, sollte für die anderen Testzeiträume eher mäßige Ergebnisse liefern, d.h. sein Ergebnisdurchschnitt über alle Zeiträume ist demzufolge auch eher mäßig. Gute Ergebnisdurchschnitte gibt es nur für Parametersätze, die über alle Testzeiträume halbwegs brauchbare Ergebnisse geliefert haben, und nur die zieht man in Betracht.

Das mildert das Problem des Overfittings, löst es aber nicht. Wenn man viele Parameter in der Strategie hat, dann wird die Optimierung letztendlich alle Testzeiträume lernen. D.h. mehr Testzeiträume sind auf jeden Fall besser - eine echte Hilfe ist das aber nur, wenn die Strategie relativ wenige Parameter verwendet.


d) Den Backtest mit einer Datenflut ersäufen.

Je mehr Parameter man hat, desto mehr kann gelernt werden. Deswegen noch mehr Testzeiträume, noch längere Testzeiträume, noch mehr Coins, ... solange alles steigern, bis es viel zu viele Daten sind, als mit der Parameterzahl gelernt werden können.

Das ist sehr schwammig und leider schwierig zu kontrollieren, wann man genug Daten hat, um das Overfitten zu verhindern. Dennoch - je mehr Daten, desto besser. Overfitting wird schlimmer mit wenigen Daten und milder mit mehr Daten. Deswegen ist es immer besser, noch mehr Daten zu verwenden - leider erhöht das die Rechenzeit auch entsprechend.

Methoden des maschinellen Lernens (z.B. neuronale Netze, Entscheidungsbäume, etc.) haben typischerweise extrem viele Parameter, da ist eine möglichst große Menge an Daten eine Grundvoraussetzung, ohne die man überhaupt keine Chance gegen Overfitting hat.


e) In-Sample optimieren, Out-Of-Sample kontrollieren

Eine heutzutage häufig angewandte Methode. Man lässt die Optimierung über soundsoviel Daten/Testzeiträume/Coins/... laufen und prüft mit den Testergebnissen einen zusätzlichen, während der Optimierung nie verwendeten Zeitraum.

Solange während der Optimierung noch tatsächlich „echtes Wissen“ gelernt wird, werden sich auch die Ergebnisse für den zusätzlichen Zeitraum verbessern. Sobald das Overfitting einsetzt, werden die Ergebnisse des zusätzlichen Zeitraumes wieder schlechter werden.


f) Parametersatz verrauschen und prüfen.

Overfitting charakterisiert sich dadurch, dass es nicht „robust“ ist. Sobald sich etwas (Kurs, genauer Parameterwert, ...) leicht ändert, fallen die Ergebnisse deutlich ab.

Das kann man sich zunutze machen, wenn man ein Ergebnis auf Overfitting prüfen möchte. Man kopiert den Parametersatz mehrfach und ändert in jedem Duplikat einen oder mehrere Parameterwerte um wenige Prozent.

Basiert der ursprüngliche Parametersatz größtenteils auf Overfitting, dann werden die leicht veränderten Duplikate mehrheitlich merklich abfallen. Enthält der ursprüngliche Parametersatz dagegen kaum Overfitting, dann werden auch die leicht veränderten Duplikate ähnlich gute Ergebnisse erzielen.

Edited by PeWi
8) wird durch einen Smiley ersetzt
  • Thanks 1
  • Like 1
Link to comment
Share on other sites

9) Historie meiner Backtests

 
Meine Gedanken möchte ich mit der Historie meiner Backtests abschließen.


Ich habe im Herbst 2017 mit ersten Bots angefangen und ziemlich schnell auch den allerersten, primitiven Backtest ergänzt. Schon deswegen, weil ich mit Börsen und Trading überhaupt keine Erfahrungen hatte und von daher keinerlei Gefühl für gut und schlecht.

Die ersten Strategien und Backtests waren entsprechend simpel: zwei kreuzenden EMAs und zwei geschachtelte Schleifen, die für beide EMAs die Parameterbereiche durchrechneten. Ähnliches dann für die Kombination RSI und Bollinger Bänder. Und das musste man dann für jedes Coinpaar wiederholen.


Zu meinem ersten, ernsthaften Bot habe ich dann einen umfangreicheren Backtest entwickelt, der alle angegebenen Coinpaare gleichzeitig miteinander hat laufen lassen. Für jeden Parameter konnte man mehrere explizite Werte vorgeben, und der Backtest hat daraus zufällig einen Wert gezogen. Das ganze mehrere hundert mal, und man bekam eine große Ergebnistabelle mit den Gewinnen (oder Verlusten) und mehreren Kennzahlen wie Tradezahl, Sharpe Ratio, Profit Factor, Ulcer Index und einem anschließenden „Rang“, der die wichtigsten vorhergehenden Kennzahlen in eine einzige Zahl kondensiert hat.

Bald darauf wurden drei Testzeiträume pro Backtest eingeführt, damit man sehen konnte, wie sich die Strategie und ihre Parameter in Bullen-, in Bären- und in Seitwärtszeiten machen würde. Die Zeiträume entsprechender Charakteristik habe ich dann per Augenmaß aus dem Chart heraus ermittelt und eingetragen.

Weil Python für eigene Rechnungen doch recht langsam war, habe ich bald Caches für die Indikatorrechnungen und Multitasking eingeführt. Das hat es mir dann erlaubt, über Nacht nicht nur hunderte Parameterkombinationen rechnen zu lassen, sondern mehrere tausend.

 

Einschub: Je mehr Parameter eine Strategie hat, und je mehr Möglichkeiten zur Auswahl man jedem Parameter vorgibt, desto mehr mögliche Kombinationen ergeben sich, mit denen man die Strategie laufen lassen kann.

Nehmen wir das Minimal-Beispiel mit den beiden kreuzenden EMAs: Wenn ich bei jedem EMA für die jeweilige Periodenlänge fünf verschiedene Möglichkeiten durchtesten will, ergeben sich bereits 5 hoch 2 = 25 verschiedene Möglichkeiten. Bei der RSI-Bollinger-Strategie mit ihren fünf Parameters ergeben sich für je fünf Möglichkeiten pro Parameter bereits 5 hoch 5 = 3125 verschiedene Parametersätze. Bei zehn Parametern mit je zehn Auswahlmöglichkeiten landet man bereits bei 10 Milliarden an unterschiedlichen Kombinationsmöglichkeiten - da würde mein Backtest bereits 4 Jahre kontinuierlich rechnen müssen.

Die Zahl der Möglichkeiten explodiert somit ziemlich schnell in Höhen, die man nicht mehr alle durchtesten kann. Insofern zieht man über Zufallszahlen eine bestimmte Anzahl mal aus dem Topf mit allen Möglichkeiten und rechnet nur die gezogenen Sets durch. Es ist nämlich gar nicht notwendig, wirklich alle Kombinationen durchzurechnen. Auch wenn man nur jede zehnte oder jede hunderste durchrechnet, bekommt man bereits ein Gefühl für die „Karte“.

Wieder ein hinkender Vergleich: Um eine Landkarte zu erstellen, muss man auch nicht jeden einzelnen Zentimeter der Landschaft vermessen. Selbst wenn man nur mit einem Raster von je 100 Metern misst, bekommt man bereits einen brauchbaren Eindruck von der Landschaft, wo große Berge sind, wo große Seen sind etc.

Schließlich wollen wir ja Overfitting vermeiden, d.h. hohe, aber schmale Berge sind uninteressant; wir wollen mehr so Gegenden wie das tibetische Hochland finden, wo’s in jeder Richtung ein ganzes Stück geht, und es so hoch bleibt. Insofern darf man grob rastern, und wenn man einen hohen Punkt findet, kontrolliert man die Nachbarpunkte. Sind die ebenfalls hoch, hat man robuste Parametersätze gefunden; sind die Nachbarn mal hoch, mal tief, mal mittendrin, dann war der hohe Ausgangspunkt nicht robust genug, sondern doch etwas overfittet.

 

Damit aber rückte das Problem Overfitting immer mehr ins Bewusstsein. Bisher hatte ich mir einfach immer ein gut erscheinendes Ergebnis aus der Tabelle herausgepickt und dessen Werte in den Bot übernommen. Je mehr Parametersets man durchrechnen kann, desto mehr gerät man ins Overfitting.

Das habe ich dann lange von Hand zu lösen versucht. Zuerst aus der Tabelle alle schlechten Ergebnisse löschen, danach die mit den allerbesten Werten für Gewinn, Sharpe Ratio etc., weil die am ehesten auf Overfitting basieren sollten. Die verbleibenden dann manuell verglichen, und was häufiger vorzukommen schien, dann als neue Parameter in den Backtest eingetragen. Zusätzlich noch zu jedem Wert den Wert darüber und darunter ergänzt und das ganze neu durchrechnen lassen. (Entspricht dem obigen Punkt „verrauschen und neu prüfen“.) Waren die neuen Ergebnisse weitgehend ähnlich gut, dann war der ursprüngliche Parametersatz wohl tauglich und konnte verwendet werden. Haben die neuen Ergebnisse dagegen recht gestreut, war der ursprüngliche Parametersatz bereits overfittet.


Irgendwann wollte ich per Bot auch shorten können und bin von Binance zu Kraken umgezogen und von Python auf die schnellere Sprache Go umgestiegen. Den Großteil des bisherigen Pythonbots konnte ich übernehmen (d.h. auf Go portieren), den kleineren Rest habe ich neu geschrieben.

Go als deutlich schnellere Sprache hat den Backtest aus dem Stand heraus um den Faktor 20 bis 50 beschleunigt, ich kann seitdem über Nacht knapp sechsstellige Zahlen an Parametersets durchlaufen lassen. Damit wurde auch das manuelle Aussuchen, Überprüfen und Verfeinern guter Parametersätze immer mühsamer.

Mit den neuen Möglichkeiten und dem Kennenlernen vieler Indikatoren und Strategien anderer wurden meine eigenen Versuche auch immer komplexer. Trotz der deutlich höheren Geschwindigkeit von Go wurde die Rasterung der Backtests aufgrund der explodierenden Permutationen immer gröber, so dass die Chancen immer größer wurden, auch größere robuste Bereiche einfach zu übersehen. (Da ist es nur ein schwacher Trost, dass auch das Overfitting harmloser wird, da es statistisch einfach immer unwahrscheinlicher wird, genau so einen hohen, aber schmalen Peak zu treffen.)

Eine automatische, selbst suchende Optimierung des Backtests musste her. Nach etwas Recherchieren klang die „genetische Optimierung“ interessant. Dankenswerterweise ließ sich das auf meine bisherigen Backtests obendrauf setzen. Man lässt einen konventionellen Backtest laufen, die genetische Optimierung pickt anhand einer zu definierenden Fitnessfunktion gute Datensätze heraus, übernimmt sie und füllt den Rest mit Mutationen und Kombinationen zur vollen Stärke auf. Auf diese neue Tabelle lässt man den nächsten Backtest los, und so weiter.

(Übliche Fitnessfunktionen liefern typischerweise einen einzelnen Wert zurück, weswegen ich mich für den NSGA-II-Algorithmus entschieden habe, da dieser gleichzeitig auf mehrere Kennzahlen hin optimieren kann und dadurch die „genetische Vielfalt“ der Parametersätze erhält.)


Mit so einer Optimierung läuft man natürlich irgendwann unweigerlich ins Overfitting hinein, weswegen man den Zyklus der genetischen Optimierung rechtzeitig abbrechen muss. Nur wann ist rechtzeitig? Wieviele Durchläufe der Methode sind noch ok?

Das kann man über die Methode der In-Sample-/Out-Of-Sample-Tests kontrollieren. Der Backtest samt der genetischen Optimierung bekommt einen der Testzeiträume nie zu sehen. Nach jedem Durchlauf wird dieser spezielle Testzeitraum gesondert getestet. Solange seine Kennzahlen noch steigen, solange lernt die Optimierung tatsächlich sinnvolles, das auch außerhalb funktioniert. Wenn die Anpassung an die normalen Testzeiträume spezifisch wird, dann werden die Kennzahlen außerhalb wieder schlechter werden; und dann bricht man ab und nimmt den Durchlauf, bei dem die Out-Of-Sample-Kennzahlen am höchsten waren.

Edited by PeWi
Tippfehler
  • Thanks 2
  • Like 1
Link to comment
Share on other sites

Sehr schön und ausführlich geschrieben. Cool!

Das deckt sich gut mit meinen - weit geringeren Erfahrungen - in der Botentwicklung.

Eine Sache fällt mir spontan noch ein. Du schriebst zwar, dass du unterschiedliche Marktszenarien analysiert, man sollte aber trotzdem im Hinterkopf behalten, dass der Backtest nur die Vergangenheit abbildet.

Die Kryptokurse kannten in den letzten Jahren überwiegend eine Richtung, das kann in den kommenden Jahren aber auch anders aussehen. Verwendet man für den Backtest Daten der letzten Jahre aus dem Kryptotrading, optimiert man vermutlich für steigende Märkte.

 

Wie beschrieben, sind die Backtest-Ergebnisse mehr oder weniger weit entfernt von der Realität. Trotzdem sind sie - in ihren Grenzen - extrem hilfreich und ohne könnte ich mir die Botentwicklung nicht vorstellen.

Meine ersten selbstgeschriebenen Bots basierten ebenfalls auf gebräuchlichen Indikatoren wie RSI und MA. Gefühlt funktionierten die ganz okay, aber später habe ich diese im Backtest nachgebaut und realisiert, dass diese langfristig nicht profitabel sind.

Auch aktuell teste ich alle Änderungen intensiv im Backtest und verwerfe immer wieder Ideen, da der Backtest zeigt, dass dadurch kein positiver Effekt entsteht.

 

Und abschließend noch eine Anmerkung zur Optimierung mittels Backtest:

Wie du beschriebst, potenzieren sich die erforderlichen Backtests pro Parameter. Deshalb ist es meiner Erfahrung nach effizienter, jeden Parameter einzeln zu optimieren.

Und um nochmal Werbung für Freqtrade zu machen, dort sind Backtests und die Optimierung der Parameter bereits eingebaut. Das optimieren nennt sich Hyperopt und funktioniert ähnlich wie von dir beschrieben mittels der Definition des oberen und unteren Grenzwertes. Die Werte dazwischen werden aufgrund der vorherigen Ergebnisse ermittelt. Es lohnt sich, einen Blick in die Dokumentation zu werfen: https://www.freqtrade.io/en/stable/hyperopt/

Es lassen sich z.B. auch verschiedene Bewertungsmethoden auswählen. U.a. die von dir erwähnte Methode nach Sharpe. Es gibt aber noch andere, z.B. Sortino, Calmar, oder selber geschriebene. Alle haben Vor- und Nachteile und passen je nach Strategie besser oder schlechter.

Ist man bereits soweit fortgeschritten wie du, lohnt der Umstieg vermutlich kaum. Ist man aber noch nicht so weit, nimmt Freqtrade definitiv mehrere Monate Arbeit ab.

 

Nochmal, tolle Zusammenfassung. Werde ich bestimmt noch ein paar Mal reinschauen und lesen. 👍

  • Thanks 1
Link to comment
Share on other sites

2 hours ago, Maaz said:

Die Kryptokurse kannten in den letzten Jahren überwiegend eine Richtung, das kann in den kommenden Jahren aber auch anders aussehen. Verwendet man für den Backtest Daten der letzten Jahre aus dem Kryptotrading, optimiert man vermutlich für steigende Märkte.

Man darf nur nicht zu kurz in die Vergangenheit blicken, gerade das Jahr 2018 z.B. war ein deutliches Bärenjahr. Edit: Und wenn man mehrere Testzeiträume in einem Backtest verwenden kann anstelle eines einzigen, dann kann man die Bären-, Bullen- und Seitwärts-Zeiten so gewichten, wie man will.

Ich bin inzwischen davon abgerückt, mir drei Zeiträume gezielt für Bulle, Bär und seitwärts rauszupicken, ich verwende inzwischen immer ziemlich viele Testzeiträumen (jeweils ein Jahr) und verrutsche die stumpf immer um ein Vierteljahr. Damit nehme ich die Subjektivität aus den Testzeiträumen und habe zwangsläufig eine bunte Mischung.

Zusätzlich verwende ich noch einen Filter, der Parametersätze, die einen bestimmten (wählbaren) Drawdown überschreiten, aus dem Backtest kickt. Damit reicht bereits ein einziger "schlechter" Testzeitraum, um haufenweise nicht "bärenfeste" Kombinationen aus dem Rennen zu nehmen.

Edit: Ich finde mehrere Testzeiträume auch deswegen besser als einen ganz langen, weil der Startzeitpunkt eine nicht zu unterstützende Rolle spielt. Das Bärenjahr 2018 war leichter zu überstehen, falls man bereits im Herbst 2017 eingestiegen war und bis zum Jahreswechsel bereits auf guten Gewinnen saß. Und es war besonders übel, wenn man tatsächlich erst Anfang Januar 2018 gestartet ist und ohne Polster gleich den Abwärtsstrudel bewältigen musste. Solche Details gehen in einem einzigen, endlos langen Testzeitraum unter. Und das finde ich heikel, denn man kann sich den Startzeitpunkt für reales Trading ja eben nicht frei aussuchen - man muss das nehmen, was ab jetzt kommt.

2 hours ago, Maaz said:

Wie beschrieben, sind die Backtest-Ergebnisse mehr oder weniger weit entfernt von der Realität. Trotzdem sind sie - in ihren Grenzen - extrem hilfreich und ohne könnte ich mir die Botentwicklung nicht vorstellen.

So geht es mir auch - absolut.

2 hours ago, Maaz said:

Und um nochmal Werbung für Freqtrade zu machen, dort sind Backtests und die Optimierung der Parameter bereits eingebaut. Das optimieren nennt sich Hyperopt und funktioniert ähnlich wie von dir beschrieben mittels der Definition des oberen und unteren Grenzwertes. Die Werte dazwischen werden aufgrund der vorherigen Ergebnisse ermittelt. Es lohnt sich, einen Blick in die Dokumentation zu werfen: https://www.freqtrade.io/en/stable/hyperopt/

Ich habe mir das vor ein oder zwei Jahren mal angeschaut, und es hat mir ziemlich gut gefallen. Und seitdem ist es sicherlich nicht schlechter geworden.

Hab's jetzt noch mal überflogen, Hyperopt gefällt mir nach wie vor sehr gut. In ein paar Punkten ist Freqtrade  definitiv besser als  mein Bot-Environment, ein paar mir wichtige Punkte fehlen Freqtrade dafür - in Summe sozusagen Gleichstand. ;)

2 hours ago, Maaz said:

Deshalb ist es meiner Erfahrung nach effizienter, jeden Parameter einzeln zu optimieren.

Es spart auf jeden Fall viel Rechenzeit, jeden Parameter einzeln zu optimieren, und senkt die Gefahr von Overfitting deutlich. Ich lasse gerne alles auf einmal optimieren, weil Änderungen in Bereich A oft auch Veränderungen in Bereich B nahelegen. Der Aufpreis für die höhere Rechenzeit ist dank der schnelleren Sprache und der inzwischen intelligenten Optimierung nicht mehr so schmerzhaft. Und das Overfitting hoffe ich durch die In-Sample- und Out-Of-Sampe-Messung in erträglichen Grenzen zu halten.

Der Autor vom Blog  https://financial-hacker.com/  (von ihm habe ich viel gelernt) unterstützt mehr deine These. Seine Empfehlung:

- erst die Trade Entries optimieren
- dann die Trade Exits optimieren
- dann das restliche Zeug (Stops o.ä.)

(Kann natürlich sein, dass er das auch aus Gründen einer akzeptablen Rechenzeit empfohlen hat. Das von ihm benutzte Tradingsystem Zorro enthält nämlich eine Bewertung der Ergebnisse, die robuste und breite Ergebnisplateus gegenüber Overfitting-Spitzen präferiert.)

Einer meiner Kritikpunkte an seiner Lösung und auch an Hyperopt ist, dass bei beiden Systemen am Ende nur eine einzige Lösung herauspurzelt. Bei der genetischen Optimierung mittels NSGA-II kommt ein ganzes Bündel an Lösungen heraus, sowohl Spezialisten für die drei Kennzahlen, auf die ich optimieren lasse, als auch diverse Mischungen, die alle drei Kennzahlen in unterschiedlichem Maße gewichtet haben.

Wenn ich z.B. mehrere Testbots betreibe, dann kann ich die somit problemlos mit unterschiedlichen Schwerpunkten betreiben. Der mit der größten Balance bekommt möglicherweise eine Low-Risk-Mischung, die niedrige Drawdowns sehr stark gewichtet und dafür weniger Wert auf viel Profit oder hohes Sortino Ratio legt. Und der andere Testbot mit der kleineren Balance bekommt ggfs. eine etwas riskantere Lösung, die den Profit etwas höher gewichtet als den Drawdown und das Sortino Ratio.

 

Edited by PeWi
Zwei Ergänzungen
  • Thanks 1
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
 Share

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.