Indicateur Trade Size Distribution : formule, réglages et lecture
Trade Size Distribution mesure à quel point le volume d'une barre est concentré sur ses niveaux de prix les plus lourds. Il indique le pourcentage du volume de la barre traité sur les niveaux situés au-dessus d'un seuil de percentile calculé sur cette même barre, le 80e percentile par défaut.
Senzoukria · Indicateurs · Updated September 2026
Trade Size Distribution — Tape et flux, dans son propre panneau sous le graphique.
Ce que mesure Trade Size Distribution
Pour chaque barre, les volumes de ses niveaux de prix sont triés et un seuil est pris au rang le plus proche, sans interpolation : le seuil est donc toujours un volume de niveau réellement observé, et non un chiffre calculé entre deux niveaux. L'indicateur additionne ensuite le volume de chaque niveau strictement au-dessus de ce seuil, le divise par le volume total des niveaux de la barre et exprime le résultat en pourcentage. Les niveaux partageant le même prix sont d'abord fusionnés et les niveaux sans quantité exclus, si bien qu'une source qui publie une liste de niveaux non fusionnée ne peut pas gonfler le nombre de niveaux. Une barre footprint est agrégée et l'ordre des exécutions est perdu : ce qui est mesuré est la concentration du flux sur les prix, pas un histogramme des tailles de transactions individuelles.
La formule, telle qu’implémentée
Ce n'est pas la définition habituelle ailleurs : c'est ce que calcule le code livré, documenté à côté de son implémentation :
Points d'histogramme : `f` rend `null` quand la barre n'a pas d'information — la barre n'émet alors PAS de point (contrat `HistogramPoint` : pas de trou, pas de valeur inventée). */ function histPoints( bars: readonly FootprintBar[], f: (bar: FootprintBar, i: number) => number | null, ): HistogramPoint[] { const out: HistogramPoint[] = []; for (let i = 0; i < bars.length; i++) { const v = f(bars[i], i); if (v !== null) out.push({ time: bars[i].bucketTsNs, value: v }); } return out; } function histOut( points: HistogramPoint[], positiveColor: string, negativeColor: string, ): SeriesOutput { return { shape: "histogram", points, positiveColor, negativeColor }; } /** Un niveau de la barre indexé par sa CLÉ ENTIÈRE (indice de tick quand le tick est connu, quantification 1e-6 sinon — canon : jamais de clé f64). */ type KeyedLevel = { key: number; price: number; buy: number; sell: number }; /** Niveaux EXPLOITABLES de la barre (canon : qty = 0 et prix non fini exclus), agrégés par clé de prix, rendus en ordre ASCENDANT. L'agrégation est indispensable : deux entrées `levels` au même prix (source qui n'a pas fusionné, ou deux prix qui tombent sur le même tick) ne doivent compter QUE POUR UN niveau — sinon le compte de niveaux, les percentiles et la largeur traversée mentent tous les trois. / function barLevelsByKey( bar: FootprintBar, tickSize: number | null, ): KeyedLevel[] { const byKey = new Map<number, KeyedLevel>(); for (const lvl of usableLevels(bar)) { const key = priceKey(lvl.price, tickSize); const cur = byKey.get(key); if (cur !== undefined) { cur.buy += lvl.buyVolume; cur.sell += lvl.sellVolume; } else { byKey.set(key, { key, price: lvl.price, buy: lvl.buyVolume, sell: lvl.sellVolume, }); } } return [...byKey.values()].sort((a, b) => a.key - b.key); } /** CVD de séance par barre + indice de la PREMIÈRE barre de sa séance. CVD = Σ `totalDelta` depuis l'ouverture CME 17:00 CT, RESET à chaque ouverture (`splitSessions`) — canon, jamais le début du chart. Le second tableau permet aux fenêtres glissantes de refuser de comparer deux barres séparées par un reset : la différence de CVD n'aurait alors aucun sens. / function sessionCvd(bars: readonly FootprintBar[], ctx: SeriesContext): { cvd: number[]; sessionStart: number[]; } { const cvd = new Array<number>(bars.length).fill(0); const sessionStart = new Array<number>(bars.length).fill(0); for (const s of splitSessions(bars, ctx)) { let running = 0; for (let i = s.start; i <= s.end; i++) { running += bars[i].totalDelta; cvd[i] = running; sessionStart[i] = s.start; } } return { cvd, sessionStart }; } /** VWAP de séance par barre : Σ(tp·vol)/Σvol cumulé depuis l'ouverture CME 17:00 CT, reset à CHAQUE ouverture. Prix d'échantillon = prix TYPIQUE (H+L+C)/3, poids = volume de la barre — exactement le mode `typical` de `vwap.ts` (parité ATAS/Sierra/TradingView) : un second VWAP maison qui divergerait du VWAP dessiné serait pire qu'inutile. Barres à volume nul : n'alimentent rien ; avant le premier volume de la séance → `null` (pas de VWAP, pas de distance). / function sessionVwap(bars: readonly FootprintBar[], ctx: SeriesContext): Array<number | null> { const out = new Array<number | null>(bars.length).fill(null); for (const s of splitSessions(bars, ctx)) { let pv = 0; let v = 0; for (let i = s.start; i <= s.end; i++) { const w = bars[i].totalVolume; if (w > 0) { pv += typicalPrice(bars[i]) * w; v += w; } out[i] = v > 0 ? pv / v : null; } } return out; } /** Extrêmes COURANTS (running high/low) de la séance en cours, reset à chaque ouverture 17:00 CT. Définis dès la 1ʳᵉ barre : un extrême courant existe immédiatement, contrairement à une moyenne — pas de warm-up. */ function runningSessionExtremes( bars: readonly FootprintBar[], ctx: SeriesContext, ): Array<{ hi: number; lo: number }> { const out = new Array<{ hi: number; lo: number }>(bars.length); for (const s of splitSessions(bars, ctx)) { let hi = Number.NEGATIVE_INFINITY; let lo = Number.POSITIVE_INFINITY; for (let i = s.start; i <= s.end; i++) { if (bars[i].high > hi) hi = bars[i].high; if (bars[i].low < lo) lo = bars[i].low; out[i] = { hi, lo }; } } return out; } /** Offset de la barre depuis l'ouverture de SA séance, en NANOSECONDES. Les buckets sont des ns entiers sur la grille du timeframe : la clé est exacte (la règle `priceKey` ne concerne que les PRIX). */ function offsetNs(bar: FootprintBar, openSec: number): number { return bar.bucketTsNs - openSec * 1e9; } /** Offset de la barre depuis l'ouverture de SA séance, en MINUTES ENTIÈRES (plancher). Clé plus grossière qu'`offsetNs` — voir `time-of-day-volume` pour la raison d'être de ce choix. */ function offsetMinutes(bar: FootprintBar, openSec: number): number { return Math.floor((bar.bucketTsNs / 1e9 - openSec) / 60); } /** Seuil de percentile par RANG LE PLUS PROCHE (nearest-rank, méthode NIST « inverse empirique ») sur une liste TRIÉE ASCENDANTE et NON VIDE : rang = ⌈pct/100 × m⌉, borné à [1, m] → seuil = trié[rang − 1] Choix documenté : pas d'interpolation linéaire. Sur 4 ou 5 niveaux — le cas courant d'une barre footprint — une interpolation fabriquerait un seuil qui n'existe dans aucun niveau ; le rang le plus proche rend toujours un volume RÉELLEMENT observé. */ function nearestRankThreshold(sortedAsc: readonly number[], pct: number): number { const m = sortedAsc.length; const rank = Math.min(m, Math.max(1, Math.ceil((pct / 100) * m))); return sortedAsc[rank - 1]; } // ── Microstructure (Tape & flow) ──────────────────────────────────────────── /** Distribution des tailles — part du volume venant des niveaux LOURDS : seuil = percentile P des volumes de niveau de la barre (nearest-rank) value = 100 × Σ { vol(niveau) : vol(niveau) > seuil } / Σ vol(niveau) POURQUOI : une barre de 1 000 lots répartie sur 20 niveaux et une barre de 1 000 lots dont 800 sont tombés sur 2 prix ne racontent pas la même histoire. Cet indicateur mesure la CONCENTRATION du flux, c'est-à-dire la trace que laissent les gros participants — le seul angle honnête sur la « taille des trades » que permette une barre footprint AGRÉGÉE : la distribution des tailles trade par trade exigerait le tape brut (l'ordre des exécutions est perdu à l'agrégation). Le doc-comment le dit plutôt que le nom seul. Convention : comparaison STRICTE au seuil (`>`), donc une barre dont TOUS les niveaux pèsent pareil rend 0 — c'est une valeur MESURÉE (aucune concentration), pas un 0/0 déguisé : le dénominateur, lui, est > 0 par construction (`usableLevels` exclut les niveaux à volume nul). Défaut P=80 : le décile supérieur est trop fin pour 3-5 niveaux, la médiane ne mesure plus la concentration mais la simple asymétrie. Barre sans niveau exploitable → PAS de point. Aucun tick size requis (les clés ne servent qu'à dédupliquer).
Comment le lire
- Une lecture basse signifie que le volume de la barre s'est réparti assez uniformément sur ses niveaux de prix ; une lecture élevée, qu'une grande partie est tombée sur très peu de prix.
- Une concentration qui apparaît à l'extrémité d'un range mérite d'être ouverte sur le footprint lui-même, où vous voyez quel côté du tape l'a produite.
- Le nombre de niveaux exploitables d'une barre détermine ce que le seuil par défaut peut laisser au-dessus de lui : en dessous de cinq niveaux, le 80e percentile tombe sur le niveau le plus lourd et la lecture vaut 0 par construction.
- Une valeur exactement égale à 0 est un résultat mesuré, pas une donnée manquante : elle signifie qu'aucun niveau n'a porté plus de volume que le seuil.
- Les barres sans niveau exploitable ne produisent aucun point : un trou dans le panneau signifie que la barre ne portait pas de données par niveau, et non une lecture nulle.
Paramètres et valeurs par défaut
Percentile vaut 80 par défaut et accepte de 1 à 99. Comme le seuil est pris au rang le plus proche, le percentile et le nombre de niveaux interagissent directement : une barre ne renvoie une valeur non nulle que si elle contient au moins 100/(100 − P) niveaux exploitables, soit cinq niveaux par défaut. Sur une barre d'exactement cinq niveaux, le seuil tombe sur le quatrième plus lourd, et la lecture est la part portée par le seul niveau le plus lourd ; sur des barres plus larges, elle couvre à peu près le cinquième supérieur des niveaux. Abaisser le percentile vers 50 place le seuil au niveau médian de la barre, ce qui augmente les valeurs et mesure davantage l'asymétrie que la concentration. L'augmenter vers 99 exige cent niveaux avant que quoi que ce soit puisse dépasser le seuil : sur des barres footprint ordinaires, toutes les lectures retombent à 0.
| Paramètre | Type | Par défaut | Bornes |
|---|---|---|---|
| Percentile | number | 80 | 1 – 99 |
Ce qu’il ne montre pas
Ce n'est pas une distribution de la taille de chaque transaction. Reconstituer la taille de chaque exécution exige le tape brut, et cette information disparaît dès qu'une barre agrège ses niveaux. La comparaison stricte a une conséquence à connaître : une barre traitée à un seul prix renvoie 0, car aucun niveau ne peut dépasser un seuil égal à lui-même, alors qu'une telle barre est concentrée au maximum ; la même arithmétique explique chaque 0 sur les barres étroites au percentile par défaut. La lecture dépend donc du nombre de niveaux de la barre, qui découle du timeframe, du range de la barre et du regroupement des prix par la source : les lectures ne sont comparables que pour un même instrument et un même timeframe. Enfin, l'indicateur exige des données par niveau avec le volume par prix ; une source qui ne fournit que l'ouverture, le plus haut, le plus bas, la clôture et le volume ne produit rien.
Indicateurs liés
- Unfinished Auctions — Tape et flux
- Effort vs Result — Tape et flux
- POC Drift (ticks) — Tape et flux
- Cumulative buy volume — Tape et flux
- Cumulative sell volume — Tape et flux
- Buy/sell ratio — Tape et flux
Cette page dans d’autres langues
Frequently asked questions
- Peut-on mesurer la taille des transactions individuelles sur un graphique footprint ?
- Pas à partir d'une barre footprint agrégée. L'agrégation conserve le volume traité à chaque prix mais perd la séquence et la taille des exécutions individuelles qui l'ont produit. Ce qui reste mesurable, c'est la concentration de ce volume sur les prix, et c'est ce qu'indique cet indicateur.
- Que signifie une lecture de 0 sur Trade Size Distribution ?
- Qu'aucun niveau de prix de la barre n'a porté plus de volume que le seuil de percentile, puisque la comparaison est stricte. Cela arrive quand tous les niveaux pèsent à peu près autant, sur une barre traitée à un seul prix, et sur toute barre de moins de cinq niveaux exploitables au 80e percentile par défaut, où le seuil tombe sur le niveau le plus lourd lui-même. C'est une valeur mesurée, pas une erreur.
- Quel percentile utiliser pour Trade Size Distribution ?
- Partez de la valeur par défaut de 80, qui fonctionne sur les barres de cinq niveaux ou plus. Avant de la changer, vérifiez combien de niveaux vos barres comptent réellement : un percentile P exige au moins 100/(100 − P) niveaux avant qu'un niveau puisse dépasser le seuil, donc 99 est inutilisable sur une barre footprint typique. Un percentile proche de 50 mesure l'asymétrie de la distribution plutôt que sa concentration.