Les ressources ont été chargées... Je charge...

Le meilleur langage de programmation pour les systèmes de trading algorithmique?

Auteur:La bonté, Créé: 2019-02-12 10:33:36, mis à jour:

L'une des questions les plus fréquentes que je reçois dans le courrier est Quel est le meilleur langage de programmation pour le trading algorithmique?. La réponse courte est qu'il n'y a pas de langage best. Les paramètres de stratégie, les performances, la modularité, le développement, la résilience et le coût doivent tous être considérés. Cet article décrira les composants nécessaires de l'architecture d'un système de trading algorithmique et comment les décisions concernant la mise en œuvre affectent le choix du langage.

Dans un premier temps, les principaux composants d'un système de négociation algorithmique seront considérés, tels que les outils de recherche, l'optimisateur de portefeuille, le gestionnaire de risque et le moteur d'exécution.

Une fois la stratégie de trading sélectionnée, il est nécessaire d'architecter l'ensemble du système. Cela inclut le choix du matériel, du système d'exploitation et de la résilience du système face à des événements rares et potentiellement catastrophiques.

Que cherche à faire le système commercial?

Avant de décider du "meilleur" langage avec lequel écrire un système de trading automatisé, il est nécessaire de définir les exigences. Le système sera-t-il purement basé sur l'exécution? Le système aura-t-il besoin d'un module de gestion des risques ou de construction de portefeuille? Le système aura-t-il besoin d'un backtester haute performance? Pour la plupart des stratégies, le système de trading peut être divisé en deux catégories: recherche et génération de signaux.

La recherche concerne l'évaluation de la performance d'une stratégie sur les données historiques. Le processus d'évaluation d'une stratégie de trading sur les données de marché antérieures est connu sous le nom de backtesting. La taille des données et la complexité algorithmique auront un grand impact sur l'intensité de calcul du backtester.

La génération de signaux consiste à générer un ensemble de signaux de trading à partir d'un algorithme et à envoyer de tels ordres sur le marché, généralement via un courtier.

Type, fréquence et volume de la stratégie

Le type de stratégie algorithmique utilisée aura une incidence substantielle sur la conception du système. Il faudra tenir compte des marchés négociés, de la connectivité avec les fournisseurs de données externes, de la fréquence et du volume de la stratégie, du compromis entre la facilité de développement et l'optimisation des performances, ainsi que de tout matériel personnalisé, y compris les serveurs personnalisés, les GPU ou les FPGA co-localisés qui pourraient être nécessaires.

Les choix technologiques pour une stratégie d'actions américaines à basse fréquence seront très différents de ceux d'une stratégie d'arbitrage statistique à haute fréquence sur le marché des contrats à terme.

Il sera nécessaire de prendre en compte la connectivité avec le fournisseur, la structure des API, la rapidité des données, les exigences de stockage et la résilience face à un fournisseur hors ligne. Il est également sage de disposer d'un accès rapide à plusieurs fournisseurs!

La fréquence de la stratégie est susceptible d'être l'un des principaux moteurs de la définition de la pile technologique.

Une stratégie dépassant les barres secondaires (c.-à-d. les données de tick) conduit à une conception axée sur les performances comme exigence principale.

Pour traiter les volumes importants de données nécessaires aux applications HFT, un backtester et un système d'exécution largement optimisés doivent être utilisés. C / C ++ (éventuellement avec un assembleur) est probablement le candidat de langage le plus fort.

Systèmes de recherche

Les systèmes de recherche impliquent généralement un mélange de développement interactif et de scripting automatisé. Le premier se déroule souvent dans un IDE tel que Visual Studio, MatLab ou R Studio. Ce dernier implique des calculs numériques étendus sur de nombreux paramètres et points de données. Cela conduit à un choix de langage fournissant un environnement simple pour tester le code, mais fournit également une performance suffisante pour évaluer les stratégies sur plusieurs dimensions de paramètres.

