Die beste Programmiersprache für algorithmische Handelssysteme?

Schriftsteller:Gutes, Erstellt: 2019-02-12 10:33:36, aktualisiert:

Eine der häufigsten Fragen, die ich im Briefkasten erhalte, ist Was ist die beste Programmiersprache für den algorithmischen Handel?. Die kurze Antwort ist, dass es keine beste Sprache gibt. Strategieparameter, Leistung, Modularität, Entwicklung, Widerstandsfähigkeit und Kosten müssen alle berücksichtigt werden. Dieser Artikel wird die notwendigen Komponenten einer algorithmischen Handelssystemarchitektur skizzieren und wie Entscheidungen über die Implementierung die Sprachauswahl beeinflussen.

Zunächst werden die wichtigsten Komponenten eines algorithmischen Handelssystems, wie z. B. die Forschungsinstrumente, der Portfolioptimierer, der Risikomanager und die Ausführungsmaschine, betrachtet. Anschließend werden verschiedene Handelsstrategien untersucht und wie sie das Design des Systems beeinflussen. Insbesondere wird die Häufigkeit des Handels und das wahrscheinliche Handelsvolumen diskutiert.

Nach der Auswahl der Handelsstrategie ist es notwendig, das gesamte System zu konstruieren. Dies umfasst die Auswahl der Hardware, des Betriebssystems (s) und die Systemwiderstandsfähigkeit gegen seltene, potenziell katastrophale Ereignisse. Während die Architektur in Betracht gezogen wird, muss der Leistung gebührend Rechnung getragen werden - sowohl den Forschungswerkzeugen als auch der Live-Ausführungsumgebung.

Was versucht das Handelssystem zu tun?

Bevor man sich für die best Sprache entscheidet, mit der man ein automatisiertes Handelssystem schreiben soll, muss man die Anforderungen definieren. Wird das System rein ausführungsbasiert sein? Wird das System ein Risikomanagement- oder Portfoliokonstruktionsmodul benötigen? Wird das System einen leistungsstarken Backtester benötigen? Für die meisten Strategien kann das Handelssystem in zwei Kategorien unterteilt werden: Forschung und Signalgenerierung.

Die Forschung befasst sich mit der Bewertung der Strategieleistung gegenüber historischen Daten. Der Prozess der Bewertung einer Handelsstrategie gegenüber früheren Marktdaten wird als Backtesting bezeichnet. Die Datengröße und die algorithmische Komplexität haben einen großen Einfluss auf die Rechenintensität des Backtesters.

Bei der Signalgenerierung handelt es sich um die Generierung einer Reihe von Handelssignalen aus einem Algorithmus und das Senden solcher Aufträge an den Markt, in der Regel über eine Maklergesellschaft. Für bestimmte Strategien ist ein hohes Leistungsniveau erforderlich. I/O-Probleme wie Netzwerkbandbreite und Latenz sind oft der einschränkende Faktor bei der Optimierung von Ausführungssystemen.

Art, Häufigkeit und Umfang der Strategie

Die Art der eingesetzten algorithmischen Strategie hat erhebliche Auswirkungen auf das Design des Systems. Es ist notwendig, die zu handelnden Märkte, die Konnektivität zu externen Datenanbietern, die Häufigkeit und das Volumen der Strategie, den Kompromiss zwischen Leichtigkeit der Entwicklung und Leistungsoptimierung sowie alle erforderlichen kundenspezifischen Hardware, einschließlich lokalisierter kundenspezifischer Server, GPUs oder FPGAs, zu berücksichtigen.

Die Technologieentscheidungen für eine Niedrigfrequenz-US-Aktienstrategie unterscheiden sich erheblich von denen für eine Hochfrequenz-statistische Arbitrage-Strategie, die auf dem Futures-Markt gehandelt wird.

Es wird notwendig sein, die Konnektivität mit dem Anbieter, die Struktur aller APIs, die Aktualität der Daten, die Speicheranforderungen und die Widerstandsfähigkeit im Falle eines Offline-Venders zu berücksichtigen. Es ist auch ratsam, schnellen Zugriff auf mehrere Anbieter zu haben! Verschiedene Instrumente haben alle ihre eigenen Speicherfrequenzen, zu denen Beispiele mehrere Tickersymbole für Aktien und Ablaufdaten für Futures (ganz zu schweigen von spezifischen OTC-Daten) gehören. Dies muss beim Plattformdesign berücksichtigt werden.

Strategiefrequenz ist wahrscheinlich einer der wichtigsten Treiber für die Definition des Technologie-Stacks.

Eine Strategie, die die Sekundärbars übersteigt (d. h. Tick-Daten), führt zu einem leistungsorientierten Design als primäre Anforderung. Für Hochfrequenzstrategien muss eine erhebliche Menge an Marktdaten gespeichert und ausgewertet werden.

Um die umfangreichen Datenmengen zu verarbeiten, die für HFT-Anwendungen benötigt werden, muss ein weitgehend optimiertes Backtester und Ausführungssystem verwendet werden. C / C ++ (möglicherweise mit einem Assembler) ist wahrscheinlich der stärkste Sprachkandidat. Ultra-hohe Frequenzstrategien erfordern fast sicher kundenspezifische Hardware wie FPGA, Exchange-Colocation und Kernel / Netzwerk-Schnittstellen-Tuning.

Forschungssysteme

