Quand faut-il accepter qu'un changement de régime n'est pas un blip ?

Trois régimes, deux seuils, un dwell time — l'hystérèse t'évite de switcher à chaque tick.

J = 1 − BV/RV te donne, à chaque fenêtre 60s, une mesure instantanée de la part de variance attribuable aux sauts (bipower-and-jumps). Mais Salim ne trade pas une mesure ; il trade un état. Cette page raconte comment passer de mesure-qui-bouge à verdict-qui-tient — sans switcher à chaque tick, sans rater une vraie bascule.


State machine — trois régimes, et c'est tout

J > θ_high = 0.7

J > θ_high ET dwell ≥ 60s

J < θ_low = 0.4 ET dwell ≥ 60s

J < θ_low = 0.4 (immédiat, anti-piège)

Smooth

Transition

Rough

Trois états seulement — Smooth, Transition, Rough. Pas de continuum, pas de quatre niveaux : « le régime n'est pas dans la nature, il est dans la décision » (ADR-0003 §4 ontologie). Le classifier ne prétend pas modéliser la microstructure ; il te donne un mot — Smooth, Transition, Rough — sur lequel tu peux poser une règle de trailing.

L'invariant clé : on n'entre pas dans Rough directement depuis Smooth. Le seul chemin descendant vers la rugosité passe par Transition, et ce passage est soumis à un dwell time (cf. §dwell ci-bas). Le seul chemin remontant immédiat est \(Rough → Transition\) — anti-piège nommé.


L'hystérèse, vue de deux côtés

Deux seuils, pas un. \(θ_high = 0.7\) pour entrer en zone haute, \(θ_low = 0.4\) pour en sortir. Le gap \(θ_high − θ_low = 0.3\) n'est pas cosmétique — il fait deux boulots différents en même temps. La synthèse délibérative (§C9 redondance pédagogique délibérée) impose de garder les deux lectures côte à côte dans le texte, pas de choisir.

Lecture 1 — anti-chattering numérique

RV à fenêtre 60s porte une erreur d'estimation relative bornée à ~18 % à N=60 returns (realized-variance §borne d'erreur — \(\sqrt(2/N)\) avec N=60). En cascade : BV porte la même classe d'erreur, et J = 1 − BV/RV flotte alors \(\pm0.05–0.10\) même si rien ne change dans le marché. Avec un seuil unique à 0.55, ce bruit ferait chatter le classifier des dizaines de fois par heure. Le gap de 0.3 dépasse confortablement l'amplitude de ce flottement.

Conséquence opérationnelle : si J dépasse 0.7 puis retombe à 0.5, le classifier reste en zone haute. Il ne redescendra pas tant que J n'a pas franchi 0.4. C'est de l'arithmétique anti-bruit, basique.

Lecture 2 — Ulysses contract anti-Salim-of-tomorrow-morning

Le même gap, lu autrement : c'est un engagement contractuel à attendre 60s avant de croire au changement. Tversky & Kahneman (1992) Journal of Risk and Uncertainty 5, p. 311 (Cumulative Prospect Theory) mesure une asymétrie pertes/gains de \(λ ≈ 2.25\) — le coût psychique d'un mauvais switch (resserrer un stop à tort, élargir un trailing pour rien) est \(~2\times\) le bénéfice d'un bon switch. La notion de loss aversion vient de Kahneman & Tversky 1979 ; la valeur calibrée 2.25 vient de 1992. La symétrie du gap (anti-chattering) corrige une asymétrie cognitive, pas seulement numérique.

Salim, à 6 h du matin, fatigué, voit J = 0.71 sur sa montre. Sans le dwell, sans l'hystérèse, il bascule l'élargissement du trailing. À 6 h 03, J est retombé à 0.55. Le classifier intelligent n'a jamais bougé. Le classifier naïf a coûté à Salim un trade resserré au mauvais moment, et le frottement émotionnel d'avoir cru à un faux signal — frottement payé au taux \(\lambda\) \(\approx\) 2.25.

L'hystérèse est le même objet vu par deux lentilles : un filtre passe- bas pour le bruit numérique, et un Ulysses contract pour le bruit psychologique. Les deux lectures ne sont pas concurrentes — elles co-justifient le même gap (synthèse §C9 + §I2).


Le dwell time — asymétrique par construction