Les IDE typiques dans cet espace comprennent Microsoft Visual C++/C#, qui contient des utilitaires de débogage étendus, des capacités de complétion de code (via Intellisense) et des aperçus simples de l'ensemble de la pile de projets (via la base de données ORM, LINQ); MatLab, qui est conçu pour une algebra linéaire numérique étendue et des opérations vectorielles, mais de manière interactive; R Studio, qui enveloppe la console de langage Rstatistical dans un IDE à part entière; Eclipse IDE pour Java Linux et C++; et des IDE semi-propriétaires tels qu'Enthought Canopy pour Python, qui incluent des bibliothèques d'analyse de données telles que NumPy, SciPy, scikit-learn et pandas dans un seul environnement interactif (console).

Pour le backtesting numérique, tous les langages ci-dessus sont appropriés, bien qu'il ne soit pas nécessaire d'utiliser une interface graphique / IDE car le code sera exécuté en arrière-plan. La principale considération à ce stade est la vitesse d'exécution. Un langage compilé (comme C ++) est souvent utile si les dimensions des paramètres de backtesting sont grandes. Rappelez-vous qu'il est nécessaire d'être prudent avec de tels systèmes si c'est le cas!

Les langages interprétés tels que Python utilisent souvent des bibliothèques de haute performance telles que NumPy / pandas pour l'étape de backtesting, afin de maintenir un degré raisonnable de compétitivité avec les équivalents compilés.

Construction de portefeuille et gestion des risques

Les composantes de la construction de portefeuille et de la gestion des risques sont souvent négligées par les traders algorithmiques de détail. C'est presque toujours une erreur. Ces outils fournissent le mécanisme par lequel le capital sera préservé. Ils tentent non seulement d'atténuer le nombre de paris risqués, mais aussi de minimiser le désabonnement des transactions elles-mêmes, réduisant les coûts de transaction.

Les versions sophistiquées de ces composants peuvent avoir un effet significatif sur la qualité et la cohérence de la rentabilité. Il est facile de créer une stratégie stable car le mécanisme de construction du portefeuille et le gestionnaire de risque peuvent facilement être modifiés pour gérer plusieurs systèmes. Ils devraient donc être considérés comme des composants essentiels au début de la conception d'un système de trading algorithmique.

La tâche du système de construction de portefeuille est de prendre un ensemble de transactions souhaitées et de produire l'ensemble de transactions réelles qui minimisent le désabonnement, maintiennent les expositions à divers facteurs (tels que les secteurs, les classes d'actifs, la volatilité, etc.) et optimisent l'allocation du capital aux différentes stratégies d'un portefeuille.

La construction de portefeuille se réduit souvent à un problème d'algèbre linéaire (comme une facteurisation de matrice) et par conséquent les performances dépendent fortement de l'efficacité de l'implémentation d'algèbre linéaire numérique disponible. Les bibliothèques courantes incluent uBLAS, LAPACK et NAG pour C ++. MatLab possède également des opérations de matrice largement optimisées. Python utilise NumPy / SciPy pour de tels calculs. Un portefeuille rééquilibré nécessitera une bibliothèque de matrice compilée (et bien optimisée!) pour effectuer cette étape, afin de ne pas bloquer le système de trading.

La gestion des risques est une autre partie extrêmement importante d'un système de trading algorithmique. Le risque peut prendre de nombreuses formes: augmentation de la volatilité (bien que cela puisse être considéré comme souhaitable pour certaines stratégies!), augmentation des corrélations entre les classes d'actifs, défaut de paiement de la contrepartie, pannes de serveur, événements de "cygne noir" et bugs non détectés dans le code de trading, pour n'en nommer que quelques-uns.

Les composants de gestion des risques tentent d'anticiper les effets de la volatilité excessive et de la corrélation entre les classes d'actifs et leurs effets ultérieurs sur le capital de trading. Souvent, cela se réduit à un ensemble de calculs statistiques tels que les tests de Monte Carlo.

Systèmes d'exécution

Le travail du système d'exécution est de recevoir des signaux de trading filtrés des composants de construction de portefeuille et de gestion des risques et de les envoyer à un courtier ou à d'autres moyens d'accès au marché. Pour la majorité des stratégies de trading algorithmique de détail, cela implique une connexion API ou FIX à un courtier tel que Interactive Brokers.

La "qualité" de l'API fait référence à sa documentation, à ses performances, à sa nécessité d'un logiciel autonome ou à la possibilité d'établir une passerelle sans tête (c'est-à-dire sans interface graphique). Dans le cas des Interactive Brokers, l'outil Trader WorkStation doit être exécuté dans un environnement graphique pour accéder à leur API.