Forschungssysteme beinhalten in der Regel eine Mischung aus interaktiver Entwicklung und automatisiertem Skripting. Das erstere findet häufig in einer IDE wie Visual Studio, MatLab oder R Studio statt. Das letztere beinhaltet umfangreiche numerische Berechnungen über zahlreiche Parameter und Datenpunkte. Dies führt zu einer Sprachauswahl, die eine einfache Umgebung zum Testen von Code bietet, aber auch ausreichende Leistung bietet, um Strategien über mehrere Parameterdimensionen zu bewerten.

Typische IDE's in diesem Bereich sind Microsoft Visual C++/C#, das umfangreiche Debugging-Dienstprogramme, Code-Completing-Funktionen (über Intellisense) und einfache Übersichten des gesamten Projektstacks (über die Datenbank ORM, LINQ) enthält; MatLab, das für umfangreiche numerische lineare Algebra und vektorisierte Operationen konzipiert wurde, aber auf eine interaktive Konsolenart; R Studio, das die Rstatistical-Sprachkonsole in eine vollwertige IDE umwickelt; Eclipse IDE für Java Linux und C++; und halbproprietäre IDE's wie Enthought Canopy für Python, die Datenanalysebibliotheken wie NumPy, SciPy, scikit-learn und pandas in einer einzigen interaktiven (Konsolen-) Umgebung umfassen.

Für das numerische Backtesting sind alle oben genannten Sprachen geeignet, obwohl es nicht notwendig ist, eine GUI/IDE zu verwenden, da der Code im Hintergrund ausgeführt wird. Die wichtigste Überlegung in dieser Phase ist die Ausführungsgeschwindigkeit. Eine kompilierte Sprache (wie C++) ist oft nützlich, wenn die Backtestparameterdimensionen groß sind. Denken Sie daran, dass es notwendig ist, sich vor solchen Systemen zu hüten, wenn dies der Fall ist!

Interpretierte Sprachen wie Python verwenden häufig leistungsstarke Bibliotheken wie NumPy/pandas für den Backtesting-Schritt, um ein angemessenes Maß an Wettbewerbsfähigkeit mit kompilierten Äquivalenten aufrechtzuerhalten. Letztendlich wird die für das Backtesting gewählte Sprache durch spezifische algorithmische Bedürfnisse sowie die Bandbreite der in der Sprache verfügbaren Bibliotheken bestimmt (mehr dazu unten).

Portfoliokonstruktion und Risikomanagement

Die Portfoliokonstruktion und die Risikomanagementkomponenten werden oft von den algorithmischen Einzelhändlern übersehen. Dies ist fast immer ein Fehler. Diese Tools bieten den Mechanismus, mit dem Kapital erhalten wird. Sie versuchen nicht nur, die Anzahl der riskanten Wetten zu verringern, sondern auch den Abwanderungsgrad der Trades selbst zu minimieren, wodurch die Transaktionskosten reduziert werden.

So ist es einfach, eine stabile Strategie zu erstellen, da der Portfoliokonstruktionsmechanismus und der Risikomanager leicht modifiziert werden können, um mehrere Systeme zu handhaben. Daher sollten sie zu Beginn der Gestaltung eines algorithmischen Handelssystems als wesentliche Komponenten angesehen werden.

Die Aufgabe des Portfoliokonstruktionssystems besteht darin, eine Reihe von gewünschten Geschäften zu erstellen und die Reihe der tatsächlichen Geschäfte zu erstellen, die den Abwanderungsgrad minimieren, die Risikopositionen gegenüber verschiedenen Faktoren (z. B. Sektoren, Anlageklassen, Volatilität usw.) aufrechterhalten und die Kapitalzuweisung zu verschiedenen Strategien in einem Portfolio optimieren.

Die Portfoliokonstruktion reduziert sich häufig auf ein lineares Algebraproblem (z. B. eine Matrixfaktorisierung) und die Leistung hängt daher stark von der Effektivität der verfügbaren numerischen Linearalgebra-Implementierung ab. Zu den gängigen Bibliotheken gehören uBLAS, LAPACK und NAG für C++. MatLab verfügt auch über weitgehend optimierte Matrixoperationen. Python nutzt für solche Berechnungen NumPy/SciPy. Ein häufig wieder ausgeglichenes Portfolio benötigt eine kompilierte (und gut optimierte!) Matrixbibliothek, um diesen Schritt durchzuführen, um das Handelssystem nicht zu behindern.

Das Risikomanagement ist ein weiterer äußerst wichtiger Bestandteil eines algorithmischen Handelssystems. Das Risiko kann in vielen Formen auftreten: Erhöhte Volatilität (obwohl dies für bestimmte Strategien als wünschenswert angesehen werden kann!), Erhöhte Korrelationen zwischen Anlageklassen, Ausfall der Gegenpartei, Serverunterbrechungen, black swan Ereignisse und unentdeckte Fehler im Handelscode, um nur einige zu nennen.

Risikomanagement-Komponenten versuchen, die Auswirkungen übermäßiger Volatilität und Korrelation zwischen Anlageklassen und deren nachfolgenden Auswirkungen auf das Handelskapital zu antizipieren. Oft reduziert sich dies auf eine Reihe von statistischen Berechnungen wie Monte-Carlo Stresstests. Dies ist den Rechenanforderungen einer Derivatenpreismaschine sehr ähnlich und wird als solche CPU-gebunden sein. Diese Simulationen sind sehr parallelisierbar (siehe unten) und es ist in gewissem Maße möglich, Hardware an das Problem zu werfen.

Ausführungssysteme

