Se connecter

Informatique

Programmation

Sujet : Gestion de données reçue en continu
1
gatias
Niveau 6
06 juillet 2020 à 15:33:49

Bonjour,

J'aimerais savoir comment ce genre de site gère les données reçues pour les traiter et les afficher ? https://www.tradingview.com/chart/

Je vais recevoir des données en temps réel, potentiellement quelques milliers de messages par seconde, que je dois traiter et afficher.

Actuellement, je suis connecté via le websocket, je traite les messages reçus et j'envoi environ 5 fois pars secondes un signal à la 'vue' qui gère l'affichage à l'écran pour afficher les données.

Je n'ai pas de soucis, mais j'aimerais rendre tout sa plus propre, que mes objets ne soient plus liés entre eux, mais totalement indépendant.

J'avais donc en tête de me connecter au websocket, gérer une petite partie du traitement des messages comme les trier, etc. Et de tout stocker dans une base de données.
Ensuite, de l'autre côté, je récupère les données, je les traite et je les affiche.

J'ai pensé à plusieurs choses :
Utiliser SQL pour la base de données, utiliser des fichiers CSV sur mon pc, utiliser un module python sur lequel je stock les dataframes, dictionnaires, etc. À chaque fois, j'aurais une partie connectée en lecture et une partie connectée en écriture.

L'objectif est de pouvoir totalement séparer la récupération des données du reste.

J'aimerais votre avis sur quoi mettre en place sachant que je ne suis pas du tout sur les performances.
J'utilise python mais je peux coder un truc en C++ si besoin.

Si ce n'est pas clair, n'hésitez pas à poser vos questions.

Bonne journée,

gatias
Niveau 6
07 juillet 2020 à 21:31:51

up

godrik
Niveau 22
08 juillet 2020 à 00:26:16

(je suis dans une voiture, donc je reponds rapidement)

Le clientqui visualize les donnees doit maintenir une connection avec le serveur plutot que de reinitialiser une connection. Pour un client web quelquechose comme websocket ou socketio fait en effet l'affaire.

Cote serveur, fondamentalement c'est un systeme pubsub dont tu as besoin. Python, C++, c'est probablement pas super important a ce niveau la. Mais tu parles de csv et de sql et ca me fait peur pour toi.
Quand la donne devient disponible, tu ne veux pas la stocker en base de donnee ou dans un fichier pour ensuite l'envoyer aux clients. Tu veux l'envoyer aux clients qui en ont besoin immediatement et et en parallel enregiatrer l'information dans un log pour la posterite. Tu veux maintenir toute les operations en O(1).

En fonction du nombre de client, du volume de donnee, et de calcul, l'architecture sera differente. pour une solution simple ou tu as juste une donnee et un client avoir simplement deux threads, un qui parle au client et un qui stocke l'i formation est suffisant.

Avec plein de clients et plein de donnee differente (genre twitter). Ce que tu veux est avoir plusieurs serveur qui gerent les clients et plusieurs serveur qui stockent. Tu veux que quand une donnee est produite savoir immediatement qui en a besoin. Donc tu as besoin de pouvoir identifier en O(1) quel serveur ou quel groupe de serveur va transmettre l'information. Ca en general ca veut dire hashing pour faire la correspondance rapidement.

En esperant que ca t'aide.

gatias
Niveau 6
08 juillet 2020 à 12:38:46

Bonjour,

Merci pour la réponse.
Je pense que ma question n’était pas clair et ta induit en erreur sauf si tu me suggères vraiment de créer un serveur pour ce que je souhaite faire.

Le serveur duquel je reçois les messages n'est pas le mien, je ne gère que la partie client.

Je me connecte a l'adresse de leur websocket et j'envoie des messages pour m'abonner au topics que je souhaite et il m’envoie les messages correspondant.
C'est des cours de bourse, orderbook etc, c'est pour cette raison qu'il peut y avoir beaucoup de messages envoyé par secondes en cas de gros mouvements.

Je peu récupérer les messages et ensuite les traiter directement, mais j'aimerais bien séparer les choses pour utiliser du multiprocessing avec le moins d’interaction possible entre mes objets.

Donc le SQL ou CSV c’était juste l'endroit ou stocker les messages reçu le temps de les traiter.
Quand je reçois le message, je fais un premier petit traitement déçu pour ensuite l'envoyer dans ma base de donnée.
De l'autre cote, je récupère les valeurs dans ma base de donnée pour faire le gros traitement. en ayant les deux parties qui tournent chacune de leur cote sans ce connaître mutuellement.

J'ai vu sur ce poste https://stackoverflow.com/questions/16740887/how-to-handle-incoming-real-time-data-with-python-pandas qu'il parle d'utiliser le module logging de python pour y stocker tous les messages tout en les traitant en parallèle.
J'ai du mal à imaginer comment le mettre en place et surtout comment les performances pourraient être bonne.

