Индикатор Awesome Oscillator: формула, настройки и чтение
Awesome Oscillator — гистограмма импульса Билла Вильямса: простая скользящая средняя медианной цены бара за 5 периодов минус такая же за 34 периода. Она рисуется в отдельной панели и положительна, когда краткосрочный центр диапазона находится выше долгосрочного.
Senzoukria · Индикаторы · Updated September 2026
Awesome Oscillator — Моментум, в отдельной панели под графиком.
Что измеряет Awesome Oscillator
На вход подаётся медианная цена (high + low) / 2, а не закрытие: Вильямс хотел отслеживать движение центра аукциона на двух горизонтах, а закрытие — лишь один снимок в конце бара, шумный на внутридневных фьючерсах. Оба члена — обычные простые скользящие средние: ни экспоненциального сглаживания, ни сглаживания Уайлдера в исходном определении нет, и здесь тоже. Значения 5/34 по умолчанию взяты из дневной работы Вильямса — примерно неделя против месяца — и сохранены без изменений ради совпадения с другими платформами. Ни один столбец гистограммы не выводится, пока медленная средняя не заполнена, поэтому первые бары пустые, а не приблизительные.
Формула — так, как она реализована
Это не привычное определение из других источников, а то, что вычисляет поставляемый код, задокументированное рядом с реализацией:
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.
Как его читать
- Выше нуля краткосрочный центр диапазона находится над долгосрочным; ниже нуля — наоборот. Нулевая линия — единственный уровень, который задаёт формула.
- Расстояние от нуля показывает, насколько разошлись два горизонта: это величина импульса, а не убеждённость.
- Уменьшающиеся столбцы при продолжающемся движении цены говорят, что две средние сближаются и движение замедляется.
- Более высокий максимум цены при более низком максимуме AO — дивергенция импульса: описание того, что уже произошло, а не прогноз.
- На сбалансированном рынке столбцы плотно колеблются вокруг нуля, и смены знака почти ничего не значат.
Параметры и значения по умолчанию
Быстрый (5) и медленный (34) периоды задают два горизонта усреднения; амплитуду определяет прежде всего разрыв между ними, а не их абсолютная величина. Сближение даёт более спокойную гистограмму с частыми сменами знака, раздвижение — более крупные и медленные колебания и более длинный прогрев. Два цвета влияют только на отображение.
| Параметр | Тип | По умолчанию | Диапазон |
|---|---|---|---|
| Fast SMA | number | 5 | 1 – 200 |
| Slow SMA | number | 34 | 2 – 500 |
Чего он не показывает
Awesome Oscillator строится только по цене: до него не доходит информация ни об объёме, ни о дельте, ни о стакане, поэтому он не может отличить рост, встреченный агрессивными продажами, от роста, которому никто не сопротивлялся. Он запаздывает по конструкции, поскольку оба члена — запаздывающие средние. Медианная цена к тому же игнорирует, где закрылся бар, так что бар, резко развернувшийся к закрытию, читается так же, как бар, удержавший максимумы. Замечание об отображении: здесь столбцы окрашены по знаку значения, тогда как Вильямс окрашивал каждый столбец по его изменению относительно предыдущего, поэтому одни и те же данные на разных платформах могут выглядеть по-разному.
Похожие индикаторы
Эта страница на других языках
Frequently asked questions
- Почему Awesome Oscillator использует медианную цену, а не закрытие?
- Вильямс задумал его для отслеживания центра аукциона на двух горизонтах, а медианная цена (high + low) / 2 обобщает, где торговался бар, а не где он случайно остановился. Закрытие — единственный момент в конце бара, и на коротких внутридневных барах оно шумное. Как следствие, осциллятор игнорирует сильное закрытие внутри в остальном неизменного диапазона.
- Что означает пересечение нулевой линии Awesome Oscillator?
- Это значит, что средняя медианной цены за 5 периодов пересекла среднюю за 34 периода, то есть короткий горизонт перешёл с одной стороны длинного на другую. Это утверждение о двух запаздывающих средних, и обе уже сдвинулись до того, как пересечение отобразилось. Во флэте две средние стоят близко, и пересечения происходят на очень малых разностях.
- Обязательно ли оставлять периоды 5 и 34 по умолчанию?
- Нет — оба редактируются: от 1 до 200 для быстрой средней и от 2 до 500 для медленной. Значения по умолчанию — это значения самого Вильямса, и они сохранены, чтобы показания совпадали с другими платформами, использующими ту же пару. Их изменение меняет амплитуду и прогрев, так что сравнение с графиками на настройках по умолчанию теряет силу.