Die Aufgabe des Ausführungssystems besteht darin, gefilterte Handelssignale aus den Komponenten Portfolio-Konstruktion und Risikomanagement zu empfangen und an eine Maklergesellschaft oder andere Mittel des Marktzugangs weiterzuleiten. Für die Mehrheit der algorithmischen Handelsstrategien im Einzelhandel beinhaltet dies eine API- oder FIX-Verbindung zu einer Maklergesellschaft wie Interactive Brokers. Zu den wichtigsten Überlegungen bei der Entscheidung über eine Sprache gehören die Qualität der API, die Verfügbarkeit von Sprachwrappern für eine API, die Ausführungsfrequenz und der erwartete Rutsch.

Die Qualität der API bezieht sich darauf, wie gut sie dokumentiert ist, welche Art von Leistung sie bietet, ob sie eine eigenständige Software benötigt, auf die zugegriffen werden kann, oder ob ein Gateway kopflos (d. h. ohne GUI) eingerichtet werden kann. Im Fall von Interactive Brokers muss das Trader WorkStation-Tool in einer GUI-Umgebung ausgeführt werden, um auf ihre API zugreifen zu können. Ich musste einmal eine Desktop-Ubuntu-Edition auf einen Amazon Cloud-Server installieren, um aus diesem Grund remote auf Interactive Brokers zugreifen zu können!

Die meisten APIs bieten eine C++- und/oder Java-Schnittstelle. Es liegt in der Regel an der Community, sprachspezifische Wrapper für C#, Python, R, Excel und MatLab zu entwickeln. Beachten Sie, dass bei jedem zusätzlichen Plugin (insbesondere API-Wrapper) die Möglichkeit besteht, dass sich Fehler in das System einschleichen. Testen Sie immer solche Plugins und stellen Sie sicher, dass sie aktiv gewartet werden.

Die Ausführungsfrequenz ist im Ausführungsalgorithmus von größter Bedeutung. Beachten Sie, dass Hunderte von Aufträgen pro Minute gesendet werden können und als solche Leistung kritisch ist.

Statically-typed Sprachen (siehe unten) wie C ++ / Java sind im Allgemeinen optimal für die Ausführung, aber es gibt einen Kompromiss in Entwicklungszeit, Test und einfache Wartung. Dynamisch-typierte Sprachen, wie Python und Perl sind jetzt im Allgemeinen schnell genug . Stellen Sie immer sicher, dass die Komponenten in einer modularen Weise (siehe unten) entworfen sind, so dass sie ausgetauscht werden können aus, wie das System skaliert.

Architekturplanung und -entwicklung

Die Komponenten eines Handelssystems, seine Frequenz- und Volumenanforderungen wurden oben erörtert, aber die Systeminfrastruktur muss noch abgedeckt werden. Diejenigen, die als Einzelhändler agieren oder in einem kleinen Fonds arbeiten, werden wahrscheinlich viele Hüte tragen. Es wird notwendig sein, das Alpha-Modell, das Risikomanagement und die Ausführungsparameter sowie die endgültige Implementierung des Systems abzudecken.

Sorgen trennen

Eine der wichtigsten Entscheidungen, die zu Beginn getroffen werden müssen, ist, wie man die Anliegen eines Handelssystems trennt.

Durch die Exposition von Schnittstellen an jeder der Komponenten ist es leicht, Teile des Systems für andere Versionen auszutauschen, die die Leistung, Zuverlässigkeit oder Wartung unterstützen, ohne einen externen Abhängigkeitscode zu ändern. Dies ist die "beste Praxis" für solche Systeme. Für Strategien mit niedrigeren Frequenzen werden solche Praktiken empfohlen. Für den Ultra-Hochfrequenzhandel muss das Regelbuch möglicherweise ignoriert werden, um das System für noch mehr Leistung zu optimieren. Ein engere Verbindung kann wünschenswert sein.

Die Erstellung einer Komponentenkarte eines algorithmischen Handelssystems ist ein Artikel an sich wert. Ein optimaler Ansatz besteht jedoch darin, sicherzustellen, dass separate Komponenten für die historischen und Echtzeit-Marktdateninputs, Datenspeicherung, Datenzugriff API, Backtester, Strategieparameter, Portfoliokonstruktion, Risikomanagement und automatisierte Ausführungssysteme vorhanden sind.

Wenn zum Beispiel der verwendete Datenspeicher derzeit unterdurchschnittlich leistungsfähig ist, auch bei signifikanten Optimierungsniveaus, kann er mit minimalen Umschreibungen an der Dateneinnahme- oder Datenzugriffs-API ausgetauscht werden.

Ein weiterer Vorteil von getrennten Komponenten ist, dass sie eine Vielzahl von Programmiersprachen im gesamten System verwenden lassen. Es ist nicht notwendig, sich auf eine einzige Sprache zu beschränken, wenn die Kommunikationsmethode der Komponenten sprachunabhängig ist. Dies ist der Fall, wenn sie über TCP/IP, ZeroMQ oder ein anderes sprachunabhängiges Protokoll kommunizieren.

Als konkretes Beispiel betrachten wir den Fall eines Backtesting-Systems, das in C++ für die Leistung von number crunching geschrieben wird, während der Portfoliomanager und die Ausführungssysteme in Python mit SciPy und IBPy geschrieben werden.

Leistungsbezogene Erwägungen

Performance ist für die meisten Handelsstrategien ein wichtiger Faktor. Für Hochfrequenzstrategien ist sie der wichtigste Faktor. Performance umfasst eine Vielzahl von Themen, wie z. B. algorithmische Ausführungsgeschwindigkeit, Netzwerklatenz, Bandbreite, Daten-E/A, Gleichzeitigkeit/Parallelität und Skalierung. Jeder dieser Bereiche wird einzeln von großen Lehrbüchern behandelt, so dass dieser Artikel nur die Oberfläche jedes Themas kratzen wird. Architektur und Sprachauswahl werden nun in Bezug auf ihre Auswirkungen auf die Leistung diskutiert.

