XRAYS · Planning commentaires

Le rituel du lancement, prêt à coller depuis ton téléphone. Chaque commentaire a son bouton Copier.

Rythme : Mardi = Défi (08h30) · Jeudi = Jeu (12h30). Pour chaque post : le 1er commentaire (indice) dans la foulée (T0), une relance à +2h, la réponse d'ingé le lendemain (J+1) même heure - en version complète ou courte, au choix.
Horaires en heure de Paris - à l'étranger, poste à l'équivalent local (ou garde l'heure de Paris, au choix).

💬 Réponses aux commentaires

Réagis dans l'heure, like les bonnes réponses. Ton : sharp, vrai, jamais corporate.
✅ Bonne réponse
Exactement ça 👌 Et sans filet en plus. C'est le réflexe qu'on aime voir.
Pile poil. Tu mérites ton café du mardi ☕
Dans le mille. Tu compiles ça dans ta tête en 2 secondes, nous on appelle ça un bon signe 👀
🔥 Bonne réponse + profil à matcher (puis DM)
Réponse propre ET l'explication qui va avec : exactement le profil qu'on cherche. Je te glisse un mot en privé 👀
Là tu réponds comme quelqu'un qui l'a déjà vu casser en prod. On a des postes où ça compte, je t'écris.
🤏 Presque / partiel
Tu chauffes 🔥 Il te manque juste le pourquoi exact, creuse encore deux minutes.
Bonne intuition, mais c'est pas tout à fait la racine. Regarde un cran plus bas, t'y es presque.
🤔 Faux mais bon raisonnement
Pas la bonne réponse, mais le raisonnement est sain, et c'est ça qui compte ici. Continue.
Faux sur la conclusion, juste sur la démarche. On préfère ça à une bonne réponse récitée par cœur 😉
❌ À côté (bienveillant)
Pas cette fois 😅 mais c'est tout l'intérêt : la réponse d'ingé tombe demain même heure, tu vas kiffer.
Là on s'éloigne un peu. Garde un œil, je lâche la solution demain et ça va faire tilt.
😏 Wrong Answers Only (joue le jeu)
Magnifique. Horrible, mais magnifique 👏
Ça, c'est le genre d'idée qui fait pleurer un SRE à 3h du matin. Validé pour le pire 🏆
Pire réponse, meilleur commentaire. On garde 😄
💬 Question / débat
Très bonne question, et y'a pas de réponse unique, c'est tout le sel. Toi tu ferais quoi en prod ?
Là tu touches un vrai débat d'ingé. Argumente, on adore se faire challenger 👀
👋 Faire participer / relancer un hésitant
Allez, tente même si t'es pas sûr : c'est comme ça qu'on apprend, et personne se moque ici 💪
T'as une intuition ? Balance, même à moitié. On creuse ensemble.
⚡ Réagir vite (golden hour, ultra court)
👀
Bien vu.
Ça sent l'expérience, ça 👌
Intéressant, continue.
Haha exactement.
🟥 Défi #01mardi 30 juin · 08h30

La boucle qui ne s'arrête jamais

cpp · Moyen
POST mardi 30 juin · 08h30Le post (programmé LinkedIn)
🔔 🟥 LE DÉFI DU MARDI #01

On a tous écrit cette boucle un jour. Elle parcourt un buffer de ticks à l'envers, du plus récent au plus ancien. Revue de code : OK. Tests sur 3 éléments : OK.

En prod, sur un gros buffer : boucle infinie, puis lecture hors limites. Un mardi à 9h02, évidemment.

Le bug tient en un seul caractère de type, il est sous tes yeux dans l'image 👇

Tu le vois ? Balance ta réponse en commentaire, on épingle la première bonne. Indice juste en dessous, réponse d'ingé demain même heure.

#cpp #lowlatency #cppfr #financedemarche #xraystrading
T0 mardi 30 juin · 08h301er commentaire (indice)
Indice 👀 De quel type est i ? Et qu'est-ce qu'un std::size_t ne peut JAMAIS valoir ?
+2h mardi 30 juin · 10h30Relance
⏰ Plus qu'une heure pour tenter votre réponse 👇

Je lâche la solution demain, même heure. Postez vos hypothèses en commentaire, on en débat 👀
J+1 mercredi 1 juillet · 08h30Réponse d'ingé (complète)
La réponse du #01 🟥

std::size_t est NON SIGNÉ : i >= 0 est toujours vrai, un unsigned ne peut pas être négatif. Quand i vaut 0, --i ne donne pas -1, il wrap à SIZE_MAX (18 446 744 073 709 551 615 en 64 bits). On lit ticks[SIZE_MAX] (hors limites) et la condition de sortie ne casse jamais.

On l'a compilé et exécuté : i = 2 → 1 → 0 → 18446744073709551615 → ...

Le compilo le voit aussi (GCC : -Wtype-limits, Clang : -Wtautological-compare - « comparison of unsigned expression >= 0 is always true »). Mets tes warnings, ils bossent pour toi.

Le fix idiome : for (std::size_t i = ticks.size(); i-- > 0; ) handle(ticks[i]);
(ou des reverse iterators / std::views::reverse en C++20).

Réf : conversion vers un type non signé = modulo 2^n ([conv.integral]). Défini, déterministe, et ça casse un buffer en prod.

C'est exactement le genre de détail qu'on traque chez XRAYS TRADING : une lecture hors-cache coûte des microsecondes, un crash coûte une session. On recrute des gens qui voient ce caractère 👉 drh@xrays.fr. Rendez-vous mardi prochain pour le #02.
J+1 mercredi 1 juillet · 08h30Réponse courte (option)
std::size_t est NON SIGNÉ : i >= 0 est toujours vrai, un unsigned ne peut pas être négatif. Quand i vaut 0, --i ne donne pas -1, il wrap à SIZE_MAX (18 446 744 073 709 551 615 en 64 bits).
🎮 Jeu #01jeudi 2 juillet · 12h30

Devine La Techno

C++ low latency · Facile
POST jeudi 2 juillet · 12h30Le post (programmé LinkedIn)
Elle est rapide. Très rapide.
Elle ne pardonne rien : un pointeur qui traîne, et c'est segfault à 9h02 pile pendant l'ouverture.
On la déteste le mardi, on l'adore quand le book se charge en microsecondes.
Les recruteurs la mettent dans 80% des annonces salle de marché.

Vous avez 3 secondes. C'est quoi ?
Réponse en commentaire, pas de triche avec Google.
T0 jeudi 2 juillet · 12h301er commentaire (indice)
Un indice pour ceux qui hésitent : son meilleur ami s'appelle "valgrind", son pire ennemi "double free". On lit vos paris.
+2h jeudi 2 juillet · 14h30Relance
⏰ Plus qu'une heure pour tenter votre réponse 👇

Je lâche la solution demain, même heure. Postez vos hypothèses en commentaire, on en débat 👀
J+1 vendredi 3 juillet · 12h30Réponse d'ingé (complète)
C++, et son cœur moderne C++17/20. Pourquoi lui : compilé en natif, contrôle mémoire total, des abstractions à coût zéro, donc la latence la plus basse et surtout la plus prévisible. Le revers est dans l'énoncé : aucun garde-fou, un pointeur qui traîne ou un buffer mal borné et c'est segfault ou double free en pleine ouverture. C'est pour ça qu'il tient le hot path en salle de marché, et pourquoi valgrind et les sanitizers (ASan/UBSan) sont les meilleurs amis de l'ingé. On accepte aussi « C++ moderne ».
J+1 vendredi 3 juillet · 12h30Réponse courte (option)
C++, et son cœur moderne C++17/20. Pourquoi lui : compilé en natif, contrôle mémoire total, des abstractions à coût zéro, donc la latence la plus basse et surtout la plus prévisible.
🟥 Défi #02mardi 7 juillet · 08h30

string_view sur temporaire

cpp · Moyen
POST mardi 7 juillet · 08h30Le post (programmé LinkedIn)
🔔 🟥 LE DÉFI DU MARDI #02

Classique des feed handlers : on normalise un symbole, on le passe en string_view pour éviter une copie sur le hot path. Sauf que ce code la lit de la mémoire morte.

std::string_view v lie le résultat de venue_id() + "_MIC". Question simple : la string_view rendue par sym() pointe sur quoi, et pourquoi c'est cassé ?

Dites-moi en commentaire ce que voit le lecteur en aval.
T0 mardi 7 juillet · 08h301er commentaire (indice)
string_view ne possède rien. Elle ne fait que pointer. Demandez-vous combien de temps vit le std::string temporaire produit par operator+.
+2h mardi 7 juillet · 10h30Relance
⏰ Plus qu'une heure pour tenter votre réponse 👇

Je lâche la solution demain, même heure. Postez vos hypothèses en commentaire, on en débat 👀
J+1 mercredi 8 juillet · 08h30Réponse d'ingé (complète)
UB : dangling string_view. operator+ produit un std::string temporaire. v est construite dessus, mais string_view ne possède pas la donnée, elle ne fait que stocker pointeur + longueur ([string.view.template] : un view est non-owning). Le temporaire est détruit à la fin de l'instruction complète ([class.temporary]), bien avant le return. v pointe alors sur de la mémoire libérée : tout accès en aval est un comportement indéfini, pas une 'sortie'. Le fait que v soit liée à un view (et non à une const ref) signifie qu'il n'y a AUCUNE extension de durée de vie : seule la liaison directe d'un temporaire à une référence l'étend, jamais via un view. Fix idiomatique : renvoyer un std::string (possède la donnée), ou garder le std::string vivant dans le scope appelant et n'exposer la view que tant qu'il vit. Sur un feed handler, ne jamais stocker une view au-delà de la durée de vie du buffer source. C'est exactement ce qu'on traque chez XRAYS TRADING, on recrute : drh@xrays.fr
J+1 mercredi 8 juillet · 08h30Réponse courte (option)
UB : dangling string_view. operator+ produit un std::string temporaire.
🎮 Jeu #02jeudi 9 juillet · 12h30

Bug Ou Feature ?

market data · Facile
POST jeudi 9 juillet · 12h30Le post (programmé LinkedIn)
Tous les lundis à 8h45, le flux de market data se fige pendant exactement 1,2 seconde. Puis il repart, comme si de rien n'était. Aucune erreur dans les logs. Le P&L est juste, les ordres passent.

Bug ou feature ?
Votez en commentaire et dites pourquoi. Le "pourquoi" nous intéresse plus que le vote.
T0 jeudi 9 juillet · 12h301er commentaire (indice)
Pour pimenter : en interne, l'équipe était divisée 50/50. Camp "bug" contre camp "snapshot programmé côté provider". Tranchez.
+2h jeudi 9 juillet · 14h30Relance
⏰ Plus qu'une heure pour tenter votre réponse 👇

Je lâche la solution demain, même heure. Postez vos hypothèses en commentaire, on en débat 👀
J+1 vendredi 10 juillet · 12h30Réponse d'ingé (complète)
A) Bug : un trou de données masqué
B) Feature : un snapshot de resync côté provider
Réponse : feature déguisée en bug. C'était un snapshot de resynchronisation côté fournisseur, documenté dans un PDF que personne n'avait lu.
J+1 vendredi 10 juillet · 12h30Réponse courte (option)
A) Bug : un trou de données masqué
B) Feature : un snapshot de resync côté provider
Réponse : feature déguisée en bug. C'était un snapshot de resynchronisation côté fournisseur, documenté dans un PDF que personne n'avait lu.
🟥 Défi #03mardi 14 juillet · 08h30

