Elliott Wave Oscillator: formula and limits
The Elliott Wave Oscillator indicator measures the difference between a fast and a slow moving average. A common version uses 5 and 35 simple averages of the close. Its histogram shows their separation, but it cannot automatically confirm an Elliott Wave count.
Raw EWO = SMA(source, 5) − SMA(source, 35)
Percent EWO = 100 × raw EWO / current source
Example below: close source, SMA, 5/35 periods, percentage mode. Percent mode requires a positive source in this implementation.
Match the version before reading the histogram
The EWO name does not specify one universal implementation. koryu's published version uses configurable SMAs, defaults to close and offers percentage scaling. DGT's publication describes a 5/34 EMA variant. Neither name alone tells you which formula is on your chart.
| Choice | Effect | Verification |
|---|---|---|
| Source | Close and HL2 can produce different values. | Use the same input for both averages. |
| SMA or EMA | Changes the weighting and initialization. | Match the method and both periods. |
| Raw units | Same units as the source price; unbounded. | A value of 5 is a price difference, not 5%. |
| Percent units | A dimensionless ratio with a moving denominator. | Record whether the denominator is source or slow MA. |
For positive source values, a positive EWO means the fast average is above the slow one. A shrinking positive bar means that separation is smaller in the selected units. It does not mean price must be falling. This example colors bars by sign; other scripts may color them by change from the previous bar.
A 36-bar calculation you can reproduce
This is a hypothetical close-price sequence, not market data or a backtest. Bars 1 through 30 close at 100. Bars 31 through 35 close at 102, 104, 106, 108 and 110. Bar 36 closes at 100. Use SMA lengths 5 and 35.
| Quantity | Bar 35 | Bar 36 |
|---|---|---|
| Current close | 110 | 100 |
| Fast SMA | 530 / 5 = 106 | 528 / 5 = 105.6 |
| Slow SMA | 3,530 / 35 = 100.857143 | 3,530 / 35 = 100.857143 |
| Raw EWO | 5.142857 | 4.742857 |
| Percent of close | 4.675325% | 4.742857% |
At bar 36, the fast window drops 102 and adds 100. The slow window drops 100 and adds 100. Raw EWO falls by 0.4, yet percentage EWO rises because its denominator falls from 110 to 100. A divergence comparison can therefore change when you switch units. Rounded values are shown to six decimal places.
Dividing bar 35's difference by the slow SMA instead would give 5.099150%. That is another normalization, not a rounding error. The example code below divides by the selected source and leaves percentage output blank when that source is zero or negative.
Pine Script v6 with inspectable inputs
Paste the complete script into TradingView's Pine Editor and add it to a chart. The Data Window includes both averages and the raw difference for comparison. The script plots a histogram and confirmed zero-cross markers; it does not label waves, detect divergence or place orders.
// This source code is subject to the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Pineify
//@version=6
indicator("Elliott Wave Oscillator: explicit inputs", overlay=false, precision=6)
source = input.source(close, "Source")
fastLength = input.int(5, "Fast length", minval=1)
slowLength = input.int(35, "Slow length", minval=2)
maType = input.string("SMA", "Average type", options=["SMA", "EMA"])
usePercent = input.bool(true, "Percent of current source")
if fastLength >= slowLength
runtime.error("Fast length must be smaller than slow length.")
fastSma = ta.sma(source, fastLength)
slowSma = ta.sma(source, slowLength)
fastEma = ta.ema(source, fastLength)
slowEma = ta.ema(source, slowLength)
fast = maType == "SMA" ? fastSma : fastEma
slow = maType == "SMA" ? slowSma : slowEma
validSamples = ta.cum(not na(source) ? 1 : 0)
ready = validSamples >= slowLength and not na(source) and not na(fast) and not na(slow)
raw = ready ? fast - slow : na
ewo = usePercent ? (source > 0 ? 100 * raw / source : na) : raw
crossUp = ta.crossover(ewo, 0)
crossDown = ta.crossunder(ewo, 0)
confirmedUp = crossUp and barstate.isconfirmed
confirmedDown = crossDown and barstate.isconfirmed
plot(ewo, "EWO (selected units)", color=ewo >= 0 ? color.teal : color.red, style=plot.style_histogram, linewidth=2)
plot(fast, "Fast MA", display=display.data_window)
plot(slow, "Slow MA", display=display.data_window)
plot(raw, "Raw MA difference", display=display.data_window)
hline(0, "Zero", color=color.gray)
plotshape(confirmedUp, "Confirmed cross up", shape.triangleup, location.bottom, color.teal, size=size.tiny)
plotshape(confirmedDown, "Confirmed cross down", shape.triangledown, location.top, color.red, size=size.tiny)
alertcondition(confirmedUp, "EWO above zero", "EWO crossed above zero on a closed chart bar.")
alertcondition(confirmedDown, "EWO below zero", "EWO crossed below zero on a closed chart bar.")Teal bars are zero or positive; red bars are negative. Triangles mark zero crosses after the chart candle closes. The live histogram still updates during the open candle. Create an alert from the named EWO condition and choose Once Per Bar Close. TradingView documents the confirmation state used here.
Warm-up and input checks
- Fast length must be smaller than slow length. Equal periods would collapse the difference to zero; reversed periods would reverse its meaning.
- The script waits for slowLength non-missing source observations. Continuous close data with 5/35 inputs first produces a value on the 35th bar. A first valid value is not itself a zero cross.
- EMA uses recursive history. The minimum sample gate does not remove initialization effects; load enough prior data and compare later bars when matching an EMA implementation.
- Changing from a one-hour chart to a daily chart changes what 35 observations represent. Keep symbol, session, timeframe and chart type fixed while comparing settings. No best timeframe is established here.
Divergence needs a rule and a confirmation time
A bearish divergence can be defined as a higher price swing high with a lower EWO value at that swing. For example, two hypothetical confirmed price highs of 110 and 114 with raw EWO readings of 5.14 and 4.20 meet that comparison. A bullish divergence reverses the relationship at swing lows. Neither comparison identifies a wave number or guarantees a reversal.
- Choose the price pivots before comparing readings. One explicit rule requires a high above each of the two bars on either side, with strict comparisons so tied highs fail.
- Record EWO on those same price-pivot bars. Do not silently compare unrelated oscillator peaks; a separate oscillator-pivot method needs its own pairing rule.
- Wait for the second right-hand bar to close. A pivot at bar 50 is available at bar 52's close under this rule, not at bar 50. A label backdated to bar 50 must not become a historical entry there.
- Keep source, average type and units fixed. Then define a separate entry trigger, exit, sizing and costs if testing a strategy.
TradingView's repainting documentation explains why retrospective pivot plots can hide this delay. An expanding EWO peak can continue expanding; a divergence can persist while price keeps trending. Repeated zero crosses in a range also provide no automatic wave confirmation.
Educational calculation example. No performance test or investment recommendation is provided. Syntax validation establishes that code compiles; it does not establish profitable trading rules.
EWO, AO and the MACD histogram
Compare formulas before comparing colors. Awesome Oscillator uses 5/34 SMAs of HL2. Its usual color rule measures change from the preceding value. A close-based 5/35 SMA EWO with sign colors differs in source, slow period and color meaning.
The MACD histogram subtracts a signal average from the MACD line. EWO directly plots the fast-minus-slow average difference without that extra subtraction. An EMA EWO can resemble a MACD line with matching inputs, but that does not make it the MACD histogram.
Specify the EWO behavior in Pineify
Use the Pine Script AI Coding Agent to implement a written rule and inspect the generated source. Include the average method, price source, periods, denominator and confirmation time. A precise request for this example is:
Build a Pine Script v6 EWO using close, SMA lengths 5 and 35, and optional percent-of-current-close output. Leave percent output blank for nonpositive close. Show both averages in the Data Window. Confirm zero-cross alerts only at chart-bar close. Do not assign Elliott wave numbers.
First compare individual bars against the calculation table. If adding divergence, write the pivot and pairing rules explicitly. Only then add strategy exits, order timing and trading costs as a separate specification.
Open Pine Script AI Coding AgentElliott Wave Oscillator questions
EWO subtracts a slow moving average from a fast moving average. This page defaults to SMA(close, 5) minus SMA(close, 35), displayed as a percentage of the current close. Check the source, average type, periods and normalization before comparing two EWO scripts.
No. The moving-average difference contains no rule that assigns wave numbers or validates a complete Elliott pattern. A large peak can inform a proposed count, but it cannot establish Wave 3, Wave 5 or the end of a correction by itself.
Both appear in published implementations. They are different calculations, so match the script you intend to reproduce. The example defaults to SMA with lengths 5 and 35; its EMA option keeps those inputs until you change them. There is no performance comparison on this page that establishes a better version.
Percentage mode divides the moving-average difference by a changing denominator. This example uses the current source. A script that divides by the slow average will produce another value. Raw EWO is in source-price units; percentage EWO is a ratio, not a return earned by a strategy.
The example marks a cross only when the chart candle closes. The live histogram can still change before that close. A cross above zero means the fast average moved above the slow average when using raw mode or a positive percentage denominator; it does not confirm a new Elliott impulse.
The example waits for at least slowLength valid source observations. With continuous closes and the default length, the first output is on bar 35. EMA values retain initialization effects beyond that minimum, so compare loaded history as well as settings when checking another implementation.
A divergence describes a disagreement between selected price swings and oscillator readings. A trade needs separate confirmation, entry, exit, sizing and cost rules. If swing detection requires two bars to the right, a signal is only available after those two bars close, even when a label is drawn on the earlier peak.
Sources and further reading
Reviewed October 17, 2026. Community publications document their authors' implementations; they are not TradingView endorsements of trading outcomes.
- koryu: configurable SMA EWO publication
- DGT: EMA EWO variant publication
- TradingView: Awesome Oscillator calculation
- TradingView: repainting and delayed pivots
- TradingView: bar confirmation states
- TradingView: MACD line, signal and histogram