Die vorherrschende Weisheit, wie Donald Knuth, einer der Väter der Informatik, feststellte, ist, dass vorzeitige Optimierung die Wurzel allen Übels ist. Dies ist fast immer der Fall - außer beim Aufbau eines Hochfrequenz-Handelsalgorithmus! Für diejenigen, die sich für Niedrigfrequenzstrategien interessieren, ist ein allgemeiner Ansatz, ein System auf die einfachstmögliche Weise aufzubauen und erst zu optimieren, wenn Engpässe auftreten.

Profiling-Tools werden verwendet, um zu bestimmen, wo Engpässe entstehen. Profile können für alle oben aufgeführten Faktoren entweder in einer MS Windows oder Linux-Umgebung erstellt werden. Es gibt viele Betriebssystem- und Sprachwerkzeuge, die dazu verfügbar sind, sowie Dienstprogramme von Drittanbietern. Die Sprachauswahl wird nun im Kontext der Leistung diskutiert.

C++, Java, Python, R und MatLab enthalten alle leistungsstarke Bibliotheken (entweder als Teil ihres Standards oder extern) für grundlegende Datenstrukturen und algorithmische Arbeiten.

Eine Ausnahme ist, wenn eine hochgradig angepasste Hardwarearchitektur erforderlich ist und ein Algorithmus umfangreiche Nutzung proprietärer Erweiterungen (wie benutzerdefinierte Caches) vornimmt.

Die Latenz ist häufig ein Problem des Ausführungssystems, da sich die Recherchewerkzeuge in der Regel auf derselben Maschine befinden. Bei den ersteren kann die Latenz an mehreren Punkten entlang des Ausführungswegs auftreten. Datenbanken müssen abgerufen werden (Festplatten-/Netzwerklatenz), Signale generiert werden (Betriebssystem, Kern-Messaging-Latenz), Handelssignale gesendet (NIC-Latenz) und Aufträge verarbeitet werden (interne Latenz von Austauschsystemen).

Für Hochfrequenzoperationen ist es notwendig, sich mit Kerneloptimierung sowie Optimierung der Netzwerkübertragung vertraut zu machen.

Caching ist sehr nützlich im Toolkit eines quantitativen Handelsentwicklers. Caching bezieht sich auf das Konzept der Speicherung häufig aufgerufener Daten in einer Weise, die einen höheren Leistungszugriff ermöglicht, auf Kosten der potenziellen Verzögerung der Daten. Ein häufiger Anwendungsfall tritt in der Webentwicklung auf, wenn Daten aus einer diskgestützten relationalen Datenbank genommen und in den Speicher eingesetzt werden.

Für Handelssituationen kann Caching äußerst vorteilhaft sein. Zum Beispiel kann der aktuelle Zustand eines Strategieportfolios in einem Cache gespeichert werden, bis es wieder ausgeglichen wird, so dass die Liste nicht bei jeder Schleife des Handelsalgorithmus regeneriert werden muss. Eine solche Regeneration ist wahrscheinlich eine hohe CPU- oder Festplatten-E/A-Operation.

Caching ist jedoch nicht ohne Probleme. Die Regeneration von Cache-Daten auf einmal kann aufgrund der flüchtigen Natur der Cache-Speicherung erhebliche Anforderungen an die Infrastruktur stellen. Ein weiteres Problem ist Dog-Piling, bei dem mehrere Generationen einer neuen Cache-Kopie unter extrem hoher Last durchgeführt werden, was zu einem Kaskadenversagen führt.

Die dynamische Speicheraufteilung ist eine teure Operation bei der Ausführung von Software. Daher ist es für Hochleistungs-Handelsanwendungen unerlässlich, sich bewusst zu sein, wie Speicher während des Programmflusses zugewiesen und ausgegliedert wird. Neuere Sprachstandards wie Java, C # und Python führen alle eine automatische Müllentsammlung durch, die sich auf die Ausgabe dynamisch zugewiesenen Speichers bezieht, wenn Objekte außerhalb des Umfangs gehen.

Der Garbage-Sammel ist während der Entwicklung äußerst nützlich, da er Fehler reduziert und die Lesbarkeit unterstützt. Allerdings ist er für bestimmte Hochfrequenz-Handelsstrategien oft nicht optimal. In Java ist beispielsweise durch Abstimmung des Garbage-Sammlers und der Heap-Konfiguration eine hohe Leistung für HFT-Strategien möglich.

C++ bietet keinen nativen Garbage Collector an, weshalb es notwendig ist, sämtliche Speicheraufteilung/Aufteilung als Teil der Implementierung eines Objekts zu handhaben.

Viele Operationen in algorithmischen Handelssystemen sind parallelisierbar. Dies bezieht sich auf das Konzept, mehrere programmatische Operationen gleichzeitig, d.h. parallel, durchzuführen. Die sogenannten "verwirrend parallel" Algorithmen umfassen Schritte, die vollständig unabhängig von anderen Schritten berechnet werden können. Bestimmte statistische Operationen, wie Monte-Carlo-Simulationen, sind ein gutes Beispiel für verwirrend parallele Algorithmen, da jede zufällige Ziehung und die anschließende Pfadoperation ohne Kenntnis anderer Pfade berechnet werden können.