Le prix qui ment

csharp · Moyen
POST mardi 14 juillet · 08h30Le post (programmé LinkedIn)
🔔 🟥 LE DÉFI DU MARDI #03

Un quant additionne 3 incréments de prix de 0.1 et son check d'égalité saute en prod. Classique, et pourtant ça pique encore.

Les deux WriteLine, ils affichent quoi exactement (True/False), et dans cet ordre ?

Votre verdict en commentaire, on compare demain.
T0 mardi 14 juillet · 08h301er commentaire (indice)
Indice T0 : double = IEEE 754 binaire, 0.1 n'a pas de représentation exacte en base 2. decimal, lui, est en base 10. La question est : lequel des deux tombe juste ?
+2h mardi 14 juillet · 10h30Relance
⏰ Plus qu'une heure pour tenter votre réponse 👇

Je lâche la solution demain, même heure. Postez vos hypothèses en commentaire, on en débat 👀
J+1 mercredi 15 juillet · 08h30Réponse d'ingé (complète)
Réponse d'ingé.

Sortie garantie : False puis True.

Pourquoi c'est normatif : double suit IEEE 754 binary64 (ECMA-334). 0.1 n'a pas de représentation finie en base 2, donc 0.1+0.1+0.1 vaut 0.30000000000000004, distinct de la constante 0.3 la plus proche : le == rend False. decimal est un flottant décimal (ECMA-334) : 0.1m, 0.3m sont représentés exactement en base 10, la somme égale strictement 0.3m, donc True. Aucune dépendance à la culture, au runtime ou à la plateforme.

