مؤشر Trade Size Distribution: الصيغة والإعدادات وطريقة القراءة
يقيس مؤشر Trade Size Distribution مدى تركّز حجم الشمعة على أثقل مستويات أسعارها. ويبلّغ عن النسبة المئوية من حجم الشمعة التي جرى تداولها على مستويات تتجاوز عتبة مئينية محسوبة من الشمعة نفسها، باستخدام المئين 80 افتراضيًا.
Senzoukria · المؤشرات · Updated September 2026
Trade Size Distribution — الشريط والتدفق, في لوحة مستقلة أسفل الرسم.
ما الذي يقيسه Trade Size Distribution
لكل شمعة، تُرتَّب أحجام مستويات أسعارها وتؤخذ عتبة بأقرب رتبة، دون استيفاء، فتكون العتبة دائمًا حجم مستوى رُصد فعلًا لا رقمًا محسوبًا بين مستويين. ثم يجمع المؤشر حجم كل مستوى أعلى من تلك العتبة تمامًا، ويقسمه على إجمالي حجم مستويات الشمعة ويبلّغ عن النتيجة كنسبة مئوية. تُدمج المستويات التي تتشارك السعر نفسه أولًا وتُستبعد المستويات بلا كمية، فلا يستطيع مصدر ينشر قائمة مستويات غير مدموجة أن يضخّم عدد المستويات. شمعة الـ footprint مجمَّعة وترتيب التنفيذات مفقود، فما يُقاس هو تركّز التدفق عبر الأسعار، لا هيستوغرام لأحجام الصفقات الفردية.
الصيغة كما هي منفَّذة في الكود
هذا ليس التعريف الشائع في مصادر أخرى، بل ما يحسبه الكود المنشور فعليًا، موثَّقًا بجانب التنفيذ:
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).
كيف تقرأه
- القراءات المنخفضة تعني أن حجم الشمعة توزّع بالتساوي تقريبًا على مستويات أسعارها؛ والقراءات المرتفعة تعني أن حصة كبيرة منه وقعت على أسعار قليلة جدًا.
- التركّز الذي يظهر عند طرف نطاق يستحق أن تفتحه على الـ footprint نفسه، حيث ترى أي جانب من الشريط أنتجه.
- عدد المستويات الصالحة في الشمعة يحدد ما يمكن أن تتركه العتبة الافتراضية فوقها: تحت خمسة مستويات يقع المئين 80 على أثقل مستوى وتكون القراءة 0 بطبيعة البناء.
- القيمة 0 تمامًا نتيجة مقيسة لا بيانات مفقودة: تعني أنه لا يوجد مستوى حمل حجمًا أكبر من العتبة.
- الشموع بلا مستوى صالح لا تنتج أي نقطة، فالفجوة في اللوحة تعني أن الشمعة لم تحمل بيانات مستويات لا قراءة صفرية.
المعاملات والقيم الافتراضية
المئين افتراضيًا 80 ويقبل من 1 إلى 99. ولأن العتبة تؤخذ بأقرب رتبة، يتفاعل المئين وعدد المستويات مباشرة: لا تعيد الشمعة قيمة غير صفرية إلا إذا احتوت على 100/(100 − P) مستوى صالحًا على الأقل، أي خمسة مستويات عند القيمة الافتراضية. على شمعة من خمسة مستويات تمامًا تقع العتبة على رابع أثقل مستوى، فتكون القراءة الحصة التي يحملها أثقل مستوى وحده؛ وعلى الشموع الأوسع تغطي نحو الخُمس الأعلى منها. خفض المئين نحو 50 يضع العتبة عند المستوى الوسيط للشمعة، ما يرفع القيم ويقيس اللاتماثل أكثر من التركّز. ورفعه نحو 99 يتطلب مئة مستوى قبل أن يتجاوز أي شيء العتبة، فتنهار كل القراءات إلى 0 على شموع footprint العادية.
| المعامل | النوع | القيمة الافتراضية | المدى |
|---|---|---|---|
| Percentile | number | 80 | 1 – 99 |
ما لا يُظهره
هذا ليس توزيعًا لأحجام الصفقات الفردية. فإعادة بناء حجم كل تنفيذ يتطلب الشريط الخام، وهذه المعلومة تضيع بمجرد أن تجمّع الشمعة مستوياتها. وللمقارنة الصارمة نتيجة ينبغي معرفتها: الشمعة التي تداولت عند سعر واحد تعيد 0، لأنه لا يمكن لأي مستوى أن يتجاوز عتبة تساويه، مع أن مثل هذه الشمعة في أقصى درجات التركّز؛ والحساب نفسه يفسّر كل 0 على الشموع الضيقة عند المئين الافتراضي. لذلك تتوقف القراءة على عدد المستويات في الشمعة، وهو يتبع الإطار الزمني ومدى الشمعة وتجميع الأسعار في المصدر، فلا تُقارن القراءات إلا داخل أداة واحدة وإطار زمني واحد. وأخيرًا، يتطلب المؤشر بيانات مستويات بحجم لكل سعر؛ والمصدر الذي لا يوفر إلا الافتتاح والقمة والقاع والإغلاق والحجم لا ينتج شيئًا.
مؤشرات ذات صلة
- Unfinished Auctions — الشريط والتدفق
- Effort vs Result — الشريط والتدفق
- POC Drift (ticks) — الشريط والتدفق
- Cumulative buy volume — الشريط والتدفق
- Cumulative sell volume — الشريط والتدفق
- Buy/sell ratio — الشريط والتدفق
هذه الصفحة بلغات أخرى
Frequently asked questions
- هل يمكن قياس أحجام الصفقات الفردية على رسم footprint؟
- ليس من شمعة footprint مجمَّعة. فالتجميع يحتفظ بالحجم المتداول عند كل سعر لكنه يتخلص من تسلسل التنفيذات الفردية التي أنتجته وأحجامها. ما يبقى قابلًا للقياس هو مدى تركّز ذلك الحجم عبر الأسعار، وهو ما يبلّغ عنه هذا المؤشر.
- ماذا تعني القراءة 0 في توزيع حجم الصفقات؟
- تعني أنه لا يوجد مستوى سعري في تلك الشمعة حمل حجمًا أكبر من العتبة المئينية، لأن المقارنة صارمة. ويحدث ذلك حين تتقارب أوزان كل المستويات، وعلى شمعة تداولت عند سعر واحد، وعلى أي شمعة فيها أقل من خمسة مستويات صالحة عند المئين 80 الافتراضي، حيث تقع العتبة على أثقل مستوى نفسه. إنها قيمة مقيسة، لا خطأ.
- أي مئين أستخدم لتوزيع حجم الصفقات؟
- ابدأ من القيمة الافتراضية 80، التي تعمل على الشموع التي تحمل خمسة مستويات أو أكثر. وقبل تغييرها، تحقق من عدد المستويات الذي تحتويه شموعك فعلًا: المئين P يحتاج إلى 100/(100 − P) مستوى على الأقل قبل أن يتجاوز أي مستوى العتبة، فالقيمة 99 غير صالحة على شمعة footprint نموذجية. والمئين القريب من 50 يقيس مدى لاتماثل التوزيع لا مدى تركّزه.