Andere Algorithmen sind nur teilweise parallelisierbar. Fluiddynamik-Simulationen sind ein solches Beispiel, bei dem die Berechnungsdomäne unterteilt werden kann, aber letztendlich müssen diese Domäne miteinander kommunizieren und die Operationen sind somit teilweise sequenziell. Parallelisierbare Algorithmen unterliegen dem Amdahls-Gesetz, das eine theoretische Obergrenze für die Leistungssteigerung eines parallelisierten Algorithmus vorsieht, wenn sie NN- getrennten Prozessen (z. B. auf einem CPU-Kern oder Thread) unterzogen wird.

Parallelisierung ist als Optimierungsmittel immer wichtiger geworden, da die Prozessor-Uhrgeschwindigkeiten stagniert sind, da neuere Prozessoren viele Kerne enthalten, mit denen parallele Berechnungen durchgeführt werden können. Der Aufstieg der Verbraucher-Grafik-Hardware (vor allem für Videospiele) hat zur Entwicklung von Grafikverarbeitungseinheiten (GPUs) geführt, die Hunderte von Kernen für hochkonkurrenzbetrieb enthalten. Solche GPUs sind jetzt sehr erschwinglich. Hochrangige Frameworks wie Nvidia's CUDA haben zu einer breiten Akzeptanz in der Wissenschaft und Finanzen geführt.

Eine solche GPU-Hardware eignet sich im Allgemeinen nur für den Forschungsaspekt der quantitativen Finanzen, während andere spezialisierte Hardware (einschließlich Field-Programmable Gate Arrays - FPGA) für (U) HFT verwendet werden.

Skalierung bezieht sich in Software-Engineering und Operations auf die Fähigkeit des Systems, kontinuierlich steigende Belastungen in Form von größeren Anfragen, höherer Prozessornutzung und mehr Speicherzuweisung zu bewältigen.

Während Systeme skalierbar gestaltet werden müssen, ist es oft schwierig vorherzusagen, wo ein Engpass auftreten wird. Strenge Logging, Testing, Profiling und Monitoring werden eine große Hilfe sein, um ein System skalierbar zu machen. Sprachen selbst werden oft als "unskalierbar" beschrieben. Dies ist normalerweise das Ergebnis von Fehlinformationen, anstatt der harten Tatsache. Es ist der gesamte Technologie-Stack, der für die Skalierbarkeit ermittelt werden sollte, nicht die Sprache.

Um die Fähigkeit zur Bewältigung von Spikes im System (d. h. plötzlicher Volatilität, die eine Reihe von Trades auslöst) weiter zu verbessern, ist es nützlich, eine Message-Queue-Architektur zu erstellen. Dies bedeutet einfach, ein Message-Queue-System zwischen Komponenten zu platzieren, so dass Bestellungen gestapelt werden, wenn eine bestimmte Komponente nicht in der Lage ist, viele Anfragen zu bearbeiten.

Statt dass Anfragen verloren gehen, werden sie einfach in einem Stapel gehalten, bis die Nachricht verarbeitet wird. Dies ist besonders nützlich, um Trades an eine Ausführungsmaschine zu senden. Wenn die Maschine unter starker Latenz leidet, wird sie Trades sichern. Eine Warteschlange zwischen dem Handelssignalgenerator und der Ausführungs-API wird dieses Problem auf Kosten eines potenziellen Handelsrutsches lindern. Ein angesehener Open-Source-Nachrichten-Warteschlange-Broker ist RabbitMQ.

Hardware und Betriebssysteme

Die Hardware, mit der Ihre Strategie ausgeführt wird, kann einen signifikanten Einfluss auf die Rentabilität Ihres Algorithmus haben. Dies ist auch kein Problem, das auf Hochfrequenzhändler beschränkt ist. Eine schlechte Wahl in Hardware und Betriebssystem kann zu einem Maschinenabsturz oder Neustart im unangemessenen Moment führen. Daher ist es notwendig zu überlegen, wo Ihre Anwendung sich befinden wird. Die Wahl liegt im Allgemeinen zwischen einer persönlichen Desktop-Maschine, einem Remote-Server, einem cloud Provider oder einem Exchange-Co-located Server.

Desktop-Maschinen sind einfach zu installieren und zu verwalten, vor allem mit neueren benutzerfreundlichen Betriebssystemen wie Windows 7/8, Mac OSX und Ubuntu. Desktop-Systeme besitzen jedoch einige erhebliche Nachteile. Die wichtigste ist, dass die Versionen von Betriebssystemen, die für Desktop-Maschinen entwickelt wurden, wahrscheinlich Neustart / Patching erfordern (und oft in den schlimmsten Zeiten!).

Die Verwendung von Hardware in einer häuslichen (oder lokalen Büro-) Umgebung kann zu Problemen mit der Internetverbindung und der Betriebszeit führen. Der Hauptvorteil eines Desktop-Systems besteht darin, dass für einen Bruchteil der Kosten eines Remote-Dedicated-Servers (oder Cloud-basierten Systems) mit vergleichbarer Geschwindigkeit erhebliche Rechenleistung erworben werden kann.

Ein dedizierter Server oder eine Cloud-basierte Maschine, obwohl oft teurer als eine Desktop-Option, ermöglicht eine bedeutendere Redundanzinfrastruktur, wie beispielsweise automatisierte Datensicherungen, die Fähigkeit, die Betriebszeit und die Fernüberwachung einfacher zu gewährleisten. Sie sind schwieriger zu verwalten, da sie die Fähigkeit erfordern, Remote-Login-Funktionen des Betriebssystems zu verwenden.

In Windows geschieht dies in der Regel über das GUI Remote Desktop Protocol (RDP). In Unix-basierten Systemen wird die Befehlszeile Secure Shell (SSH) verwendet. Die Unix-basierte Serverinfrastruktur ist fast immer Befehlszeile-basiert, was sofort die GUI-basierten Programmierwerkzeuge (wie MatLab oder Excel) unbrauchbar macht.