Fix idiomatique : pour des prix et montants, jamais double. On price en decimal, ou on compare avec une tolérance (Math.Abs(a - b) < epsilon) si on est contraint au binaire.

C'est exactement ce qu'on traque chez XRAYS TRADING, on recrute : drh@xrays.fr
J+1 mercredi 15 juillet · 08h30Réponse courte (option)
Réponse d'ingé.
🎮 Jeu #03jeudi 16 juillet · 12h30

Stack Battle

C++ vs Java · Facile
POST jeudi 16 juillet · 12h30Le post (programmé LinkedIn)
Order routing critique, microsecondes qui comptent, salle de marché.

C++ ou Java ?

Pas de "ça dépend" mou. Choisissez votre camp et donnez UN argument qui tue. Le meilleur argument sera épinglé.
T0 jeudi 16 juillet · 12h301er commentaire (indice)
On lance les hostilités côté C++ : quand chaque microseconde se paye, le garbage collector de la JVM est un invité qu'on n'a pas convié. À vous de défendre l'autre camp.
+2h jeudi 16 juillet · 14h30Relance
⏰ Plus qu'une heure pour tenter votre réponse 👇

Je lâche la solution demain, même heure. Postez vos hypothèses en commentaire, on en débat 👀
J+1 vendredi 17 juillet · 12h30Réponse d'ingé (complète)
A) C++, le bas niveau ou rien
B) Java, la stabilité et l'écosystème
C) Les deux, selon la couche
Pas de bonne réponse unique, c'est le but. En ultra basse latence pure, C++ domine. Sur l'OMS plus haut niveau, Java tient très bien la route.
J+1 vendredi 17 juillet · 12h30Réponse courte (option)
A) C++, le bas niveau ou rien
B) Java, la stabilité et l'écosystème
C) Les deux, selon la couche
Pas de bonne réponse unique, c'est le but. En ultra basse latence pure, C++ domine.
🟥 Défi #04mardi 21 juillet · 08h30