La plupart des API fourniront une interface C++ et/ou Java. Il appartient généralement à la communauté de développer des enveloppes spécifiques au langage pour C#, Python, R, Excel et MatLab. Notez qu'avec chaque plugin supplémentaire utilisé (en particulier les enveloppes API), il y a des risques de bugs dans le système. Testez toujours ces plugins et assurez-vous qu'ils sont activement maintenus.

La fréquence d'exécution est de la plus haute importance dans l'algorithme d'exécution. Notez que des centaines d'ordres peuvent être envoyés chaque minute et que la performance est donc essentielle.

Les langages de type statique (voir ci-dessous) tels que C ++ / Java sont généralement optimaux pour l'exécution, mais il existe un compromis dans le temps de développement, les tests et la facilité de maintenance. Les langages de type dynamique, tels que Python et Perl, sont maintenant généralement assez rapides. Assurez-vous toujours que les composants sont conçus de manière modulaire (voir ci-dessous) afin qu'ils puissent être échangés à mesure que le système évolue.

Processus de planification et de développement architecturaux

Les composants d'un système de négociation, ses exigences de fréquence et de volume ont été discutés ci-dessus, mais l'infrastructure du système n'a pas encore été couverte. Ceux qui agissent en tant que commerçant de détail ou travaillent dans un petit fonds porteront probablement beaucoup de chapeaux. Il sera nécessaire de couvrir le modèle alpha, la gestion des risques et les paramètres d'exécution, ainsi que la mise en œuvre finale du système. Avant de plonger dans des langages spécifiques, la conception d'une architecture de système optimale sera discutée.

Séparation des soucis

L'une des décisions les plus importantes qui doivent être prises dès le départ est de savoir comment "séparer les préoccupations" d'un système de négociation.

En exposant des interfaces à chacun des composants, il est facile de remplacer des parties du système par d'autres versions qui aident les performances, la fiabilité ou la maintenance, sans modifier le code de dépendance externe. C'est la "meilleure pratique" pour de tels systèmes. Pour les stratégies à fréquences plus basses, de telles pratiques sont recommandées. Pour le trading à très haute fréquence, le manuel de règles peut être ignoré au détriment de l'ajustement du système pour encore plus de performances. Un système plus étroitement couplé peut être souhaitable.

Cependant, une approche optimale consiste à s'assurer qu'il existe des composants distincts pour les entrées de données historiques et en temps réel du marché, le stockage de données, l'API d'accès aux données, le backtester, les paramètres de stratégie, la construction de portefeuille, la gestion des risques et les systèmes d'exécution automatisés.

Par exemple, si le stockage de données utilisé est actuellement sous-performant, même à des niveaux significatifs d'optimisation, il peut être remplacé avec des réécritures minimales à l'API d'ingestion de données ou d'accès aux données.

Un autre avantage des composants séparés est qu'il permet l'utilisation d'une variété de langages de programmation dans le système global. Il n'est pas nécessaire de se limiter à un seul langage si la méthode de communication des composants est indépendante du langage.

À titre d'exemple concret, considérons le cas d'un système de backtesting écrit en C++ pour la performance de number crunching, tandis que le gestionnaire de portefeuille et les systèmes d'exécution sont écrits en Python en utilisant SciPy et IBPy.

Considérations relatives aux performances

La performance est un facteur important pour la plupart des stratégies de trading. Pour les stratégies de fréquence plus élevée, c'est le facteur le plus important. Performance couvre un large éventail de problèmes, tels que la vitesse d'exécution algorithmique, la latence du réseau, la bande passante, l'E/S des données, la concurrence/parallélisme et l'évolutivité. Chacun de ces domaines est couvert individuellement par de grands manuels, donc cet article ne fera que gratter la surface de chaque sujet.

La sagesse prédominante, comme l'a déclaré Donald Knuth, l'un des pères de l'informatique, est que l'optimisation prématurée est la racine de tous les maux. C'est presque toujours le cas - sauf lors de la construction d'un algorithme de trading à haute fréquence!