Ein Co-located Server, wie der Ausdruck auf den Kapitalmärkten verwendet wird, ist einfach ein dedizierter Server, der sich in einer Börse befindet, um die Latenz des Handelsalgorithmus zu reduzieren.

Der letzte Aspekt bei der Auswahl der Hardware und der Wahl der Programmiersprache ist die Plattformunabhängigkeit. Ist es notwendig, dass der Code über mehrere verschiedene Betriebssysteme hinweg ausgeführt wird? Ist der Code für eine bestimmte Art von Prozessor-Architektur wie Intel x86/x64 konzipiert oder kann er auf RISC-Prozessoren wie denen von ARM ausgeführt werden? Diese Fragen hängen stark von der Häufigkeit und Art der implementierten Strategie ab.

Widerstandsfähigkeit und Prüfung

Einer der besten Möglichkeiten, um viel Geld beim algorithmischen Handel zu verlieren, ist die Schaffung eines Systems ohne Widerstandsfähigkeit. Dies bezieht sich auf die Haltbarkeit des Systems, wenn es seltenen Ereignissen wie Maklerinsolvenzen, plötzlicher Überschuss an Volatilität, regionweiter Ausfallzeiten für einen Cloud-Server-Anbieter oder der versehentlichen Löschung einer gesamten Handelsdatenbank unterliegt. Mit einer schlecht konzipierten Architektur können Jahre des Gewinns innerhalb von Sekunden beseitigt werden. Es ist absolut wichtig, Probleme wie Debugging, Testing, Logging, Backups, hohe Verfügbarkeit und Überwachung als Kernkomponenten Ihres Systems zu berücksichtigen.

Es ist wahrscheinlich, dass bei jeder vernünftigerweise komplizierten kundenspezifischen quantitativen Handelsanwendung mindestens 50% der Entwicklungszeit für Fehlerbehebung, Tests und Wartung aufgewendet werden.

Fast alle Programmiersprachen verfügen entweder über einen zugehörigen Debugger oder über anerkannte Alternativen von Drittanbietern. Im Wesentlichen ermöglicht ein Debugger die Ausführung eines Programms mit der Einfügung willkürlicher Bruchpunkte in den Codepfad, die die Ausführung vorübergehend stoppen, um den Zustand des Systems zu untersuchen. Der Hauptvorteil des Debuggings besteht darin, dass das Verhalten des Codes vor einem bekannten Absturzpunkt untersucht werden kann.

Debugging ist eine wesentliche Komponente in der Toolbox für die Analyse von Programmierfehlern. Sie werden jedoch häufiger in kompilierten Sprachen wie C++ oder Java verwendet, da interpretierte Sprachen wie Python aufgrund weniger LOC und weniger verblüffender Anweisungen oft einfacher zu debuggen sind. Trotz dieser Tendenz wird Python mit der pdb geliefert, die ein ausgeklügeltes Debugging-Tool ist. Die Microsoft Visual C++ IDE verfügt über umfangreiche GUI-Debugging-Dienstprogramme, während für den Befehlszeilenprogrammierer Linux C++ der gdb-Debugger existiert.

Testing in der Softwareentwicklung bezieht sich auf den Prozess der Anwendung bekannter Parameter und Ergebnisse auf bestimmte Funktionen, Methoden und Objekte innerhalb einer Codebasis, um das Verhalten zu simulieren und mehrere Code-Wege zu bewerten, um sicherzustellen, dass sich ein System so verhält, wie es sollte. Ein neueres Paradigma ist als Test Driven Development (TDD) bekannt, bei dem Testcode gegen eine spezifizierte Schnittstelle ohne Implementierung entwickelt wird. Vor Abschluss der eigentlichen Codebasis werden alle Tests scheitern.

TDD erfordert eine umfangreiche vorläufige Spezifikationsgestaltung sowie ein gesundes Maß an Disziplin, um erfolgreich durchgeführt zu werden. In C++ bietet Boost ein Unit-Testing-Framework. In Java existiert die JUnit-Bibliothek, um denselben Zweck zu erfüllen. Python hat auch das unittest-Modul als Teil der Standardbibliothek. Viele andere Sprachen besitzen Unit-Testing-Frameworks und oft gibt es mehrere Optionen.

In einer Produktionsumgebung ist ein ausgeklügeltes Logging absolut unerlässlich. Logging bezieht sich auf den Prozess der Ausgabe von Nachrichten, mit unterschiedlichem Schweregrad, bezüglich des Ausführungsverhaltens eines Systems in eine flache Datei oder Datenbank. Logs sind eine erste Angriffslinie bei der Suche nach unerwartetem Programmlaufzeitverhalten. Leider werden die Mängel eines Logging-Systems meist erst nach der Tat entdeckt!

Sowohl Microsoft Windows als auch Linux verfügen über umfangreiche Systemprotokolle und Programmiersprachen sind in der Regel mit Standardprotokolle-Bibliotheken ausgestattet, die die meisten Anwendungsfälle abdecken.

Während das Loggen eines Systems Informationen darüber liefert, was in der Vergangenheit geschehen ist, wird die Überwachung einer Anwendung Einblicke in das geben, was gerade passiert. Alle Aspekte des Systems sollten für die Überwachung berücksichtigt werden. System-Ebene Metriken wie Festplattenverbrauch, verfügbarer Speicher, Netzwerkbandbreite und CPU-Verwendung liefern grundlegende Lastinformationen.