Hier, j'ai essayé de juste créer une classe DataBase ou je stock mes dictionnaires etc et qui sera accessible en écriture pour écrire les messages(pas le message brut, j'aurais un petit traitement à faire sur chaque message reçu avant de le stocker) et en lecture pour la partie qui va les traiter.


class Singleton(type):
    _instances = {}

    def __call__(cls, *args, **kwargs):
        if cls not in cls._instances:
            cls._instances[cls] = super(Singleton, cls).__call__(*args, **kwargs)
        return cls._instances[cls]


class DataBase(metaclass=Singleton):
    pass

L'avantage, c'est que niveau performance, je pense que c'est difficile de faire mieux, après il pourrait y avoir des soucis de mémoires surtout avec de gros Dataframe via pandas.

J’espère que c'est un peu plus clair.
Bonne journée

boucif
Niveau 24
08 juillet 2020 à 13:14:10

Je ne sais pas quel est ton délai de traitement espérer, même si python est un langage lent tu devrais pouvoir t'en tirer avec.

Quels sont les traitements fait sur les données, est-ce que tu as vraiment besoin de les stocker ?

gatias
Niveau 6
08 juillet 2020 à 14:10:09

Oui, je pense que je peux me débrouiller avec python et dans le pire des cas si une partie pose problème, je pourrais la coder en C ou C++.

Oui, je dois les stocker vue qu'elles me permettent de tout mettre à jour, mais pas éternellement, je peux récupérer l'historique de toutes les données quand je le souhaite. (limité à 60 requêtes par minute donc pas de live possible)

Vu que je ne ces pas comment savoir si j'ai loupé des messages ou non via le websocket, toutes les 2 min, je vais envoyer des requêtes pour avoir l'historique des dernières minutes et je le comparerais avec mes données pour tout modifier si besoin.

Les traitements à faire vont varier, de la simple comparaison de valeurs pour garder la plus petite/grande, simple sélection en fonction de paramètres spéciaux jusqu’à des calculs plus ou moins longs, et a la fin, afficher ce que je souhaite sur mon interface graphique.

boucif
Niveau 24
08 juillet 2020 à 14:18:28

Si t'as besoin de l'historique pas le choix tu stock tout en base, après tu peux stocker les donnée brut et créer des vues qui te renvoient les données tel qu'attendus

gatias
Niveau 6
08 juillet 2020 à 15:00:52

C'est pour ça que j'hésite entre plusieurs choses.

Comme j'ai mis plus haut doit être le plus rapide, mais ça va coûter cher en mémoire si je prends beaucoup de données différentes.
Une base de données SQL, je pense que ça va être trop lent, des fichiers texte/csv pareil.

Je n'ai jamais mis en place ce genre de choses et vue que ça va être la base pour construire tout le reste, j'essaie que ce soit vraiment solide.

boucif
Niveau 24
08 juillet 2020 à 16:02:20

En quoi une base de données sql c'est trop lent, après tu peux toujours passer sur du Inmemory.
Sinon t'as des système nosql style redis.

Quel est l'envergure des données, du nombre de requêtes secondes, d'utilisateurs ...

En tout cas je te déconseille un stockage fichier classique pour le coup ça peut être lent, merdique à gérer et posé des problèmes de verrous sur les fichiers.

J'ai bossé sur des systèmes avec des millions de données en base si ce n'est plus avec une problématique de perfs et on utilisait sql Server, on utilisait pratiquement que des proc stock.

gatias
Niveau 6
08 juillet 2020 à 16:36:19

Dans mes recherches, il était presque toujours déconseillé d'utiliser SQL pour un cas comme le mien sauf si les données devaient être garde sur le long terme.
J'avais peu être l'impression que c'était à peu près le même cas alors que non.

Pour l'envergure des données, tout va dépendre du nombre de souscriptions, ça peut aller d'une dizaine de messages(très rare) à plusieurs milliers de messages par seconde. Je ne me rends pas vraiment compte jusqu'où ça peut aller dans de gros pics mais c'est des cours de bourse avec l'orderbook etc, donc ca peut être vraiment lourd quand il y a de gros mouvements.

godrik
Niveau 22
08 juillet 2020 à 17:08:17

la question fondamentale est quel type de traitement tu veux faire la dessus et quel type de delai tu es pres a payer pour les types d'analyse qui va etre fait.

gatias
Niveau 6
08 juillet 2020 à 17:33:54

Le 08 juillet 2020 à 17:08:17 godrik a écrit :
la question fondamentale est quel type de traitement tu veux faire la dessus et quel type de delai tu es pres a payer pour les types d'analyse qui va etre fait.

Pour la réception des messages, j'aimerais n'en louper aucun pour ne pas tout fausser et j'aimerais aussi pouvoir directement trier les données.

Ensuite, pour les calculs je ne ces pas trop, les faire le plus rapidement possible est le mieux.
Je vise 200 ms pour l'affichage à voir plus tard.