Les outils de profilage sont utilisés pour déterminer où les goulots d'étranglement surviennent. Les profils peuvent être créés pour tous les facteurs énumérés ci-dessus, soit dans un environnement MS Windows ou Linux. Il existe de nombreux outils de système d'exploitation et de langage disponibles pour ce faire, ainsi que des utilitaires tiers. Le choix de la langue sera maintenant discuté dans le contexte de la performance.

C++, Java, Python, R et MatLab contiennent toutes des bibliothèques de haute performance (soit dans le cadre de leur norme, soit à l'extérieur) pour la structure de données de base et le travail algorithmique.

Une exception est si une architecture matérielle hautement personnalisée est requise et qu'un algorithme utilise largement des extensions propriétaires (telles que des caches personnalisées). Cependant, souvent, la "réinvention de la roue" gaspille du temps qui pourrait mieux être consacré au développement et à l'optimisation d'autres parties de l'infrastructure de trading. Le temps de développement est extrêmement précieux, en particulier dans le contexte des développeurs individuels.

La latence est souvent un problème du système d'exécution, car les outils de recherche sont généralement situés sur la même machine. Pour le premier, la latence peut se produire à plusieurs points le long du chemin d'exécution. Les bases de données doivent être consultées (latence disque / réseau), les signaux doivent être générés (système d'exploitation, latence de messagerie du noyau), les signaux commerciaux envoyés (latence NIC) et les commandes traitées (latence interne des systèmes d'échange).

Pour les opérations de fréquence plus élevée, il est nécessaire de se familiariser intimement avec l'optimisation du noyau ainsi qu'avec l'optimisation de la transmission du réseau.

La mise en cache est très utile dans la boîte à outils d'un développeur de trading quantitatif. La mise en cache fait référence au concept de stockage de données fréquemment consultées d'une manière qui permet un accès plus performant, au détriment de la stabilité potentielle des données. Un cas d'utilisation courant se produit dans le développement Web lors de la prise de données d'une base de données relationnelle prise en charge par disque et la mise en mémoire.

Pour les situations de trading, la mise en cache peut être extrêmement bénéfique. Par exemple, l'état actuel d'un portefeuille de stratégie peut être stocké dans un cache jusqu'à ce qu'il soit rééquilibré, de sorte que la liste n'ait pas besoin d'être régénérée à chaque boucle de l'algorithme de trading.

Cependant, la mise en cache n'est pas exempte de problèmes. La régénération des données de cache en une seule fois, en raison de la nature volatile du stockage de cache, peut imposer une demande importante sur l'infrastructure. Un autre problème est le dog-piling, où plusieurs générations d'une nouvelle copie de cache sont effectuées sous une charge extrêmement élevée, ce qui conduit à une défaillance en cascade.

L'allocation dynamique de mémoire est une opération coûteuse dans l'exécution de logiciels. Il est donc impératif pour les applications de trading de haute performance d'être bien conscient de la façon dont la mémoire est allouée et déalloquée pendant le flux du programme.

La collecte de déchets est extrêmement utile pendant le développement car elle réduit les erreurs et facilite la lisibilité. Cependant, elle est souvent sous-optimale pour certaines stratégies de trading à haute fréquence. La collecte de déchets personnalisée est souvent souhaitable pour ces cas.

C++ ne fournit pas de collecteur de déchets natif et il est donc nécessaire de gérer toute l'allocation/déallocation de mémoire dans le cadre de l'implémentation d'un objet.

De nombreuses opérations dans les systèmes de trading algorithmique sont susceptibles de parallélisation. Cela fait référence au concept d'exécution de plusieurs opérations programmatiques en même temps, c'est-à-dire en parallèle. Les algorithmes dits embarrassantement parallèles incluent des étapes qui peuvent être calculées complètement indépendamment des autres étapes. Certaines opérations statistiques, telles que les simulations de Monte Carlo, sont un bon exemple d'algorithmes embarrassantement parallèles car chaque tirage au sort et l'opération de chemin ultérieure peuvent être calculées sans connaissance d'autres chemins.

D'autres algorithmes ne sont que partiellement parallélisables. Les simulations de dynamique des fluides en sont un exemple, où le domaine du calcul peut être subdivisé, mais en fin de compte ces domaines doivent communiquer entre eux et donc les opérations sont partiellement séquentielles. Les algorithmes parallélisables sont soumis à la loi d'Amdahl, qui fournit une limite supérieure théorique à l'augmentation des performances d'un algorithme parallélisé lorsqu'il est soumis à des processus distincts NN (par exemple sur un noyau ou un thread de processeur).

La parallélisation est devenue de plus en plus importante comme moyen d'optimisation depuis que les vitesses d'horloge des processeurs se sont stagnées, car les nouveaux processeurs contiennent de nombreux cœurs pour effectuer des calculs parallèles.

Un tel matériel GPU n'est généralement adapté qu'à l'aspect de recherche de la finance quantitative, alors que d'autres matériels plus spécialisés (y compris les tableaux de porte programmables sur le terrain - FPGA) sont utilisés pour (U) HFT. De nos jours, la plupart des langages modernes prennent en charge un certain degré de concurrence / multithreading. Il est donc simple d'optimiser un backtester, car tous les calculs sont généralement indépendants les uns des autres.

La mise à l'échelle dans l'ingénierie logicielle et les opérations fait référence à la capacité du système à gérer des charges toujours croissantes sous la forme de demandes plus importantes, d'une utilisation plus élevée du processeur et d'une allocation de mémoire plus importante.

Bien que les systèmes doivent être conçus pour évoluer, il est souvent difficile de prédire à l'avance où un goulot d'étranglement se produira. L'enregistrement, les tests, le profilage et la surveillance rigoureux aideront grandement à permettre à un système d'évoluer. Les langages eux-mêmes sont souvent décrits comme "non évolutifs".

Un moyen de gérer l'échelle est de séparer les préoccupations, comme indiqué ci-dessus. Afin d'introduire davantage la possibilité de gérer les pics dans le système (c'est-à-dire la volatilité soudaine qui déclenche une série de transactions), il est utile de créer une architecture de file d'attente de messages. Cela signifie simplement placer un système de file d'attente de messages entre les composants afin que les commandes soient empilées si un certain composant est incapable de traiter de nombreuses demandes.

Au lieu de perdre les demandes, elles sont simplement conservées dans une pile jusqu'à ce que le message soit traité. Cela est particulièrement utile pour envoyer des transactions à un moteur d'exécution. Si le moteur souffre d'une forte latence, il sauvegardera les transactions. Une file d'attente entre le générateur de signaux commerciaux et l'API d'exécution atténuera ce problème aux dépens d'un potentiel glissement commercial.

Matériel et systèmes d'exploitation

Le matériel qui exécute votre stratégie peut avoir un impact significatif sur la rentabilité de votre algorithme. Ce n'est pas un problème limité aux traders à haute fréquence non plus. Un mauvais choix de matériel et de système d'exploitation peut entraîner un crash ou un redémarrage de la machine au moment le plus inopportun. Il est donc nécessaire de considérer où résidera votre application. Le choix est généralement entre une machine de bureau personnelle, un serveur distant, un fournisseur de cloud ou un serveur co-loqué d'échange.

Les machines de bureau sont simples à installer et à administrer, en particulier avec les nouveaux systèmes d'exploitation conviviaux tels que Windows 7/8, Mac OSX et Ubuntu. Les systèmes de bureau possèdent cependant des inconvénients importants. Le plus important est que les versions de systèmes d'exploitation conçues pour les machines de bureau sont susceptibles de nécessiter des redémarrages / correctifs (et souvent au pire des cas!).

L'utilisation de matériel dans un environnement domestique (ou de bureau local) peut entraîner des problèmes de connectivité Internet et de disponibilité de l'alimentation.

Un serveur dédié ou une machine basée sur le cloud, bien que souvent plus cher qu'une option de bureau, permet une infrastructure de redondance plus importante, comme des sauvegardes automatisées de données, la possibilité d'assurer plus facilement la disponibilité et la surveillance à distance.

Dans Windows, cela se fait généralement via le protocole GUI Remote Desktop (RDP). Dans les systèmes basés sur Unix, la ligne de commande Secure SHell (SSH) est utilisée.

Un serveur co-localisé, tel que l'expression est utilisée sur les marchés de capitaux, est simplement un serveur dédié qui réside dans un échange afin de réduire la latence de l'algorithme de trading.

L'aspect final du choix du matériel et du choix du langage de programmation est l'indépendance de la plate-forme. Le code doit-il s'exécuter sur plusieurs systèmes d'exploitation différents? Le code est-il conçu pour s'exécuter sur un type particulier d'architecture de processeur, comme l'Intel x86/x64 ou sera-t-il possible de l'exécuter sur des processeurs RISC tels que ceux fabriqués par ARM? Ces problèmes dépendront fortement de la fréquence et du type de stratégie mise en œuvre.

Résilience et épreuves

L'une des meilleures façons de perdre beaucoup d'argent sur le trading algorithmique est de créer un système sans résilience. Cela se réfère à la durabilité du système lorsqu'il est soumis à des événements rares, tels que des faillites de courtage, une volatilité soudaine excessive, des temps d'arrêt dans toute la région pour un fournisseur de serveur cloud ou la suppression accidentelle d'une base de données de trading entière. Des années de profits peuvent être éliminées en quelques secondes avec une architecture mal conçue. Il est absolument essentiel de considérer des problèmes tels que le débogage, les tests, l'enregistrement, les sauvegardes, la haute disponibilité et la surveillance comme composants de base de votre système.

Il est probable que dans toute application de trading quantitative personnalisée raisonnablement compliquée, au moins 50% du temps de développement sera consacré au débogage, aux tests et à la maintenance.

La plupart des langages de programmation sont livrés avec un débogueur associé ou possèdent des alternatives tierces bien respectées. En substance, un débogueur permet l'exécution d'un programme avec l'insertion de points de rupture arbitraires dans le chemin du code, qui arrêtent temporairement l'exécution afin d'enquêter sur l'état du système.

Le débogage est un composant essentiel de la boîte à outils pour analyser les erreurs de programmation. Cependant, ils sont plus largement utilisés dans les langages compilés tels que C ++ ou Java, car les langages interprétés tels que Python sont souvent plus faciles à déboguer en raison de moins de LOC et de déclarations moins verbes. Malgré cette tendance, Python est livré avec le pdb, qui est un outil de débogage sophistiqué.

Le test dans le développement de logiciels fait référence au processus d'application de paramètres et de résultats connus à des fonctions, méthodes et objets spécifiques au sein d'une base de code, afin de simuler le comportement et d'évaluer plusieurs chemins de code, ce qui aide à s'assurer qu'un système se comporte comme il se doit. Un paradigme plus récent est connu sous le nom de Test Driven Development (TDD), où le code de test est développé contre une interface spécifiée sans mise en œuvre. Avant la fin de la base de code réelle, tous les tests échoueront.

TDD nécessite une conception préalable de spécifications étendue ainsi qu'un degré de discipline pour être mis en œuvre avec succès. En C++, Boost fournit un cadre de test unitaire. En Java, la bibliothèque JUnit existe pour remplir le même objectif.

Dans un environnement de production, l'enregistrement sophistiqué est absolument essentiel. L'enregistrement fait référence au processus de sortie de messages, avec divers degrés de gravité, concernant le comportement d'exécution d'un système vers un fichier plat ou une base de données. Les journaux sont une première ligne d'attaque lors de la recherche d'un comportement inattendu de l'exécution d'un programme. Malheureusement, les lacunes d'un système d'enregistrement ont tendance à ne être découvertes qu'après coup!

Microsoft Windows et Linux sont tous deux dotés d'une vaste capacité de journalisation du système et les langages de programmation ont tendance à être livrés avec des bibliothèques de journalisation standard qui couvrent la plupart des cas d'utilisation.

Alors que l'enregistrement d'un système fournira des informations sur ce qui s'est passé dans le passé, la surveillance d'une application fournira un aperçu de ce qui se passe en ce moment. Tous les aspects du système doivent être considérés pour la surveillance.

Les indicateurs de négociation tels que les prix/volumes anormaux, les retraits rapides soudains et l'exposition des comptes pour différents secteurs/marchés devraient également être surveillés en permanence.

La surveillance du système est souvent le domaine de l'administrateur du système ou du gestionnaire des opérations. Cependant, en tant que développeur de trading unique, ces métriques doivent être établies dans le cadre d'une conception plus large.

Les sauvegardes et la haute disponibilité devraient être les principales préoccupations d'un système de négociation. Considérez les deux questions suivantes: 1) Si une base de données de production complète de données de marché et d'historique de négociation était supprimée (sans sauvegardes), comment l'algorithme de recherche et d'exécution serait-il affecté? 2) Si le système de négociation souffre d'une panne pendant une période prolongée (avec des positions ouvertes), comment l'équité du compte et la rentabilité continue seraient-elles affectées?

Il est impératif de mettre en place un système de sauvegarde des données et de test de la restauration de ces données. Beaucoup de personnes ne testent pas une stratégie de restauration. Si la récupération après un crash n'a pas été testée dans un environnement sûr, quelles garanties y a-t-il que la restauration sera disponible au pire moment possible?

De même, une disponibilité élevée doit être incorporée dès le départ. Les infrastructures redondantes (même moyennant des coûts supplémentaires) doivent toujours être prises en considération, car le coût des temps d'arrêt est susceptible de l'emporter de loin sur le coût de maintenance continu de ces systèmes.

Le choix d'une langue

Les différents facteurs qui se posent lors du développement d'un système de trading algorithmique personnalisé à haute performance ont été considérablement détaillés.

Systèmes de type

Lors du choix d'un langage pour une pile de trading, il est nécessaire de prendre en compte le système de types. Les langages qui sont d'intérêt pour le trading algorithmique sont soit statiquement- ou dynamiquement-typé. Un langage typé statiquement effectue des vérifications des types (par exemple des entiers, des flottants, des classes personnalisées, etc.) pendant le processus de compilation.

Pour un système hautement numérique tel qu'un moteur de trading algorithmique, la vérification de type au moment de la compilation peut être extrêmement bénéfique, car elle peut éliminer de nombreux bugs qui conduiraient autrement à des erreurs numériques. Cependant, la vérification de type ne capte pas tout, et c'est là que le traitement des exceptions intervient en raison de la nécessité de gérer des opérations inattendues.

Un autre avantage des langages à types statiques est que le compilateur est capable d'effectuer de nombreuses optimisations qui sont autrement indisponibles pour le langage à types dynamiques, simplement parce que le type (et donc les exigences de mémoire) sont connus au moment de la compilation.

Open Source ou propriétaire?

L'un des plus grands choix disponibles pour un développeur de trading algorithmique est d'utiliser des technologies propriétaires (commerciales) ou open source. Il y a des avantages et des inconvénients pour les deux approches. Il est nécessaire de considérer la qualité du support d'un langage, l'activité de la communauté entourant un langage, la facilité d'installation et de maintenance, la qualité de la documentation et les coûts de licence / maintenance.

La pile Microsoft.NET (y compris Visual C++, Visual C#) et MathWorks MatLab sont deux des plus grands choix propriétaires pour développer un logiciel de trading algorithmique personnalisé.

Microsoft et MathWorks fournissent tous deux une documentation étendue de haute qualité pour leurs produits. En outre, les communautés entourant chaque outil sont très grandes avec des forums Web actifs pour les deux. Le logiciel.NET permet une intégration cohérente avec plusieurs langages tels que C ++, C # et VB, ainsi qu'un lien facile avec d'autres produits Microsoft tels que la base de données SQL Server via LINQ. MatLab dispose également de nombreux plugins / bibliothèques (certains gratuits, d'autres commerciaux) pour presque tous les domaines de recherche quantitative.

Il y a aussi des inconvénients. Avec l'un ou l'autre logiciel, les coûts ne sont pas négligeables pour un commerçant isolé (bien que Microsoft fournisse gratuitement une version d'entrée de gamme de Visual Studio). Les outils Microsoft fonctionnent bien les uns avec les autres, mais s'intègrent moins bien avec le code externe. Visual Studio doit également être exécuté sur Microsoft Windows, ce qui est sans doute beaucoup moins performant qu'un serveur Linux équivalent qui est optimisé.

MatLab manque également de quelques plugins clés tels qu'un bon enveloppe autour de l'API Interactive Brokers, l'un des rares courtiers susceptibles d'un trading algorithmique à haute performance.

Les outils open source sont de qualité industrielle depuis un certain temps. Une grande partie de l'espace d'actifs alternatifs utilise largement Linux, MySQL / PostgreSQL, Python, R, C ++ et Java en haute performance. Cependant, ils ne sont pas limités à ce domaine. Python et R, en particulier, contiennent une multitude de bibliothèques numériques étendues pour effectuer presque tous les types d'analyse de données imaginables, souvent à des vitesses d'exécution comparables aux langages compilés, avec certaines mises en garde.

Le principal avantage de l'utilisation de langages interprétés est la vitesse du temps de développement. Python et R nécessitent beaucoup moins de lignes de code (LOC) pour atteindre des fonctionnalités similaires, principalement en raison des bibliothèques étendues.

Étant donné que le temps d'un développeur est extrêmement précieux et que la vitesse d'exécution est souvent inférieure (sauf dans l'espace HFT), il vaut la peine de considérer de manière approfondie une pile de technologie open source.

Les outils open source souffrent souvent d'un manque de contrat de support commercial dédié et fonctionnent de manière optimale sur des systèmes avec des interfaces utilisateur moins indulgentes. Un serveur Linux typique (comme Ubuntu) sera souvent entièrement orienté vers la ligne de commande. En outre, Python et R peuvent être lents pour certaines tâches d'exécution.

Bien que les logiciels propriétaires ne soient pas à l'abri des problèmes de dépendance / version, il est beaucoup moins courant de devoir faire face à des versions de bibliothèque incorrectes dans de tels environnements.

Je vais m'aventurer mon opinion personnelle ici et déclarer que je construis tous mes outils de trading avec des technologies open source. En particulier, j'utilise: Ubuntu, MySQL, Python, C++ et R. La maturité, la taille de la communauté, la capacité de creuser profondément si des problèmes se produisent et la réduction du coût total de possession (TCO) l'emportent largement sur la simplicité des GUI propriétaires et les installations plus faciles.

Les piles incluses?

L'en-tête de cette section se réfère aux capacités "out of the box" du langage - quelles bibliothèques contient-il et à quel point sont-elles bonnes? C'est là que les langages matures ont un avantage sur les variantes plus récentes.

C++ est célèbre pour sa bibliothèque de modèles standard (STL) qui contient une multitude de structures de données et d'algorithmes de haute performance gratuitement . Python est connu pour être capable de communiquer avec presque tous les autres types de système / protocole (en particulier le Web), principalement via sa propre bibliothèque standard. R a une multitude d'outils statistiques et économétriques intégrés, tandis que MatLab est extrêmement optimisé pour tout code d'algèbre linéaire numérique (qui peut être trouvé dans l'optimisation de portefeuille et le prix des dérivés, par exemple).

En dehors des bibliothèques standard, C++ utilise la bibliothèque Boost, qui remplit les parties manquantes de la bibliothèque standard.

Python possède la combinaison de bibliothèque d'analyse de données NumPy/SciPy/Pandas à haute performance, qui a gagné une large acceptation pour la recherche sur le trading algorithmique. En outre, des plugins haute performance existent pour accéder aux principales bases de données relationnelles, telles que MySQL++ (MySQL/C++), JDBC (Java/MatLab), MySQLdb (MySQL/Python) et psychopg2 (PostgreSQL/Python). Python peut même communiquer avec R via le plugin RPy!

Un aspect souvent négligé d'un système de trading au stade initial de la recherche et de la conception est la connectivité à une API de courtier. La plupart des API prennent en charge natifement C++ et Java, mais certaines prennent également en charge C# et Python, soit directement, soit avec le code d'emballage fourni par la communauté aux API C++. En particulier, les Interactive Brokers peuvent être connectés via le plugin IBPy. Si des performances élevées sont requises, les courtiers prendront en charge le protocole FIX.

Conclusion

Comme il est maintenant évident, le choix du langage de programmation (s) pour un système de trading algorithmique n'est pas simple et nécessite une réflexion approfondie. Les principales considérations sont les performances, la facilité de développement, la résilience et les tests, la séparation des préoccupations, la familiarité, la maintenance, la disponibilité du code source, les coûts de licence et la maturité des bibliothèques.

L'avantage d'une architecture séparée est qu'elle permet de connecter des langages pour différents aspects d'une pile de trading, au fur et à mesure que les exigences changent.


Plus de