Quand RV ment-elle, et de combien ?

RV mesure la variance vraiment réalisée tick-by-tick — pas celle qu'on a supposée le matin.

La realized variance est l'estimateur empirique le plus simple qu'on puisse écrire sur des log-returns intraday : on les met au carré et on les somme sur une fenêtre temporelle. Mais simple n'est pas exact. Cette page nomme de combien RV ment quand on la lit à τ = 60 s, et elle pourrait mentir silencieusement si on l'implémentait sans discipline.


Définition

Soit m_i = (bid_i + ask_i) / 2 le mid-quote au tick i, et r_i = log(m_i) − log(m_{i-1}) le log-return entre deux ticks consécutifs. Pour une fenêtre temporelle τ (en nanosecondes) :

RV(t, τ) = Σ_{i : t_i ∈ (t-τ, t]} r_i²

La fenêtre est temporelle, pas en éléments fixés. Raison : la densité de ticks varie d'un facteur cinq entre 09:35 et 11:00 New York time ([bouchaud2018trades, Chap. 2 §2.4 — U-shape intraday] ; docs/adr/0003-stats-and-classifier.md §1 L67-69). Compter en éléments mélangerait deux régimes microstructurels distincts ; compter en temps les sépare.

Convention en bordure : Err(EmptyWindow) si la fenêtre ne contient aucun tick. Pas de NaN silencieux — invariant INV-RV-1 à INV-RV-5 de l'ADR-0003 (docs/adr/0003-stats-and-classifier.md §1).


Algorithme — deque temporelle online

L'implémentation tient dans une VecDeque<(i64, f64)> qui mémorise les couples (ts_ns, r²), plus un cumul sum_sq: f64. Voir research/crates/salim-core/src/stats.rs §RvAccumulator lignes 30-111 pour le code complet.

Étape de push(ts_ns, log_return) :

  1. Eviction temporelle : while buf.front().0 < ts_ns - window_ns { sum_sq -= front.1; pop_front(); }.
  2. Append : sum_sq += r²; buf.push_back((ts_ns, r²)).
  3. Snapshot : sum_sq directement — pas de re-calcul.

Coût amorti O(1) par push, pire cas O(k)k est le nombre d'éléments expulsés au tick courant (rare en pratique, borné par INV-RV-2 ci-dessous). Une discipline debug_assert!(sum_sq ≥ 0) post-eviction protège contre la dérive négative quand la fenêtre se vide (research/crates/salim-core/src/stats.rs:76-81).


Borne d'erreur — Andersen–Bollerslev–Diebold–Labys 2003

C'est le nombre qui doit être lu en même temps que la valeur. Sous le modèle BS-Heston, pour un nombre N = τ/Δ de ticks à pas régulier :

Var(RV) ≈ 2 · IV² · (Δ / τ)
σ(RV)   ≈ IV · √(2 / N)

[andersen2003modeling, Eq. 3 p. ~587] ; [@andersen2003modeling, Thm. 2 p. ~587] pour la consistance RV →_p IV as Δ → 0.

Numériquement, à τ = 60 s et Δ = 1 s (donc N = 60) :

σ(RV_short) / IV ≈ √(2 / 60) ≈ 18 %

— le 18 % est dérivé directement de l'Eq. 3 de [@andersen2003modeling, p. ~587]. C'est du bruit estimateur, pas de la vraie volatilité. Salim qui lit RV_short(60s) = 2 · baseline lit en réalité RV_short / baseline ∈ [1.6, 2.4] à 1-σ ([andersen2003modeling, Eq. 3 p. ~587], propagation multiplicative). Le seuil binaire « calme/agité » devient une zone floue.


Stabilité numérique — f64 naïf suffit (table compressée)

Le Σ r² peut être implémenté de cinq façons connues. Pour RV non-centered sur n ticks bornés |n| ≤ 6·10⁶ (peak ARM open dans docs/adr/0003-stats-and-classifier.md §1 L72) :

MéthodeBorne erreur relativeVerdict
f64 naïf sum_sq += r²(n−1)·u ≈ 7·10⁻¹⁰ à n = 6·10⁶ ([higham2002accuracy, Thm. 4.1 p. ~81])OK — adopté
Pairwise summationO(log n)·u ≈ 2·10⁻¹⁵ ([higham2002accuracy, Algo. 4.1 p. ~89])Overkill
Kahan compensated≈ 2u ≈ 2·10⁻¹⁶ ([higham2002accuracy, Thm. 4.7 p. ~95])Overkill
Welford one-passO(u) indep de n (Welford 1962)Interdit pour RV — voir docs/adr/0003-stats-and-classifier.md §1 L72-86

Pourquoi Welford est interdit, en une phrase : RV n'a pas de moyenne soustraite (c'est Σ r², pas Σ (r − r̄)²), donc la cancellation que Welford corrige n'existe pas, et la version Welford de RV exigerait un état supplémentaire sans gain d'exactitude (docs/adr/0003-stats-and-classifier.md §1 L79-86).

L'erreur du f64 naïf à 7·10⁻¹⁰ ([higham2002accuracy, Thm. 4.1 p. ~81]) est dix-huit ordres de grandeur plus petite que le bruit estimateur de 18 % ([andersen2003modeling, Eq. 3 p. ~587]) calculé ci-dessus. Optimiser la première sans bouger la seconde est du cargo cult.


Pour ton cas

Pour toi, Salim, en clair :

Si tu veux serrer le ±18 %, la seule façon honnête est d'augmenter N (donc τ, donc latence de décision) : à τ = 600 s, Δ = 1 s, N = 600, le bruit relatif tombe à √(2/600) ≈ 5.8 % ([@andersen2003modeling, Eq. 3 p. ~587]). C'est la raison du double horizon RV_short(60s) / RV_long(600s) de l'ADR-0003 §1.


Limites du résultat


Adversaire endogène

estimator-instability — le risque que Salim sur-interprète une valeur ponctuelle de RV ou un franchissement de seuil isolé. Antidote nommé dans cette page : la borne ±18 % à N = 60 ([@andersen2003modeling, Eq. 3 p. ~587]) est lue en même temps que la valeur, et reliée explicitement à la nécessité d'hystérèse côté classifier (docs/adr/0003-stats-and-classifier.md §4).


Références