Deux ordres au même prix

java · Facile
POST mardi 21 juillet · 08h30Le post (programmé LinkedIn)
🔔 🟥 LE DÉFI DU MARDI #04

Classique qui pique en prod. On dédup des ordres par leur id en Integer, et un matin deux ids identiques ne matchent plus. Les deux println affichent quoi, et surtout pourquoi pas pareil ?

Votre réponse en commentaire, on débriefe demain.
T0 mardi 21 juillet · 08h301er commentaire (indice)
Indice : la réponse est garantie par la spec, elle ne dépend pas de la JVM. Regardez l'intervalle -128..127 de très près.
+2h mardi 21 juillet · 10h30Relance
⏰ Plus qu'une heure pour tenter votre réponse 👇

Je lâche la solution demain, même heure. Postez vos hypothèses en commentaire, on en débat 👀
J+1 mercredi 22 juillet · 08h30Réponse d'ingé (complète)
Réponse : false puis true.

Pourquoi (normatif) : a == b et c == d comparent des RÉFÉRENCES, pas des valeurs. L'autoboxing passe par Integer.valueOf(int). La JLS 5.1.7 impose que valueOf mette en cache et renvoie le MÊME objet pour toute valeur de -128 à 127. Donc 127 == 127 est true (même instance cachée), mais 128 sort du cache garanti : deux instances distinctes, == compare deux références différentes, donc false.

Fix idiomatique : pour comparer des valeurs, on utilise c.equals(d) ou Objects.equals(a, b), jamais == sur des wrappers. Ou on travaille en int primitif.

C'est exactement ce qu'on traque chez XRAYS TRADING, on recrute : drh@xrays.fr
J+1 mercredi 22 juillet · 08h30Réponse courte (option)
Réponse : false puis true.
🎮 Jeu #04jeudi 23 juillet · 12h30

Estimation Latence

réseau / fibre · Moyen
POST jeudi 23 juillet · 12h30Le post (programmé LinkedIn)
Estimation.

Un signal lumineux dans une fibre optique parcourt environ combien de kilomètres en 1 milliseconde ?

Pas de calculatrice, pas de Google. Posez votre estimation à l'instinct, puis on compare. L'ingénierie de latence commence par les ordres de grandeur.
T0 jeudi 23 juillet · 12h301er commentaire (indice)
Indice : dans une fibre, la lumière est plus lente que dans le vide, environ deux tiers. Recalculez.
+2h jeudi 23 juillet · 14h30Relance
⏰ Plus qu'une heure pour tenter votre réponse 👇

