Chaikin Oscillator on TradingView
The Chaikin Oscillator is the fast EMA of the accumulation/distribution line minus its slow EMA, commonly using 3 and 10 bars. It measures ADL momentum. It is neither the ADL itself nor the rolling volume ratio used by Chaikin Money Flow.
Use the calculation table and Pine Script below to check individual bars, EMA initialization and data gaps before turning a zero cross into a strategy rule.
Chaikin Oscillator formula
Marc Chaikin's oscillator starts with the close's position inside the current bar. The multiplier is +1 at the high, 0 at the midpoint and -1 at the low when the range is nonzero.
MFM = ((close - low) - (high - close)) / (high - low)
MFV = MFM × volume
ADL = previous ADL + MFV
CO = EMA(ADL, fast) - EMA(ADL, slow)
For length N, the EMA recurrence uses α = 2 / (N + 1): current EMA = α × current ADL + (1 - α) × previous EMA. Both averages must use the same ADL series and a documented starting rule.
Formula reference: TradingView's Chaikin Oscillator documentation. Zero-range handling and gap resets below are explicit choices in this example.
A four-bar audit of the 3/10 calculation
This is synthetic OHLCV data, not a market result. Start ADL at zero and seed both EMAs with the first ADL value of 50, matching the script. The fast weight is 1/2 and the slow weight is 2/11. Calculations retain full precision; the table rounds to three decimals.
| Bar | H / L / C | Volume | MFM | MFV | ADL | EMA 3 | EMA 10 | Raw CO |
|---|---|---|---|---|---|---|---|---|
| 1 | 12 / 8 / 11 | 100 | 0.5 | 50 | 50 | 50.000 | 50.000 | 0.000 |
| 2 | 12 / 8 / 9 | 100 | -0.5 | -50 | 0 | 25.000 | 40.909 | -15.909 |
| 3 | 12 / 8 / 12 | 100 | 1 | 100 | 100 | 62.500 | 51.653 | 10.847 |
| 4 | 10 / 10 / 10 | 100 | 0 (policy) | 0 | 100 | 81.250 | 60.443 | 20.807 |
At bar 3, the fast EMA is 0.5 × 100 + 0.5 × 25 = 62.5. The slow EMA is (2/11) × 100 + (9/11) × 40.90909 = 51.65289. Their difference changes sign even though ADL does not need to cross zero.
Bar 4 adds no flow, but the two EMAs keep approaching ADL at different speeds, so CO changes. These are internal audit values: the script hides plotted CO for the first nine valid bars at the default slow length of 10. That warm-up is a chosen minimum, not proof that initialization effects have disappeared.
Inputs and data policy
| Input | Default | Constraint and effect |
|---|---|---|
| Fast EMA length | 3 | Integer ≥ 1, smaller than slow. Controls the faster ADL average. |
| Slow EMA length | 10 | Integer ≥ 2, larger than fast. Also sets the number of valid bars before plotting resumes. |
| Bar condition | This script does | What to check |
|---|---|---|
| High equals low | Set MFM to zero; retain the bar in the EMA sequence. | No close location can be inferred from a zero range. |
| Volume is zero | Add zero MFV; update both EMAs. | Zero is a supplied value. It is different from unavailable volume. |
| Missing/negative volume or invalid HLC | Reset ADL and both EMAs; show a gap and orange shading. | After data returns, seed a new segment and wait slowLength valid bars. |
| No bar exists during a closed session | No execution and no reset. | A scheduled market closure is not an explicit na bar. |
| Fast length ≥ slow length | Stop with an input error. | Equal lengths produce zero; reversed lengths invert the intended sign. |
This reset policy avoids silently assigning invented flow to missing data. It also gives up continuity across that gap. Compare feeds and session settings before comparing oscillator values; tick volume counts price updates and is not traded quantity. TradingView explains volume availability by feed.
Copy the Chaikin Oscillator Pine Script
Paste this standalone indicator into TradingView's Pine Editor and add it to the chart. It exposes the two lengths, a zero reference, confirmed cross markers and audit values in the Data Window. Manual EMA recurrence makes the reset and seed policy visible in the code.
//@version=6
indicator("Chaikin Oscillator with data checks [Pineify]", overlay=false)
fastLength = input.int(3, "Fast EMA length", minval=1)
slowLength = input.int(10, "Slow EMA length", minval=2)
if fastLength >= slowLength
runtime.error("Fast EMA length must be smaller than slow EMA length.")
invalidBar = na(high) or na(low) or na(close) or high < low or close > high or close < low or na(volume) or volume < 0
multiplier = high == low ? 0.0 : (2.0 * close - high - low) / (high - low)
var float adl = na
var float fastEma = na
var float slowEma = na
var int validBars = 0
// Missing data starts a new segment; it is never silently replaced by zero volume.
if invalidBar
adl := na
fastEma := na
slowEma := na
validBars := 0
else
adl := nz(adl, 0.0) + multiplier * volume
fastAlpha = 2.0 / (fastLength + 1)
slowAlpha = 2.0 / (slowLength + 1)
fastEma := na(fastEma) ? adl : fastAlpha * adl + (1.0 - fastAlpha) * fastEma
slowEma := na(slowEma) ? adl : slowAlpha * adl + (1.0 - slowAlpha) * slowEma
validBars += 1
ready = validBars >= slowLength
co = ready ? fastEma - slowEma : na
crossUp = ta.crossover(co, 0.0)
crossDown = ta.crossunder(co, 0.0)
confirmedUp = barstate.isconfirmed and crossUp
confirmedDown = barstate.isconfirmed and crossDown
plot(co, "Chaikin Oscillator", color=color.blue, linewidth=2, style=plot.style_linebr)
hline(0, "Zero", color=color.gray)
bgcolor(not ready ? color.new(color.orange, 85) : na, title="Invalid data or warm-up")
plot(adl, "ADL audit", display=display.data_window)
plot(fastEma, "Fast EMA audit", display=display.data_window)
plot(slowEma, "Slow EMA audit", display=display.data_window)
plotshape(confirmedUp, "Confirmed cross up", shape.triangleup, location.bottom, color.green, size=size.tiny)
plotshape(confirmedDown, "Confirmed cross down", shape.triangledown, location.top, color.red, size=size.tiny)
alertcondition(confirmedUp, "CO crossed above zero", "Chaikin Oscillator crossed above zero at bar close.")
alertcondition(confirmedDown, "CO crossed below zero", "Chaikin Oscillator crossed below zero at bar close.")| Output | Meaning |
|---|---|
| Blue line | Fast minus slow EMA, after the selected warm-up. |
| Gray zero line | The two EMA values are equal here. |
| Green / red triangle | A cross above / below zero confirmed at bar close. It is not an order. |
| Orange background | Invalid data or fewer than slowLength consecutive valid bars. |
| Data Window audit fields | ADL and both EMA states, including warm-up values. |
The open-bar line can change as price and volume update. Markers and alert conditions use barstate.isconfirmed. Create an alert from the desired condition in TradingView. Closing-bar confirmation does not validate the trading hypothesis or prevent later data revisions. Pine bar-state reference.
Read zero crosses without confusing CO, ADL and CMF
| Measure | Calculation | Interpretation boundary |
|---|---|---|
| ADL | Cumulative MFV | Its absolute starting level is not a buy/sell threshold. |
| Chaikin Oscillator | Fast ADL EMA minus slow ADL EMA | Positive means fast exceeds slow. It has no fixed upper or lower limit. |
| Chaikin Money Flow | Rolling sum(MFV) / sum(volume) | A volume-normalized window ratio; its thresholds do not transfer to CO. |
A rising negative CO means the EMA gap is narrowing while fast remains below slow. A positive CO does not establish positive flow on the current bar. It also does not measure actual cash entering an asset. CO's zero cross compares two ADL averages, whereas a MACD signal-line cross compares MACD with its own smoothed signal.
The close-location formula ignores the previous close. For example, after a previous close of 20, a bar with high 12, low 8 and close 11 contributes positive MFV despite the price drop. Price gaps and gaps in available data are separate issues.
- Audit a clean interval against TradingView's built-in CO using the same feed, session, timeframe and lengths. Check ADL, then each EMA before comparing the final difference.
- Inspect initialization and missing bars when values differ. This example's explicit reset policy can intentionally differ from the built-in series.
- Define pivots and their confirmation delay before adding divergence rules. A visual disagreement alone is not a timed entry.
- Test entry candidates with separately defined exits, position size, commission and slippage. Repeated zero crosses can occur without a lasting price move.
See the ADL guide and CMF guide for their separate calculations. Educational material; no return or signal accuracy is implied.
Turn the audit into a Pineify coding request
Use Pine Script AI Coding Agent to specify input constraints, confirmation timing and the missing-data policy. Keep the generated source open for review and compare its bar values before adding strategy orders.
Create a Pine v6 Chaikin Oscillator with fast 3 and slow 10 inputs. Require fast < slow. Use zero MFV for zero-range bars. Reset ADL and EMA states on missing volume, hide CO until 10 valid bars resume, and mark zero crosses only at bar close. Expose ADL and both EMAs in the Data Window. Keep exits and costs separate.Open Pine Script AI Coding Agent
Chaikin Oscillator questions
Sources and calculation notes
Official references checked October 17, 2026. The synthetic table and gap-handling policy are this page's worked example, not measured trading performance.