Smooth     → Transition           : pas de dwell  (alerte précoce, sans coût)
Transition → Rough                : dwell ≥ 60s   (anti-blip, on confirme)
Transition → Smooth               : dwell ≥ 60s   (anti-faux-retour-au-calme)
Rough      → Transition           : pas de dwell  (anti-piège, on sort vite)

Pourquoi cette asymétrie. Entrer dans Rough est un engagement coûteux côté Salim (trailing élargi, taille réduite) — il faut le mériter, 60s de confirmation. Sortir de Rough est gratuit côté risque (on ne fait que relâcher la garde, et seulement vers Transition, pas vers Smooth) — donc immédiat. Si la rugosité s'effondre brusquement, le classifier ne bloque pas Salim en mode défensif.

L'autre asymétrie : \(Transition → Smooth\) est aussi gardée par 60s de dwell. Sans ce dwell, un J qui retombe brièvement sous 0.4 entre deux bouffées rugueuses dégonflerait le diagnostic — exactement le contraire de ce qu'on veut quand le marché oscille en zone limite.


Auction hard-block — la fenêtre où le classifier se tait

Si l'heure UTC \(\in\) [14:30, 14:34], le classifier reste forcé Smooth quoi qu'il arrive.

La fenêtre d'ouverture NY est structurellement haute-variance : pricing discontinu, matching d'auction, pas un processus Lévy. Bouchaud, Bonart, Donier, Gould (2018) chap. 2 §2.4 décrit le U-shape intraday de la volatilité comme artefact de mécanisme (open + close), pas comme régime de queue lourde — la même mesure J y a une sémantique différente. Si le classifier réagit à l'auction comme à un saut de marché, Salim ressort de l'ouverture en mode défensif pour rien.

Le hard-block est la responsabilité du caller (salim-pipeline::run), pas du classifier (ADR-0003 §4 — discipline caller, pas de complexification de la state machine). Quand l'horloge passe 14:34 UTC, le pipeline reprend l'appel normal à classifier.step(). Référence empirique : un trigger d'ordre observé entre 09:30 et 09:34 ET tombe exactement dans la fenêtre d'auction — c'est exactement le cas où le classifier ne doit pas parler.


Invariants algo

IDInvariant
INV-CLASSIFIER-MONOTONIC-DWELLToute transition \(state' ≠ state\) implique (ts_ns − entered_at_ns) ≥ dwell_min_ms · 1e6, sauf \(Smooth → Transition\) (anti-blip ne s'applique pas à l'alerte) et \(Rough → Transition\) (anti-piège). Property-test + TLC.
INV-CLASSIFIER-AUCTIONTick d'auction \(\to\) le classifier ne transitione pas. Discipline caller, pas dans le classifier.
INV-CLASSIFIER-MIN-TICKJ n'est pas consommé tant que tick_count_short < 30 et tick_count_long < 300 — sinon BV instable produit \(J → 1\) artificiel (ADR-0005 patch (a)).

Détail complet : docs/adr/0003-stats-and-classifier.md §4 table.


Pour ton cas

Prends un scénario standard de gap-and-go avorté : tu poses un stop sous le bas du chandelier d'allumage, un limit au-dessus du high, et le marché traverse le stop sans toucher le limit. Si ce classifier tourne en parallèle, il marque la zone Rough dès que J reste au-dessus de 0.7 pendant 60s — typiquement quelques minutes avant que la cascade prenne ton stop. Sa recommandation : trailing élargi à \(1.5\times\) la min-tick tant que l'état tient. Voir pivot-j-based pour pourquoi le ratio RV_short / RV_long seul aurait raté ce switch (il plafonne à ~0.2 sur la journée — il n'a aucune chance de franchir 0.7).

Le diagnostic n'est pas « il fallait mettre des stops plus larges » — c'est « il fallait que tes stops sachent dans quel régime ils opèrent ». L'hystérèse est ce qui rend la décision tenable : tu ne resserres pas parce que J vient de descendre à 0.65 ; tu attends que J traverse 0.4 et y reste 60s.


Limites


Références


Adversary nommé : salim-of-tomorrow-morning. Mitigation portée par cette page : l'hystérèse double-nommée raconte explicitement pourquoi attendre 60s — ce n'est pas une lourdeur d'ingénieur, c'est \(λ ≈ 2.25\) fait code.