Je lâche la solution demain, même heure. Postez vos hypothèses en commentaire, on en débat 👀
J+1 vendredi 24 juillet · 12h30Réponse d'ingé (complète)
Réponse : environ 200 km. Dans une fibre, la lumière voyage à environ deux tiers de sa vitesse dans le vide, soit à peu près 200 000 km/s, donc environ 200 km par milliseconde. C'est pour ça que la distance physique entre votre serveur et le marché est un paramètre de latence majeur.
J+1 vendredi 24 juillet · 12h30Réponse courte (option)
Réponse : environ 200 km. Dans une fibre, la lumière voyage à environ deux tiers de sa vitesse dans le vide, soit à peu près 200 000 km/s, donc environ 200 km par milliseconde.
🟥 Défi #05mardi 28 juillet · 08h30

__slots__ et le hot path CPython

python · Moyen
POST mardi 28 juillet · 08h30Le post (programmé LinkedIn)
🔔 🟥 LE DÉFI DU MARDI #05

Côté Python du desk : on instancie des millions de Tick pour rejouer un flux. La classe naïve marche, mais la RAM explose et le cache CPU pleure. Quelqu'un propose __slots__ = ('px', 'qty').

Deux effets à nommer précisément : (1) qu'arrive-t-il à la ligne A (t.source = 'X') APRÈS ajout des slots, et exactement quelle exception ? (2) pourquoi la mémoire par instance baisse en CPython ? Soyez précis sur le 'pourquoi'.

À vous.
T0 mardi 28 juillet · 08h301er commentaire (indice)
Indice T0 : sans __slots__, chaque instance porte un __dict__ pour stocker ses attributs, ce qui permet d'en ajouter n'importe lequel à la volée (comme source). Avec __slots__, ce dictionnaire par instance disparaît. Que devient alors un attribut hors liste ?
+2h mardi 28 juillet · 10h30Relance
⏰ Plus qu'une heure pour tenter votre réponse 👇

Je lâche la solution demain, même heure. Postez vos hypothèses en commentaire, on en débat 👀
J+1 mercredi 29 juillet · 08h30Réponse d'ingé (complète)
Réponse d'ingé :

(1) Après __slots__ = ('px', 'qty'), la ligne A lève AttributeError : 'Tick' object has no attribute 'source'. En déclarant des slots, on supprime le __dict__ par instance ; les seuls attributs autorisés sont ceux listés. Toute affectation d'un attribut hors liste échoue (sauf si on ajoute explicitement '__dict__' aux slots, ce qui annule l'intérêt).

