TradingView indicator calculations

Gann swing indicator: bar rules and confirmation timing

A Gann swing indicator turns high/low bar comparisons into directional swings. The reversal count and treatment of inside, outside and equal-price bars determine its output. A swing high can occur several candles before the downswing confirms. This guide separates those times and supplies an explicit Gann-style reference you can reproduce in Pine Script.

See the decision guide

Choose a rule version before comparing charts

Optuma documents Gann swings as comparisons of bar highs and lows, with configurable swing counts and inside/outside handling. Its optional breakout rule can reverse a multi-bar swing early. Consequently, a script name alone does not identify a reproducible algorithm. The public reference here is Pineify Gann-style v1, dated October 18, 2026: an original educational implementation, not a copy of Optuma or a claim to reproduce every historical Gann convention.

  • The baseline follows the publicly documented directional-bar concept. Our explicit choices below govern ambiguous bars, initialization, count resets and event timing. Breakout overrides are disabled; no percentage threshold or future-bar pivot window is used.
  • Use standard OHLC candles on one chart timeframe. The example does not infer the intrabar order of a high and low, and it does not request higher-timeframe data.

Classify against the immediately previous physical candle

All comparisons use completed highs and lows. Skipping a bar in the reversal count does not skip it as the reference for the next classification. These strict rules also define what happens at equality, where implementations often differ.

  • Track the active high during an upswing and the active low during a downswing on every valid closed bar, including neutral and outside bars. A strict new active extreme resets pending reversal evidence. Equal extremes retain the earliest bar index.
  • An outside bar expands both sides of the prior range. OHLC alone cannot tell which extreme occurred first. This version avoids inventing two intrabar reversals; a different outside-bar convention will produce different swings.
Bar conditionClassificationEffect in reference v1
H > H[1] and L > L[1]UpOne upward observation.
H < H[1] and L < L[1]DownOne downward observation.
H < H[1] and L > L[1]InsideNo directional observation; preserve a pending count.
H > H[1] and L < L[1]OutsideReset the pending count; no reversal on this bar.
Either comparison is equal, including identical rangesEqual / neutralNo directional observation; preserve a pending count unless the active extreme extends.

Count opposite observations and preserve the candidate extreme

Start direction at zero. The first Up or Down bar seeds direction and its current extreme without emitting a pivot. In an established swing, an opposite directional bar increments the pending count. A same-direction bar, an outside bar or a new active extreme resets it. Inside and equality bars otherwise pause it. Thus N means successive opposite directional observations under this policy, not necessarily N consecutive calendar candles.

  • During a pending downswing, retain the lowest low from its first qualifying Down bar onward; during a pending upswing, retain the highest high. Include intervening neutral bars in that candidate extreme.
  • At count N, emit the old active extreme and its original bar index, then reverse direction and initialize the new active extreme from the retained candidate. Reset the count to zero.
  • Missing high/low or high below low clears state. The next valid bar only supplies history; a later directional comparison seeds a new swing. Changing the loaded start or inputs can change the seeded state.

Recalculate all 16 bars with N = 1, 2 and 3

Prices below are invented in arbitrary units. No symbol, currency or trading performance is implied. Opens and closes may be anywhere inside their ranges because the rule uses only high and low. Each state cell is direction / pending opposite count after the close. An asterisk marks a newly confirmed reversal; initialization has none.

  • Bar 6 is Down relative to inside bar 5: 10 < 10.5 and 8 < 9.5. That gives the second opposite observation for N = 2.
  • Bar 11 updates the developing high to 13 but produces no reversal. Bar 13 shares bar 12 high of 12, so its lower low alone does not count as Down.