Handelsindikatoren wie ungewöhnliche Preise/Volumen, plötzliche schnelle Abzüge und Kontoexposition für verschiedene Sektoren/Märkte sollten auch kontinuierlich überwacht werden.

Systemüberwachung ist oft die Domäne des Systemadministrators oder Operations Managers. Als einziger Handelsentwickler müssen diese Metriken jedoch als Teil des größeren Designs festgelegt werden. Es gibt viele Lösungen für die Überwachung: proprietär, gehostet und Open Source, die eine umfangreiche Anpassung von Metriken für einen bestimmten Anwendungsfall ermöglichen.

Bei einem Trading-System sollten die wichtigsten Anliegen Sicherungen und hohe Verfügbarkeit sein. Betrachten Sie folgende zwei Fragen: 1) Wenn eine gesamte Produktionsdatenbank von Marktdaten und Handelsgeschichte gelöscht wird (ohne Sicherungen), wie wird sich der Forschungs- und Ausführungsalgorithmus beeinflussen? 2) Wenn das Trading-System für einen längeren Zeitraum (mit offenen Positionen) unter einem Ausfall leidet, wie werden die Kontowerte und die laufende Rentabilität beeinflusst? Die Antworten auf beide Fragen sind oft ernüchternd!

Es ist unerlässlich, ein System zur Sicherung von Daten und auch zur Erprobung der Wiederherstellung solcher Daten einzuführen. Viele Personen testen keine Wiederherstellungsstrategie. Wenn die Wiederherstellung nach einem Absturz nicht in einer sicheren Umgebung getestet wurde, welche Garantien gibt es, dass die Wiederherstellung im schlimmsten Moment verfügbar ist?

In diesem Zusammenhang möchte ich auf eine Reihe von Aspekten hinweisen, die sich auf das System beziehen, und zwar auf die Bereiche, in denen die Datenverarbeitung und die Datenverarbeitung in den einzelnen Mitgliedstaaten erfolgt.

Eine Sprache wählen

In diesem Zusammenhang ist es wichtig, daß sich die verschiedenen Faktoren, die bei der Entwicklung eines benutzerdefinierten algorithmischen Hochleistungshandelssystems entstehen, im Detail darlegen.

Typsysteme

Bei der Auswahl einer Sprache für einen Handelsstack ist es notwendig, das Typsystem zu berücksichtigen. Die Sprachen, die für den algorithmischen Handel von Interesse sind, sind entweder statisch oder dynamisch getypt. Eine statisch getyptete Sprache führt während des Kompilierungsprozesses die Überprüfungen der Typen (z. B. ganze Zahlen, Floats, benutzerdefinierte Klassen usw.) durch.

Für ein hochnumerisches System wie eine algorithmische Handelsmaschine kann die Typprüfung zur Kompilierungszeit äußerst vorteilhaft sein, da sie viele Fehler beseitigen kann, die ansonsten zu numerischen Fehlern führen würden. Die Typprüfung erfasst jedoch nicht alles, und hier kommt die Ausnahmebehandlung ein, da unerwartete Operationen behandelt werden müssen. Dynamische Sprachen (d.h. dynamisch getypte Sprachen) können oft zu Laufzeitfehlern führen, die ansonsten mit einer Kompilierungszeit-Typprüfung erfasst würden. Aus diesem Grund entstand das Konzept von TDD (siehe oben) und Unit-Testing, das bei richtiger Durchführung oft mehr Sicherheit bietet als die Kompilierungszeitprüfung allein.

Ein weiterer Vorteil statisch getypter Sprachen besteht darin, dass der Compiler viele Optimierungen vornehmen kann, die ansonsten für die dynamisch getypte Sprache nicht verfügbar sind, einfach weil der Typ (und damit die Speicheranforderungen) zur Kompilierungszeit bekannt sind.

Open Source oder proprietär?

Eine der größten Möglichkeiten, die einem algorithmischen Handelsentwickler zur Verfügung stehen, besteht darin, ob er proprietäre (kommerzielle) oder Open-Source-Technologien verwendet. Beide Ansätze haben Vor- und Nachteile. Es ist notwendig zu berücksichtigen, wie gut eine Sprache unterstützt wird, die Aktivität der Gemeinschaft, die eine Sprache umgibt, die einfache Installation und Wartung, die Qualität der Dokumentation und alle Lizenz- / Wartungskosten.