(2) La mémoire par instance baisse parce qu'on élimine le __dict__ par instance. Sans slots, CPython alloue à chaque instance un dictionnaire (structure de hash avec sur-allocation) pour porter les attributs ; avec slots, les attributs sont rangés dans des descripteurs à offsets fixes directement dans l'objet, comme des champs d'une struct C. Résultat : moins d'octets par instance, et un layout plus compact donc plus cache-friendly quand on en parcourt des millions. Le gain réel dépend de la version de CPython (les key-sharing dicts atténuent l'écart sur les récents), mais le __dict__ supprimé reste la cause directe.

Fix idiomatique : __slots__ sur les objets à forte cardinalité et schéma fixe (Tick, OrderBookLevel), exactement comme on choisit un POD bien aligné en C++. Garder en tête : pas d'attribut dynamique, et interaction à vérifier avec l'héritage et le pickling.

C'est exactement ce qu'on traque chez XRAYS TRADING : le layout mémoire jusque dans le Python de replay et de tooling. On recrute : drh@xrays.fr
J+1 mercredi 29 juillet · 08h30Réponse courte (option)
Réponse d'ingé :
🎮 Jeu #05jeudi 30 juillet · 12h30

Le Terminal Raconte

Linux / Bash · Facile
POST jeudi 30 juillet · 12h30Le post (programmé LinkedIn)
Le terminal raconte.

"23h47. Personne ne me parle depuis 2h. Soudain un cron se réveille. Il lance un script que personne n'a relu depuis 2019. Le script ouvre une connexion, copie 4 Go vers un disque qui en a 3 de libre. Je commence à paniquer. À 23h51, je n'ai plus rien à offrir. df me regarde avec pitié. À 23h52, la prod tousse."

Qu'est-ce qui a vraiment tué la machine cette nuit-là ?
T0 jeudi 30 juillet · 12h301er commentaire (indice)
Le mot magique tient en trois lettres anglaises très connues : "no space left on...". Complétez et expliquez la prévention.
+2h jeudi 30 juillet · 14h30Relance
⏰ Plus qu'une heure pour tenter votre réponse 👇

Je lâche la solution demain, même heure. Postez vos hypothèses en commentaire, on en débat 👀
J+1 vendredi 31 juillet · 12h30Réponse d'ingé (complète)
Réponse : disque plein (no space left on device) provoqué par un job non supervisé. Cause profonde : pas de monitoring d'espace disque et pas de rotation/nettoyage automatique.
J+1 vendredi 31 juillet · 12h30Réponse courte (option)
Réponse : disque plein (no space left on device) provoqué par un job non supervisé. Cause profonde : pas de monitoring d'espace disque et pas de rotation/nettoyage automatique.
🟥 Défi #06mardi 4 août · 08h30

Le filtre fantôme

sql · Moyen
POST mardi 4 août · 08h30Le post (programmé LinkedIn)
🔔 🟥 LE DÉFI DU MARDI #06

Un collègue veut sortir les positions sans P&L calculé. Il pousse ça en prod, le rapport risque tourne, zéro ligne. Pourtant la moitié du book a un pnl NULL. Le serveur ne plante pas, ne renvoie aucune erreur.

Combien de lignes ramène cette requête, et pourquoi ?

À vos commentaires.
T0 mardi 4 août · 08h301er commentaire (indice)
Indice T0 : en SQL standard, NULL n'est égal à rien, pas même à un autre NULL. Que vaut le prédicat pnl = NULL pour chaque ligne ?
+2h mardi 4 août · 10h30Relance
⏰ Plus qu'une heure pour tenter votre réponse 👇

Je lâche la solution demain, même heure. Postez vos hypothèses en commentaire, on en débat 👀
J+1 mercredi 5 août · 08h30Réponse d'ingé (complète)
Réponse : 0 ligne, toujours.

Pourquoi : NULL représente une valeur inconnue, et toute comparaison avec = NULL s'évalue à UNKNOWN (jamais TRUE), donc le WHERE ne retient aucune ligne. C'est de la logique ternaire SQL, pas un bug du moteur.

Fix idiomatique : WHERE pnl IS NULL (et IS NOT NULL pour l'inverse). Piège classique en revue de code risk : un = NULL silencieux masque tout un pan du book sans lever d'erreur.

C'est exactement ce qu'on traque chez XRAYS TRADING, on recrute : drh@xrays.fr
J+1 mercredi 5 août · 08h30Réponse courte (option)
Réponse : 0 ligne, toujours.
🎮 Jeu #06jeudi 6 août · 12h30

Une Techno, Une Seule Mauvaise Reponse

Python · Moyen
POST jeudi 6 août · 12h30Le post (programmé LinkedIn)
Une techno : Python. Quatre affirmations. UNE seule est fausse. Laquelle ?

A) Le GIL limite le vrai parallélisme des threads sur du CPU pur.
B) Python est idéal pour prototyper un modèle de pricing avant portage C++.
C) Pandas charge toujours les données en flux sans jamais saturer la RAM.
D) Les bibliothèques scientifiques délèguent les calculs lourds à du code natif compilé.

Votre verdict en commentaire, avec l'argument.
T0 jeudi 6 août · 12h301er commentaire (indice)
Indice : pensez à la dernière fois qu'un notebook a fait freezer votre machine sur un gros CSV.
+2h jeudi 6 août · 14h30Relance
⏰ Plus qu'une heure pour tenter votre réponse 👇

Je lâche la solution demain, même heure. Postez vos hypothèses en commentaire, on en débat 👀
J+1 vendredi 7 août · 12h30Réponse d'ingé (complète)
A, B, C, D. Réponse : C est fausse. Pandas charge typiquement tout en mémoire, c'est même un grand classique de la saturation RAM sur gros volumes.
J+1 vendredi 7 août · 12h30Réponse courte (option)
A, B, C, D. Réponse : C est fausse. Pandas charge typiquement tout en mémoire, c'est même un grand classique de la saturation RAM sur gros volumes.
🟥 Défi #07mardi 11 août · 08h30

Le prix qui ment

javascript · Facile
POST mardi 11 août · 08h30Le post (programmé LinkedIn)
🔔 🟥 LE DÉFI DU MARDI #07

Dans le blotter, on additionne deux frais de commission, 0.1 et 0.2. Le test d'égalité à 0.3 part en vrille et le trader hurle que sa ligne de P&L est fausse.

Sans lancer Node : que loggent EXACTEMENT ces deux lignes, et pourquoi ?

Balancez en commentaire.
T0 mardi 11 août · 08h301er commentaire (indice)
Indice T0 : pensez en base 2, pas en base 10. 0.1 et 0.2 n'ont pas de représentation finie en flottant binaire. La 2e ligne dévoile les décimales cachées.
+2h mardi 11 août · 10h30Relance
⏰ Plus qu'une heure pour tenter votre réponse 👇