Pour le traitement des données, je ne vais pas faire 36 000 choses.
Je vais devoir analyser le message pour savoir de quel actif boursier il s'agit, quelles infos il me donne dessus (le dernier prix, un trade exécuté, un ordre de lancé non exécuté) et j'extrais ce que je souhaite du message pour le ranger dans le tableau correspondant.

Phase finale, je fais des calculs sur les tableaux, j'affiche les parties du tableau qui m'intéressent, etc.
Globalement, c'est la partie d'analyse.

blackapplex
Niveau 10
08 juillet 2020 à 17:50:57

Niveau affichage, il y a toujours moyen de "tricher".
Si un actif fait +5% en 1minute, tu peux imaginer ne rafraichir l'indice que toutes les minutes et afficher l'évolution via une interpolation en local. Si sur une minute il fait +5%, ça fait +0.0167% toutes les 200ms.

Evidemment la minute ça peut être aberrant mais si tu veux donner l'impression d'un changement haute fréquence alors que t'es que capable de faire des MAJ toutes les 5s, ça fonctionne et je sais pas si c'est si dérangeant que ça.
J'imagine que prédire les résultats de la bourse sur les 5 secondes qui suivent crée pas une grosse erreur (mais j'y connais rien)

gatias
Niveau 6
08 juillet 2020 à 18:05:41

@blackapplex
Un actif qui fait +5% en 1 minute, c'est énorme ^^
La principale difficulté, c'est que l'actif ne prendra pas +x% toutes les 200ms ou en tant cas rarement, souvent le prix ne bouge pas beaucoup, d'un coup il décale plus ou moins, il s'arrête, il repart etc etc, ce n'est pas un flux constant, on peut avoir 10 messages pendant 5 secondes et en recevoir 5 000 la seconde d'après.

godrik
Niveau 22
08 juillet 2020 à 19:07:49

Tout ce que tu dis est super trivial. N'importe quoi de pas completement stupide va suffir.

1000 messages par secondes, c'est peanuts. Sur une journee de trading, ca represente 28 million de message. Tu peux probablement stocker ce qui t'interesse en quelques dizaines d'octet par transaction. Ca fait de l'ordre de 500MB par jour. C'est absoluement rien comme volume de donnee. Pour le stockage a long terme, n'importe quel base SQL fera l'affaire. N'importe quel base SQL aura les optimization necessaire pour faire les index sur les dates qui permettent de faire les access par interval, ce qui a l'air d'etre ce que tu veux.

Afficher est quasiment gratuit a ce genre de volume, les GPUs font l'affichage en milliard de triangle par seconde. Tant que tes algos et structures de donnee sont fait correctement, tu n'auras pas de soucis.

Relis ton livre de structure de donnee, utilise une API graphique qui fait du rendu materiel, et tout se passera bien.

gatias
Niveau 6
08 juillet 2020 à 19:57:11

Je n'ai jamais parlé de 1000 messages par secondes ^^
J'ai refait un test en minimisant mes connexions et avec un compteur par seconde, j'avais entre 3k et 41k messages en ayant minimisé les connexions.

Je vais regarder du cote de SQL vue que vous êtes 2 a me le suggérer. Merci

godrik
Niveau 22
08 juillet 2020 à 20:15:16

Encore une fois, tu veux separer le systeme temps reel, du systeme qui stocke les informations pour la posterite. Parceque tu ne veux pas que les delai d'ecriture tuent tes contraintes temps reel. En pratique, si le temps reel est suffisement important, j'utiliserais une autre machine pour faire le stockage.

Ton probleme fondamental est algorithmique et pas technologique tant que les choix technologique ne sont pas stupide. Meme a 40k transaction par seconde toute les secondes, tu ne parles que de 1 milliard de transaction par jour. Probablement ca tient en memoire pour une machine un peu raisonnable, ca doit meme tenir dans la memoire de ton GPU pourvu qeu tu aie un GPU un peu gros. Et en moyenne c'est beaucoup moins que ca.

Tant que tes algos sont incrementaux, tu n'auras pas de probleme de performance. Et pour ce que tu as l'air de chercher a faire, je pense qu'il va etre facil d'incrementaliser les algorithmes.

Tu veux te documenter un peu sur les techniques de representation/compression de series temporelle pour avoir une idee de comment ameliorer les perf si tu as besoin. Mais un code directe devrait fonctionner.

Mon conseil est: ecrit le premier truc qui te passe par la tete et regarde si ca passe.

gatias
Niveau 6
08 juillet 2020 à 21:00:44

Ok merci pour les conseils.
Je vais coder tout ça et si besoin, je me renseignerais sur les techniques de representation/compression de séries temporelle.
Je reviendrais dans quelque temps pour dire ce qu'il en est.

1
Sujet : Gestion de données reçue en continu
   Retour haut de page
Consulter la version web de cette page