Der Microsoft.NET-Stack (einschließlich Visual C++, Visual C#) und MathWorks MatLab sind zwei der größeren proprietären Möglichkeiten zur Entwicklung benutzerdefinierter algorithmischer Handelssoftware.

Microsoft und MathWorks bieten beide umfangreiche hochwertige Dokumentation für ihre Produkte. Darüber hinaus sind die Gemeinschaften rund um jedes Tool sehr groß mit aktiven Webforen für beide. Die.NET-Software ermöglicht eine kohärente Integration mit mehreren Sprachen wie C ++, C # und VB sowie eine einfache Verknüpfung mit anderen Microsoft-Produkten wie der SQL Server-Datenbank über LINQ. MatLab verfügt auch über viele Plugins / Bibliotheken (einige kostenlos, einige kommerziell) für fast jede quantitative Forschungsdomain.

Es gibt auch Nachteile. Bei beiden Softwareanwendungen sind die Kosten für einen Einzelhändler nicht unerheblich (obwohl Microsoft eine Einstiegsversion von Visual Studio kostenlos anbietet). Microsoft-Tools spielen gut miteinander, integrieren sich aber weniger gut mit externem Code. Visual Studio muss auch unter Microsoft Windows ausgeführt werden, was wohl weitaus weniger leistungsfähig ist als ein gleichwertiger Linux-Server, der optimal abgestimmt ist.

MatLab fehlt auch an einigen wichtigen Plugins wie einem guten Wrapper um die Interactive Brokers API, einer der wenigen Broker, die für einen leistungsstarken algorithmischen Handel geeignet sind. Das Hauptproblem mit proprietären Produkten ist die fehlende Verfügbarkeit des Quellcodes. Dies bedeutet, dass beide Tools, wenn Ultra-Performance wirklich erforderlich ist, viel weniger attraktiv sind.

Open-Source-Tools sind seit einiger Zeit branchenüblich. Ein großer Teil des alternativen Asset-Raums nutzt Open-Source-Linux, MySQL/PostgreSQL, Python, R, C++ und Java in leistungsstarken Produktionsrollen. Sie sind jedoch weit davon entfernt, sich auf diese Domäne zu beschränken. Python und R enthalten insbesondere eine Fülle von umfangreichen numerischen Bibliotheken, um fast jede denkbare Art von Datenanalyse durchzuführen, oft mit Ausführungsgeschwindigkeiten, die mit kompilierten Sprachen vergleichbar sind, mit bestimmten Vorbehalten.

Der Hauptvorteil der Verwendung von interpretierten Sprachen ist die Geschwindigkeit der Entwicklungszeit. Python und R erfordern viel weniger Codezeilen (LOC), um ähnliche Funktionalität zu erreichen, hauptsächlich aufgrund der umfangreichen Bibliotheken.

Da die Zeit als Entwickler extrem wertvoll ist und die Ausführungsgeschwindigkeit oft weniger (außer im HFT-Raum) ist, lohnt es sich, einen umfassenden Überblick über einen Open-Source-Technologie-Stack zu haben.

Open-Source-Tools leiden oft unter dem Mangel an einem dedizierten kommerziellen Supportvertrag und laufen optimal auf Systemen mit weniger vergebenden Benutzeroberflächen. Ein typischer Linux-Server (wie Ubuntu) ist oft vollständig an der Befehlszeile orientiert. Darüber hinaus können Python und R für bestimmte Ausführungsaufgaben langsam sein. Es gibt Mechanismen zur Integration mit C ++, um die Ausführungsgeschwindigkeit zu verbessern, aber es erfordert einige Erfahrung in der Mehrsprachprogrammierung.

Während proprietäre Software nicht immun gegen Abhängigkeits-/Versionsprobleme ist, ist es viel seltener, dass man in solchen Umgebungen mit falschen Bibliotheksversionen zu tun hat.

Ich werde hier meine persönliche Meinung wagen und feststellen, dass ich alle meine Handelswerkzeuge mit Open-Source-Technologien baue. Insbesondere verwende ich: Ubuntu, MySQL, Python, C ++ und R. Die Reife, die Größe der Community, die Fähigkeit, tief zu graben, wenn Probleme auftreten und die geringere Gesamtkostenberechtigung (TCO) überwiegen bei weitem die Einfachheit proprietärer GUI und einfache Installationen.

Batterien eingeschlossen?

Die Überschrift dieses Abschnitts bezieht sich auf die out of the box Fähigkeiten der Sprache - welche Bibliotheken enthält sie und wie gut sind sie? Hier haben ausgereifte Sprachen einen Vorteil gegenüber neueren Varianten.

C++ ist berühmt für seine Standard Template Library (STL), die eine Fülle von Hochleistungsdatenstrukturen und Algorithmen enthält. Python ist dafür bekannt, mit fast jeder anderen Art von System/Protokoll (insbesondere dem Web) kommunizieren zu können, meist durch seine eigene Standardbibliothek.

Außerhalb der Standardbibliotheken nutzt C++ die Boost-Bibliothek, die die fehlenden Teile der Standardbibliothek ausfüllt.

Python verfügt über die leistungsstarke NumPy/SciPy/Pandas Datenanalyse Bibliothekskombination, die für die algorithmische Handelsforschung eine breite Akzeptanz erlangt hat. Ferner gibt es leistungsstarke Plugins für den Zugriff auf die wichtigsten relationalen Datenbanken, wie MySQL++ (MySQL/C++), JDBC (Java/MatLab), MySQLdb (MySQL/Python) und psychopg2 (PostgreSQL/Python). Python kann sogar über das RPy-Plugin mit R kommunizieren!

Ein oft übersehener Aspekt eines Handelssystems in der Anfangsforschungs- und Designphase ist die Konnektivität zu einer Broker-API. Die meisten APIs unterstützen nativerweise C++ und Java, aber einige unterstützen auch C# und Python, entweder direkt oder mit Community-bereitgestellten Wrapper-Code zu den C++-APIs. Insbesondere können Interactive Brokers über das IBPy-Plugin verbunden werden. Wenn hohe Leistung erforderlich ist, werden Broker das FIX-Protokoll unterstützen.

Schlussfolgerung

Wie sich jetzt zeigt, ist die Wahl der Programmiersprache für ein algorithmisches Handelssystem nicht einfach und erfordert tiefes Nachdenken. Die wichtigsten Überlegungen sind Leistung, Entwicklungsfreundlichkeit, Widerstandsfähigkeit und Testen, Trennung von Bedenken, Vertrautheit, Wartung, Verfügbarkeit des Quellcodes, Lizenzkosten und Reife der Bibliotheken.

Der Vorteil einer getrennten Architektur besteht darin, dass Sprachen für verschiedene Aspekte eines Handelsstacks eingeschlossen werden können, wenn sich die Anforderungen ändern.


Mehr