Je lâche la solution demain, même heure. Postez vos hypothèses en commentaire, on en débat 👀
J+1 mercredi 12 août · 08h30Réponse d'ingé (complète)
Réponse : ligne 1 => false, ligne 2 => 0.30000000000000004.

POURQUOI : les doubles IEEE-754 (le seul type Number de JS) stockent en binaire base 2. 0.1 et 0.2 sont des fractions périodiques infinies en base 2, arrondies au plus proche double. Leur somme vaut 0.30000000000000004, distincte du double le plus proche de 0.3. Donc frais === 0.3 est false.

FIX idiomatique : ne jamais comparer des flottants par égalité ni manipuler de l'argent en float. On travaille en entiers (centimes/ticks) : Math.round((0.1+0.2)*100)===30, ou une lib décimale (decimal.js, big.js), ou une comparaison à epsilon Math.abs(a-b)<Number.EPSILON pour le non-monétaire.

C'est exactement ce qu'on traque chez XRAYS TRADING, on recrute : drh@xrays.fr
J+1 mercredi 12 août · 08h30Réponse courte (option)
Réponse : ligne 1 => false, ligne 2 => 0.30000000000000004.
🎮 Jeu #07jeudi 13 août · 12h30

Devine La Techno

base de données time-series · Moyen
POST jeudi 13 août · 12h30Le post (programmé LinkedIn)
Une base vénérée en salle de marché pour stocker des milliards de ticks.
Un langage si concis qu'une requête tient en une ligne, et qui fait pleurer les nouveaux.
Trois lettres et un signe.
T0 jeudi 13 août · 12h301er commentaire (indice)
Indice : ce n'est pas du SQL classique, et "select from t where price>100" y ressemble à peine.
+2h jeudi 13 août · 14h30Relance
⏰ Plus qu'une heure pour tenter votre réponse 👇

Je lâche la solution demain, même heure. Postez vos hypothèses en commentaire, on en débat 👀
J+1 vendredi 14 août · 12h30Réponse d'ingé (complète)
kdb+ et son langage q (KX). En colonne, en mémoire, pensé pour des milliards de ticks. Concis à l'extrême, courbe d'apprentissage brutale, mais imbattable sur les séries temporelles de marché.
J+1 vendredi 14 août · 12h30Réponse courte (option)
kdb+ et son langage q (KX). En colonne, en mémoire, pensé pour des milliards de ticks. Concis à l'extrême, courbe d'apprentissage brutale, mais imbattable sur les séries temporelles de marché.
🟥 Défi #08mardi 18 août · 08h30

Le tableau vide qui se croit faux

typescript · Difficile
POST mardi 18 août · 08h30Le post (programmé LinkedIn)
🔔 🟥 LE DÉFI DU MARDI #08

Un de ces pièges de coercition qui font douter de sa propre santé mentale.

Quelqu'un teste un panier vide avec un == un peu trop optimiste. On compare un tableau [] à sa propre négation ![].

Que valent les deux console.log, et quelle branche du if s'exécute ?

Votre verdict en commentaire 👇

#dev #typescript #javascript #code
T0 mardi 18 août · 08h301er commentaire (indice)
Indice du #08 👀 ![] vaut false (un objet est truthy). Ensuite [] == false déclenche une cascade de conversions : objet vers primitive, puis vers nombre.
+2h mardi 18 août · 10h30Relance
⏰ Plus qu'une heure pour tenter votre réponse 👇

Je lâche la solution demain, même heure. Postez vos hypothèses en commentaire, on en débat 👀
J+1 mercredi 19 août · 08h30Réponse d'ingé (complète)
La réponse du #08 🟥

On a exécuté le code. La console affiche :
false
true
Panier traité comme vide

Deux mécanismes se combinent. D'abord ![] : un tableau est un objet, donc truthy, et sa négation vaut false. Ensuite [] == false suit l'algorithme d'égalité abstraite : le booléen false devient le nombre 0, puis le tableau [] est converti en primitive, ce qui donne la chaîne vide "", elle-même convertie en 0. On compare 0 == 0, qui vaut true. La branche "vide" s'exécute, même si panier n'a rien à voir là-dedans : on a comparé panier à false par le même chemin.

La parade : ne jamais utiliser == pour ce genre de test. Vérifier panier.length === 0, et préférer === partout.