BarHigh / lowTypeN = 1N = 2N = 3
110 / 8History0 / 00 / 00 / 0
211 / 9Up seedUp / 0Up / 0Up / 0
312 / 10UpUp / 0Up / 0Up / 0
411 / 9DownDown / 0 *Up / 1Up / 1
510.5 / 9.5InsideDown / 0Up / 1Up / 1
610 / 8DownDown / 0Down / 0 *Up / 2
79 / 7DownDown / 0Down / 0Down / 0 *
810 / 8UpUp / 0 *Down / 1Down / 1
911 / 9UpUp / 0Up / 0 *Down / 2
1012 / 10UpUp / 0Up / 0Up / 0 *
1113 / 9OutsideUp / 0Up / 0Up / 0
1212 / 10InsideUp / 0Up / 0Up / 0
1312 / 9Equal highUp / 0Up / 0Up / 0
1411 / 8DownDown / 0 *Up / 1Up / 1
1510 / 7DownDown / 0Down / 0 *Up / 2
169 / 6DownDown / 0Down / 0Down / 0 *

Keep pivot location separate from information availability

The completed event log below uses one-based fixture bar numbers. Pine bar_index is zero-based within its loaded dataset; compare the corresponding positions rather than assuming these numbers match a live chart. The final swing shape would have the same three confirmed vertices for all counts in this fixture, but their availability times differ.

  • At bar 5 close, the two-bar version still has an unconfirmed developing high at bar 3. A chart drawn later through bar 3 must not be treated as a signal that existed then.
  • The script places a circle and label at the confirmation bar, at the earlier pivot price. The label names the pivot index. Its gray step line is the developing extreme observed at each close, not a finalized zigzag line.
  • An alert or order can only act after confirmation under this contract. A fill at the earlier extreme is not justified by this indicator; an execution rule, spread, fees and slippage are separate.
Confirmed pivotN = 1: known at closeN = 2: known at closeN = 3: known at close
High 12 at bar 3Bar 4Bar 6Bar 7
Low 7 at bar 7Bar 8Bar 9Bar 10
High 13 at bar 11Bar 14Bar 15Bar 16

Complete Pine Script v6 reference

Set Opposite directional bars to 1, 2 or 3. All state updates are gated by barstate.isconfirmed, which TradingView documents as true on historical bars and the closing update of a realtime bar. There is no negative plot offset and no label backdated to the pivot candle. The code is an indicator, not a trading strategy.

Pineify Gann-style v1. The newest gray extreme remains provisional until a reversal confirms. Syntax validation checks compilation, not equivalence to other Gann products or profitability.pine
//@version=6
// Pineify educational Gann-style reference v1, 2026-10-18.
// Strict directional bars; inside/equality pause; outside resets count.
indicator("Gann-style v1: confirmation-time events", overlay = true, max_labels_count = 500)
int n = input.int(2, "Opposite directional bars", minval = 1, maxval = 3)
var int direction = 0
var int count = 0
var float extreme = na
var int extremeBar = na
var float pending = na
var int pendingBar = na
float pivot = na
int pivotBar = na
bool flipUp = false
bool flipDown = false
bool valid = not na(high) and not na(low) and high >= low
bool previousValid = not na(high[1]) and not na(low[1]) and high[1] >= low[1]
if barstate.isconfirmed
    if not valid or not previousValid
        direction := 0
        count := 0
        extreme := na
        extremeBar := na
        pending := na
        pendingBar := na
    else
        bool upBar = high > high[1] and low > low[1]
        bool downBar = high < high[1] and low < low[1]
        bool outside = high > high[1] and low < low[1]
        int step = upBar ? 1 : downBar ? -1 : 0
        if direction == 0
            if step != 0
                direction := step
                extreme := step == 1 ? high : low
                extremeBar := bar_index
        else
            bool extends = direction == 1 ? high > extreme : low < extreme
            if extends
                extreme := direction == 1 ? high : low
                extremeBar := bar_index
            if outside or step == direction or extends
                count := 0
                pending := na
                pendingBar := na
            if not outside and step == -direction
                count += 1
                float candidate = direction == 1 ? low : high
                if count == 1 or (direction == 1 ? candidate < pending : candidate > pending)
                    pending := candidate
                    pendingBar := bar_index
            else if count > 0
                float candidate = direction == 1 ? low : high
                if direction == 1 ? candidate < pending : candidate > pending
                    pending := candidate
                    pendingBar := bar_index
            if count >= n
                pivot := extreme
                pivotBar := extremeBar
                direction := -direction
                flipUp := direction == 1
                flipDown := direction == -1
                extreme := pending
                extremeBar := pendingBar
                count := 0
                pending := na
                pendingBar := na
