Zwischenbericht über KI-Entwicklung und Code-Performance-Optimierung

Story title image

Der Poker-Bot ist tot, lang lebe der BitSurfer! - Nein ernsthaft, was ist passiert?

Der PokerBot und der Poker Advisor waren zwei sehr interessante Projekte, und ich habe von beiden viel gelernt! Der PokerBerater nimmt die Karten vom Bildschirm auf, gibt sie automatisch in eine KI ein und sagt das Ergebnis der Hand voraus. Während der Pokerbot geplant war, selbst zu spielen - alles war vorbereitet, aber Online-Poker wurde in der Schweiz so ziemlich verboten.

Es war also an der Zeit, weiterzumachen. Aber was hätte die nächste große Herausforderung sein können?

Bitcoin Preischart

Ich stolperte über Coinbase, einen Crypto Broker, wo ich mich hauptsächlich für Bitcoin interessierte.

Sie haben ordentlich eine API, über die Sie Ihre bevorzugte Handelssoftware wie Metatrader oder ähnliches anschließen können. Aber nein.

Der Plan ist natürlich nicht, unsere bevorzugte Handelssoftware anzuschließen. Vielmehr war es meine Idee, meine eigene Schnittstelle von Grund auf mit meinen Bedürfnissen in Bezug auf meine Bedürfnisse aufzubauen. Es war unheimlich schwer und eine sehr steile Lernkurve, aber es war die Mühe sicherlich wert.

Die erste Alpha-Version ist fertig. Die Schnittstelle ist sehr hässlich, aber die Form folgt der Funktion. Meine Vorstellung von einer gut gestalteten Software ist nicht in erster Linie eine ausgefallene Benutzerschnittstelle. Vielmehr möchte ich, dass meine Software einfach ihr Ding macht. Unbedingt. Im Hintergrund. Nichts zu installieren, nicht vor dem Bildschirm zu sitzen und der Software zu sagen, was sie als nächstes tun soll. Einfach ausführen und fasziniert zusehen.

Die Schnittstelle besteht im Wesentlichen aus einer Visualisierung der Marktdaten sowie der normierten Eingangsdaten für die KI.

Was habe ich gelernt? Zuerst musste ich mich mit Coinbase verbinden. Ich habe eine Menge über APIs gelernt, und mit den verfügbaren Paketen war es glücklicherweise recht einfach.

Einführung in den Performanceaspekt der Programmierung

Ich musste viel über die Datenstrukturierung für die KI lernen, und das war im Grunde genommen mit viel Wissen über die Code-Performance verbunden. Bis zu dem Punkt, an dem es völlig verrückt wird. Es ging hauptsächlich darum, dass ich immer noch an meiner 7 Jahre alten Maschine arbeite, die ich von meiner Ausbildung zurückbekommen habe. Sie ist gut gealtert, aber man spürt wirklich das Alter... Von meinem nächsten, unmittelbar bevorstehenden Computer kann ich für meine Anwendungsfälle mit etwa 10-facher Leistung rechnen! Der Prozessor allein ist etwa 400% schneller, wenn er viele Threads verbraucht (was ich tue).

Ich befand mich in der folgenden Situation:

Mein Code braucht ungefähr eine Woche, um 8 Jahre Daten zu verarbeiten (jeder Datenpunkt ist 2s ~ 126'000'000 Preispunkte). Inzwischen ist die nächste Generation von Prozessoren und Grafikkarten nur noch ein paar Monate entfernt und sehr vielversprechend.

Die zu verarbeitende Datenmenge ist immens, und so bin ich in die Code-Performance-Optimierung eingestiegen. Ich hatte bereits einige Erfahrung mit Multi-Threaded-Arbeitern, um mehrere Aufgaben gleichzeitig zu erledigen. Dadurch hatte ich bereits etwas weniger als die 3,5-fache Leistung, da meine CPU über 4 Kerne verfügt. Es dauerte nun zwei Tage, um Daten aus 8 Jahren zu verarbeiten. Das war immer noch zu viel. Wenn ich Backtests durchführe, möchte ich die Ergebnisse sehen. Und zwar schnell.