C'est exactement le genre de détail qu'on traque chez XRAYS TRADING. Pas besoin de venir de la finance, juste d'être un bon ingé. 👉 drh@xrays.fr
J+1 mercredi 19 août · 08h30Réponse courte (option)
On a exécuté le code. La console affiche :
false
true
Panier traité comme vide
🎮 Jeu #08jeudi 20 août · 12h30

Wrong Answers Only

reduire la latence · Facile
POST jeudi 20 août · 12h30Le post (programmé LinkedIn)
Wrong answers only.
"Comment réduire la latence de notre chaîne de trading ?"
Donne-nous la PIRE idée possible en commentaire.
T0 jeudi 20 août · 12h301er commentaire (indice)
On commence : "ajouter des logs partout pour voir où ça rame en prod".
+2h jeudi 20 août · 14h30Relance
⏰ Plus qu'une heure pour tenter votre réponse 👇

Je lâche la solution demain, même heure. Postez vos hypothèses en commentaire, on en débat 👀
J+1 vendredi 21 août · 12h30Réponse d'ingé (complète)
Sérieusement : on profile d'abord, on vire les allocations du hot path, on colocalise et on passe en kernel bypass. On n'optimise jamais à l'aveugle. (Les mauvaises réponses en commentaire, elles, sont les bienvenues.)
J+1 vendredi 21 août · 12h30Réponse courte (option)
Sérieusement : on profile d'abord, on vire les allocations du hot path, on colocalise et on passe en kernel bypass. On n'optimise jamais à l'aveugle. (Les mauvaises réponses en commentaire, elles, sont les bienvenues.)
🟥 Défi #09mardi 25 août · 08h30

L'erreur qui n'est pas nil

go · Expert
POST mardi 25 août · 08h30Le post (programmé LinkedIn)
🔔 🟥 LE DÉFI DU MARDI #09

Un pointeur nil rangé dans une interface error. Le err != nil du handler part en vrille alors que la valeur est nil. Vous voyez pourquoi avant le compilo ?

Qu'affiche ce programme ?

#dev #golang #code
T0 mardi 25 août · 08h301er commentaire (indice)
Indice 👀 une interface, c'est un couple (type, valeur). Le type est-il nil ?
+2h mardi 25 août · 10h30Relance
⏰ Plus qu'une heure pour tenter votre réponse 👇

Je lâche la solution demain, même heure. Postez vos hypothèses en commentaire, on en débat 👀
J+1 mercredi 26 août · 08h30Réponse d'ingé (complète)
La réponse du #09 🟥

On a compilé et exécuté : ça affiche true.

Une interface Go n'est nil que si SON type ET SA valeur sont nil. Ici check() range un *ValErr (type concret non nil) pointant sur nil. L'interface error porte donc (*ValErr, nil) : son type n'est pas nil, donc err != nil vaut true. Le bug classique : retourner un *T typé au lieu d'un error nil. La parade, c'est return nil explicite, jamais un pointeur typé nil.

C'est exactement le genre de détail qu'on traque chez XRAYS TRADING. Pas besoin de venir de la finance, juste d'être un bon ingé. 👉 drh@xrays.fr
J+1 mercredi 26 août · 08h30Réponse courte (option)
On a compilé et exécuté : ça affiche true.
🎮 Jeu #09jeudi 27 août · 12h30

Bug Ou Feature ?

heartbeat FIX · Facile
POST jeudi 27 août · 12h30Le post (programmé LinkedIn)
Ta session FIX envoie un message vide toutes les 30 secondes, même quand il ne se passe rien.
Gaspillage, ou utile ?
T0 jeudi 27 août · 12h301er commentaire (indice)
Indice : comment savoir qu'un lien est mort si plus personne ne parle ?
+2h jeudi 27 août · 14h30Relance
⏰ Plus qu'une heure pour tenter votre réponse 👇

Je lâche la solution demain, même heure. Postez vos hypothèses en commentaire, on en débat 👀
J+1 vendredi 28 août · 12h30Réponse d'ingé (complète)
Feature. Le heartbeat (tag 108) maintient la session vivante et détecte une coupure : pas de heartbeat attendu, on envoie un TestRequest, et si silence, on coupe proprement. C'est le "tu es toujours là ?" du protocole.
J+1 vendredi 28 août · 12h30Réponse courte (option)
Feature. Le heartbeat (tag 108) maintient la session vivante et détecte une coupure : pas de heartbeat attendu, on envoie un TestRequest, et si silence, on coupe proprement. C'est le "tu es toujours là ?" du protocole.