Indicateur Awesome Oscillator : formule, réglages et lecture

L'Awesome Oscillator est l'histogramme de momentum de Bill Williams : la moyenne mobile simple à 5 périodes du prix médian de la barre moins celle à 34 périodes. Il se trace dans un panneau séparé et devient positif quand le centre du range à court horizon passe au-dessus de celui à long horizon.

Senzoukria · Indicateurs · Updated September 2026


Awesome Oscillator Momentum, dans son propre panneau sous le graphique.

Ce que mesure Awesome Oscillator

L'entrée est le prix médian, (haut + bas) / 2, et non la clôture : Williams voulait suivre le déplacement du centre de l'enchère sur deux horizons, et la clôture n'est qu'un instantané de fin de barre, bruité sur des futures intraday. Les deux termes sont de simples moyennes mobiles arithmétiques, il n'y a ni lissage exponentiel ni lissage de Wilder dans la définition d'origine, et il n'y en a pas ici non plus. Les valeurs par défaut 5/34 viennent du travail en journalier de Williams, à peu près une semaine contre un mois, et sont conservées telles quelles pour rester comparables aux autres plateformes. Aucun point d'histogramme n'est émis avant que la moyenne lente ne soit complète : les premières barres restent vides plutôt qu'approchées.

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 :

Période entière ≥ `min` depuis les params (garde-fou UI, même helper que momentum.ts / stats.ts). */ function intParam( params: Record<string, unknown>, key: string, fallback: number, min = 1, ): number { return Math.max(min, Math.floor(numParam(params, key, fallback))); } function clamp(v: number, lo: number, hi: number): number { return Math.min(hi, Math.max(lo, v)); } function toPoints( bars: readonly FootprintBar[], values: ReadonlyArray<number | null>, ): SeriesPoint[] { return bars.map((b, i) => ({ time: b.bucketTsNs, value: values[i] ?? null })); } /** Histogramme : une barre sans valeur n'émet PAS de point (contrat `HistogramPoint`, pas de trou représentable). */ function histPoints( bars: readonly FootprintBar[], values: ReadonlyArray<number | null>, ): HistogramPoint[] { const out: HistogramPoint[] = []; for (let i = 0; i < bars.length; i++) { const v = values[i]; if (v !== null && v !== undefined) { out.push({ time: bars[i].bucketTsNs, value: v }); } } return out; } /** SMA N sur série À TROUS : null dès qu'UNE valeur de la fenêtre est null — moyenner autour d'un trou mentirait sur la période effective. */ function smaNullable( values: ReadonlyArray<number | null>, period: number, ): Array<number | null> { const n = Math.max(1, Math.floor(period)); const out: Array<number | null> = new Array<number | null>(values.length).fill(null); for (let i = n - 1; i < values.length; i++) { let sum = 0; let ok = true; for (let j = i - n + 1; j <= i; j++) { const v = values[j]; if (v === null) { ok = false; break; } sum += v; } if (ok) out[i] = sum / n; } return out; } /** WMA N (poids linéaires 1..N, le plus récent pèse N) tolérante aux trous : null dès qu'une valeur manque dans la fenêtre. Même formule que `helpers.wmaSeries`, qui n'accepte que des `number[]`. */ function wmaNullable( values: ReadonlyArray<number | null>, period: number, ): Array<number | null> { const n = Math.max(1, Math.floor(period)); const denom = (n * (n + 1)) / 2; const out: Array<number | null> = new Array<number | null>(values.length).fill(null); for (let i = n - 1; i < values.length; i++) { let acc = 0; let ok = true; for (let j = 0; j < n; j++) { const v = values[i - n + 1 + j]; if (v === null) { ok = false; break; } acc += v * (j + 1); } if (ok) out[i] = acc / denom; } return out; } /** EMA N (graine SMA) sur une série dont les valeurs définies forment un SUFFIXE contigu — sortie d'un lissage précédent. Le préfixe reste null ; série toute-null ou trou interne → tout-null (dégradation propre, on ne devine pas). Copie locale de la primitive de momentum.ts (non exportée). */ function suffixEma( values: ReadonlyArray<number | null>, period: number, ): Array<number | null> { const out: Array<number | null> = new Array<number | null>(values.length).fill(null); const start = values.findIndex((v) => v !== null); if (start < 0) return out; const defined: number[] = []; for (let i = start; i < values.length; i++) { const v = values[i]; if (v === null) return out; defined.push(v); } const ema = emaSeries(defined, period); for (let j = 0; j < ema.length; j++) out[start + j] = ema[j]; return out; } /** ROC en POURCENT : 100·(x[i] − x[i−N])/x[i−N]. Référence NULLE → null (pas de division par zéro déguisée) — même règle que `roc` (momentum.ts). */ function rocPercentSeries( values: readonly number[], period: number, ): Array<number | null> { const n = Math.max(1, Math.floor(period)); const out: Array<number | null> = new Array<number | null>(values.length).fill(null); for (let i = n; i < values.length; i++) { const ref = values[i - n]; if (ref !== 0) out[i] = (100 * (values[i] - ref)) / ref; } return out; } /** Prix médian de la barre — l'entrée de Bill Williams et d'Ehlers. */ function hl2(b: FootprintBar): number { return (b.high + b.low) / 2; } /** Égalités RSI, STRICTEMENT celles de `rsi` (momentum.ts) : marché PLAT (les deux moyennes nulles) → null (pas d'information directionnelle) ; que des gains → 100 ; que des pertes → 0. */ function rsiValue(avgGain: number, avgLoss: number): number | null { if (avgLoss === 0 && avgGain === 0) return null; if (avgLoss === 0) return 100; if (avgGain === 0) return 0; return 100 - 100 / (1 + avgGain / avgLoss); } /** RSI de WILDER sur une série quelconque (closes, ou série de streaks pour Connors). Graine = moyenne SIMPLE des N premières variations, puis lissage Wilder avg = (avg·(N−1) + x)/N ; premier point à l'indice N. Copie locale de la primitive de momentum.ts (non exportée) — même formule, mêmes égalités, donc `connors-rsi` et `rsi` restent cohérents à l'écran. */ function wilderRsiSeries( values: readonly number[], period: number, ): Array<number | null> { const n = Math.max(1, Math.floor(period)); const out: Array<number | null> = new Array<number | null>(values.length).fill(null); if (values.length < n + 1) return out; let avgGain = 0; let avgLoss = 0; for (let i = 1; i <= n; i++) { const ch = values[i] - values[i - 1]; if (ch > 0) avgGain += ch; else avgLoss -= ch; } avgGain /= n; avgLoss /= n; out[n] = rsiValue(avgGain, avgLoss); for (let i = n + 1; i < values.length; i++) { const ch = values[i] - values[i - 1]; avgGain = (avgGain * (n - 1) + Math.max(0, ch)) / n; avgLoss = (avgLoss * (n - 1) + Math.max(0, -ch)) / n; out[i] = rsiValue(avgGain, avgLoss); } return out; } /** AO de Bill Williams — factorisé parce que l'Accelerator le consomme : SMA_fast(hl2) − SMA_slow(hl2), null tant que la LENTE n'est pas amorcée. */ function awesomeSeries( bars: readonly FootprintBar[], fast: number, slow: number, ): Array<number | null> { const mid = bars.map(hl2); const f = smaSeries(mid, fast); const s = smaSeries(mid, slow); return mid.map((_, i) => { const a = f[i]; const b = s[i]; return a !== null && b !== null ? a - b : null; }); } /** Étage « stochastique + lissage exponentiel à facteur fixe » de Schaff — factorisé parce que STC l'applique DEUX FOIS (cf. sa déf) : %K = 100·(x − min(x, cycle))/(max(x, cycle) − min(x, cycle)) état ← (premier %K défini) puis état + f·(%K − état) Fenêtre PLATE (max == min) ou incomplète → sortie null ET ÉTAT FIGÉ : on ne nourrit pas la récurrence avec un %K inventé, et on ne reconduit pas la dernière valeur (le `nz(f1[1])` des portages Pine peindrait un plateau faux). Un trou ainsi créé se propage aux fenêtres suivantes qui le contiennent — c'est le comportement voulu. / function schaffStage( src: ReadonlyArray<number | null>, cycle: number, factor: number, ): Array<number | null> { const n = Math.max(2, Math.floor(cycle)); const out: Array<number | null> = new Array<number | null>(src.length).fill(null); let state: number | null = null; for (let i = n - 1; i < src.length; i++) { let lo = Number.POSITIVE_INFINITY; let hi = Number.NEGATIVE_INFINITY; let ok = true; for (let j = i - n + 1; j <= i; j++) { const v = src[j]; if (v === null) { ok = false; break; } if (v < lo) lo = v; if (v > hi) hi = v; } const cur = src[i]; if (!ok || cur === null) continue; // trou → état figé, sortie null const range = hi - lo; if (!(range > 0)) continue; // fenêtre plate → null, jamais 0 const k = (100 * (cur - lo)) / range; state = state === null ? k : state + factor * (k - state); out[i] = state; } return out; } // ── Défs — Bill Williams ──────────────────────────────────────────────────── /** Awesome Oscillator (Bill Williams) — lissage SMA SIMPLE (pas d'EMA, pas de Wilder ; c'est la définition originale) sur le PRIX MÉDIAN : hl2 = (high + low)/2 AO = SMA_fast(hl2) − SMA_slow(hl2) POURQUOI hl2 et pas le close : Williams mesure le déplacement du CENTRE de l'enchère sur deux horizons ; le close n'est qu'un instantané de fin de barre, très bruité en intraday futures. Défauts 5/34 (Williams) — la paire « une semaine / un mois » de son analyse quotidienne, gardée telle quelle pour la parité avec ATAS/TradingView. HISTOGRAMME : warm-up (< slow barres) → AUCUN point. Le renderer colore par SIGNE (contrat `SeriesOutput.histogram`) ; Bill Williams colore par SENS DE VARIATION barre à barre — écart assumé et documenté, le shape du moteur ne transporte pas de couleur par point.

Comment le lire

  • Au-dessus de zéro, le centre du range à court horizon est au-dessus de celui à long horizon ; sous zéro, c'est l'inverse. La ligne de zéro est le seul niveau que la formule définit.
  • La distance à zéro mesure l'écartement des deux horizons : c'est une amplitude de momentum, pas une conviction.
  • Des barres qui rétrécissent alors que le prix progresse encore disent que les deux moyennes convergent et que le mouvement décélère.
  • Un plus haut de prix supérieur face à un plus haut d'AO inférieur est une divergence de momentum, la description de ce qui s'est déjà produit, pas une prévision.
  • Dans un marché équilibré, les barres oscillent serré autour de zéro et les changements de signe portent peu de sens.

Paramètres et valeurs par défaut

Le rapide (5) et le lent (34) fixent les deux horizons de moyennage ; c'est l'écart entre eux, plus que leur taille absolue, qui pilote l'amplitude. Les rapprocher donne un histogramme plus calme avec de fréquents changements de signe, les éloigner donne des oscillations plus amples, plus lentes et un amorçage plus long. Les deux couleurs n'affectent que l'affichage.

Awesome Oscillator — paramètres exposés dans l’application, avec les valeurs livrées.
ParamètreTypePar défautBornes
Fast SMAnumber51 – 200
Slow SMAnumber342 – 500

Ce qu’il ne montre pas

L'Awesome Oscillator ne voit que le prix : aucun volume, aucun delta, aucune information de carnet ne lui parvient, il ne peut donc pas séparer une hausse absorbée par des vendeurs agressifs d'une hausse qui n'a rencontré personne. Il retarde par construction, puisque ses deux termes sont des moyennes glissantes. Le prix médian ignore aussi l'endroit où la barre a clôturé : une barre qui s'est violemment retournée en clôture se lit comme une barre qui a tenu ses plus hauts. Une note d'affichage : les barres sont ici colorées selon le signe de la valeur, alors que Williams colorait chaque barre selon sa variation par rapport à la précédente, les mêmes données peuvent donc paraître différentes d'une plateforme à l'autre.

Voir tous les indicateurs

Cette page dans d’autres langues

Frequently asked questions

Pourquoi l'Awesome Oscillator utilise-t-il le prix médian plutôt que la clôture ?
Williams l'a conçu pour suivre le centre de l'enchère sur deux horizons, et le prix médian, (haut + bas) / 2, résume l'endroit où la barre a tradé plutôt que l'endroit où elle s'est arrêtée. La clôture n'est qu'un instant unique en fin de barre, bruité sur des barres intraday courtes. En conséquence, l'oscillateur ignore une clôture forte à l'intérieur d'un range par ailleurs inchangé.
Que signifie un croisement de la ligne de zéro sur l'Awesome Oscillator ?
Que la moyenne à 5 périodes du prix médian a croisé celle à 34 périodes : l'horizon court est passé d'un côté à l'autre de l'horizon long. C'est un constat sur deux moyennes glissantes, et toutes les deux ont déjà bougé avant que le croisement ne s'affiche. En range, les deux moyennes restent proches et les croisements se produisent sur de très petites différences.
Faut-il conserver les périodes 5 et 34 par défaut ?
Non, les deux sont modifiables, de 1 à 200 pour la moyenne rapide et de 2 à 500 pour la lente. Les valeurs par défaut sont celles de Williams et sont conservées pour que les lectures correspondent aux autres plateformes utilisant le même couple. Les changer change l'amplitude et l'amorçage, si bien que les comparaisons avec des graphiques en réglages par défaut ne tiennent plus.

Keep reading