Ich musste mich mehr mit der Leistungsoptimierung befassen und entwickelte meine eigene Worker-Abstraktion auf der Grundlage der Aufgabe in c#. Im Grunde implementiert sie eine Herstellungsweise, die ich in meinem Praktikum an der INA Lahr gelernt habe. Es ist, als hätte man eine Maschine (oder einen Arbeiter) mit einer Eingabewarteschlange und einer Ausgabewarteschlange. Die Warteschlange wirkt wie ein Puffer und kann dazu beitragen, dass jeder Cpu-Kern die Arbeit gleichmäßig verteilen kann. Es ist wie eine modulare, skalierbare Arbeiter-Pipeline, in der die Arbeiter Artikel aus einer Warteschlange oder einem Beutel entnehmen und verarbeiten können.

Das gab auch einen großen Leistungsschub. Ich konnte jetzt alle Daten in etwa einer Nacht verarbeiten, aber ich beschloss, sie noch weiter zu replizieren, nur um zu sehen, wie weit sie gehen können. Ich habe eine Visual Studio-Erweiterung "dotTrace" abonniert, die bei der Suche nach Engpässen innerhalb des Codes hervorragend funktioniert. Man kann einen Trace aufzeichnen und anschließend Funktion für Funktion sehen, wie lange die Ausführung dauert. Ich fand eine Funktion, die ich überhaupt nicht erwartet hatte - der Output String Builder drosselte die gesamte Pipeline. Mehr dazu finden Sie in der stack overflow Frage

Alles in allem ist der Prozess recht einfach:

  1. Identifizieren Sie die größte Leistungsbelastung
  2. Eliminate it
  3. Machen Sie so weiter, bis Sie eine vernünftige Leistung erbracht haben.

Im obigen Beispiel wäre dies der CLR-Arbeitnehmer-Prozess mit der ID 10584. Dies klingt zu diesem Zeitpunkt etwas verwirrend, aber JetBrains hat den Aufrufbaum auf der rechten Seite, wo wir sehen können, welche Funktion verwendet wird:

Schlussfolgerungen und Takeaways

Ich weiß, dass es in diesem Bereich noch mehr Leistung gäbe, aber im Moment bin ich mit dem Ergebnis recht zufrieden.

Im Moment vergehen 2 Jahre wie im Flug in weniger als 4 Minuten, und ich habe einen Gang zugelegt, wenn die Aktionen genauer beobachtet werden sollen.

screenshot of backtester

Auch die Equity-Linie sowie die Statistik werden gespeichert. Es ist möglich, so viele Konten und Strategien zu simulieren / laufen zu lassen, wie man will, mit nur geringem Leistungsabfall.

Ich habe bereits verschiedene Strategien mit Indikatoren und so weiter ausprobiert. Ohne viel versprechende Ergebnisse. Immerhin habe ich eine gewinnbringende Strategie gefunden, die stattdessen nichts von all diesen Dingen tut. Sie folgt weder dem Trend, noch setzt sie gegen ihn. Sie versucht nicht, etwas vorherzusagen. Weder den perfekten Einstiegspunkt noch den perfekten Ausstieg. Es ist ganz einfach, aber ich möchte nicht näher auf die Details der Strategie eingehen. Denken Sie über den Tellerrand hinaus, und Sie können etwas finden.

equity line going up

Das ist eine satte 20%ige jährliche Rendite. Fairerweise muss man sagen, dass ich mit der Buy-and-Hold-Strategie mehr Platz gemacht hätte, aber auf der anderen Seite sage ich nichts voraus, wir haben diese irrsinnigen Spitzen (und Stürze) nicht.

Das ist jetzt etwas, worauf ich aufbauen und sehen kann, was möglich ist und was nicht. Eine vollständige Marktsimulation im Sandkasten. Eine Testumgebung mit nahezu unbegrenzten Möglichkeiten.

Das war's für heute, und ich hoffe, Sie haben den Einblick in einige meiner laufenden Projekte genossen.