if not na(pivot)
    string kind = flipDown ? "High" : "Low"
    label.new(bar_index, pivot, kind + " pivot index " + str.tostring(pivotBar) + " confirmed now", style = flipDown ? label.style_label_down : label.style_label_up, color = flipDown ? color.red : color.blue, textcolor = color.white)
plot(direction == 0 ? na : extreme, "Developing extreme at observation time", color.gray, style = plot.style_stepline)
plot(pivot, "Pivot price on confirmation bar", color.orange, 3, plot.style_circles)
plot(direction, "Direction: up 1, down -1", display = display.data_window)
plot(count, "Pending opposite count", display = display.data_window)
plot(pivotBar, "Confirmed pivot bar index", display = display.data_window)
alertcondition(flipUp, "Confirmed upswing", "Gann-style v1 upswing confirmed at bar close")
alertcondition(flipDown, "Confirmed downswing", "Gann-style v1 downswing confirmed at bar close")

Test equality, outside bars and incomplete information

Replay completed bars with the exact rule version and record direction, pending count, pivot price, pivot bar and confirmation bar. Keep snapshots before advancing so the final chart cannot conceal when a fact became available.

  • Close-only updates do not protect against revised data, changed sessions, a different history start or different settings. Those inputs must match when comparing reloads.
  • More confirmation observations delay availability. They do not guarantee fewer losses; sideways ranges can still alternate confirmed swings. This page reports no backtest.
Boundary inputRequired behavior
Repeated identical rangesDirection stays zero if unseeded; otherwise no new directional count.
Two-bar upswing: Down, then outside bar, then DownThe outside bar clears the first count; the final Down is only count 1.
An equal high at the active highRetain the earlier high index; a tie is not a strict extension.
Neutral bar makes a new active extremeMove the extreme and reset pending evidence even though no directional bar was counted.
Zero or negative valid pricesComparisons still work; this version performs no division by price.
Missing or inverted high/lowClear state and require valid adjacent bars before reseeding.
An open realtime candleNo state transition, pivot marker or alert before its close.

Why this is different from a percentage Zig Zag

This Gann-style rule asks how high/low bar structure changes and how many opposite observations have accumulated. A percentage Zig Zag asks whether a move meets a price-distance threshold; implementations may also require local-pivot confirmation. The two settings measure different things.

  • For example, high/low pairs (100, 99), (100.2, 99.2), (100.1, 99.1) seed an upswing then confirm a one-bar Gann-style high at 100.2. The fall to 99.1 is only 100 × 1.1 / 100.2 = 1.0978%, below a 5% Zig Zag reversal threshold.
  • That percentage calculation isolates the distance test; it does not claim to reproduce a complete Zig Zag pivot-window algorithm. Likewise, a large outside candle does not reverse this Gann-style reference merely because its range exceeds 5%.

Give Pineify the state rules and acceptance table

The Pine Script AI Coding Agent can help draft or edit a script from the written contract. Supply reference v1, the 16-bar fixture, the equality and outside-bar policies, and the separate pivot/confirmation fields. Request syntax checking, then compare numerical output and alert timestamps on TradingView.

  • Ask for the N = 2 high at bar 3 to be reported only at bar 6 close. Require no reversal at outside bar 11 and no directional count at equal-high bar 13.
  • Changing outside handling, breakout overrides or comparison references creates a new version. Recalculate the fixture before using a modified script; the agent name alone is not numerical validation.
Where Pineify fits

Pine Script AI Coding Agent

Draft a Gann-style inspection script from explicit bar rules, then verify its confirmation-time outputs against the worked fixture.

Draft a swing inspection script

Frequently asked questions

Educational indicator analysis, not investment advice. All prices are hypothetical. The original reference defines one Gann-style convention, not a complete trading strategy or a reproduction of a proprietary indicator. Confirmation does not establish a profitable trade.

Sources and verification

Published by Pineify. Pineify is an independent product and is not affiliated with TradingView. Sources support the technical explanations; examples do not establish trading performance.