TradingView indicators

Optimized Trend Tracker: baseline, bands and state

The Optimized Trend Tracker (OTT) follows a moving-average baseline with percentage-based stops that lock until the baseline crosses them. A persistent direction state selects the active stop. This guide separates those steps so you can check the plotted line and understand why it can reverse repeatedly in a range.

"Optimized" is the indicator's name. It does not establish that its settings fit your symbol, timeframe or trading costs.

Version used here: public OTT 3.0, dated December 24, 2020

The publication by KivancOzbilgic credits Anil Ozeksi. It defaults to VAR and adds a choice of eight moving averages. This page covers single-line OTT, not OTT Bands, MOTT or HOTT/LOTT. Sources checked October 17, 2026.

Inspect the six-bar calculation

Choose the baseline before comparing values

In the VAR branch of version 3.0, U and D are the sums of positive and negative source changes over nine bars. The normalized CMO ratio is (U−D)/(U+D), with an undefined result replaced by zero. With length N, the effective weight is a = 2/(N+1) × |CMO ratio|. The baseline then follows M = a × source + (1−a) × previous M.

For N=2, U=6 and D=3, a=2/9. If the previous baseline is 100 and the current source is 103, the next VAR is 100.6667. EMA-2 instead uses a fixed weight of 2/3 and produces 102 from the same prior baseline and source. These are different algorithms, even with the same length.

The original VAR recurrence substitutes zero for missing prior VAR values. That startup policy can affect early values, especially after a flat window with a zero weight. Compare enough prior history and the same source before attributing differences to the stop formula. The copyable subset below preserves that recurrence; it offers VAR and EMA only.

From percentage bands to a locked direction

For a positive baseline M and percentage p, the fresh candidates are L=M×(1−p/100) and S=M×(1+p/100). The following rules use the previous bar's already locked stops, not yesterday's fresh candidates.

StepExact ruleConsequence
Long stopIf M > previous L, use max(fresh L, previous L); otherwise fresh L.A pullback can leave L unchanged.
Short stopIf M < previous S, use min(fresh S, previous S); otherwise fresh S.A rebound can leave S unchanged.
DirectionFrom −1, switch to +1 if M > previous S. From +1, switch to −1 if M < previous L.Otherwise retain direction. Equality alone does not flip it.
Raw OTTSelect T=L for +1, S for −1. If M > T, use T×(1+p/200); otherwise T×(1−p/200).The final half-percent adjustment differs from the original band width.
Displayed OTTRead raw OTT[2].Use the value from two chart bars earlier.

The two-bar history reference adds delay. It is not a negative plot offset or a reduction in lag. See Pine's history-reference semantics. Percentage bands also assume a suitable positive price series; this example is not designed for zero-crossing spreads or oscillators.

A six-bar example: locking followed by repeated reversals

This synthetic example deliberately selects EMA-3, p=2%, initial EMA=100 and initial direction=+1. Each later EMA is half the new close plus half the previous EMA. It is a transparent arithmetic fixture, not the default VAR-2 configuration or a market backtest. Values below are rounded only for display.

EMA-3 source sequence: 100, 104, 100, 96, 104, 96
BarCloseEMALocked LLocked SDirectionRaw OTTOTT[2]
010010098102+198.9800na
110410299.96104.04+1100.9596na
210010199.96103.02+1100.959698.9800
39698.596.53100.47-199.4653100.9596
4104101.2599.225103.275+1100.2173100.9596
59698.62596.6525100.5975-199.591599.4653

On bar 2, fresh L is 101×0.98=98.98, but the previous locked L is 99.96. Because 101 remains above 99.96, L stays at 99.96 and raw OTT stays at 99.96×1.01=100.9596. On bar 3, EMA=98.5 falls below that previous stop, so direction switches to −1. The selected short stop is 98.5×1.02=100.47; raw OTT becomes 100.47×0.99=99.4653.

The rebound on bar 4 crosses the previous short stop and restores +1. Bar 5 crosses the previous long stop and restores −1. Locking did not prevent whipsaws. A rule that buys the rebound and sells the next decline can repeatedly trade against the following move; commissions and slippage add costs. The table measures indicator state, not executable fills or returns.

Pine Script v6: expose each intermediate value

Paste this educational adaptation into the TradingView Pine Editor. Select EMA, length 3 and percent 2 to match the arithmetic convention above, or keep VAR, 2 and 1.4 to inspect the public defaults. Use the Data Window to compare stops, direction and current raw OTT. The script is an indicator; it places no orders.

Pine Script v6 · VAR/EMA subset
//@version=6
// Adapted from OTT v3.0 (2020-12-24), © KivancOzbilgic.
// Original concept: Anil Ozeksi. MPL 2.0: https://mozilla.org/MPL/2.0/
// Educational subset: VAR and EMA; confirmed support-line crosses.
indicator("OTT: inspect baseline, stops and state", overlay=true)

source = input.source(close, "Source")
length = input.int(2, "Baseline length", minval=1)
percent = input.float(1.4, "Percent", minval=0.1, maxval=99, step=0.1)
mode = input.string("VAR", "Baseline", options=["VAR", "EMA"])

upMove = source > source[1] ? source - source[1] : 0.0
downMove = source < source[1] ? source[1] - source : 0.0
upSum = math.sum(upMove, 9)
downSum = math.sum(downMove, 9)
cmoRatio = nz((upSum - downSum) / (upSum + downSum))
weight = 2.0 / (length + 1) * math.abs(cmoRatio)
varBaseline = 0.0
varBaseline := nz(weight * source) + (1.0 - weight) * nz(varBaseline[1])
emaBaseline = ta.ema(source, length)
baseline = mode == "VAR" ? varBaseline : emaBaseline

margin = baseline * percent * 0.01
longStop = baseline - margin
previousLong = nz(longStop[1], longStop)
longStop := baseline > previousLong ? math.max(longStop, previousLong) : longStop
shortStop = baseline + margin
previousShort = nz(shortStop[1], shortStop)
shortStop := baseline < previousShort ? math.min(shortStop, previousShort) : shortStop

direction = 1
direction := nz(direction[1], direction)
direction := direction == -1 and baseline > previousShort ? 1 : direction == 1 and baseline < previousLong ? -1 : direction
activeStop = direction == 1 ? longStop : shortStop
rawOtt = baseline > activeStop ? activeStop * (200 + percent) / 200 : activeStop * (200 - percent) / 200
displayedOtt = rawOtt[2]

crossUp = ta.crossover(baseline, displayedOtt)
crossDown = ta.crossunder(baseline, displayedOtt)
confirmedUp = barstate.isconfirmed and crossUp
confirmedDown = barstate.isconfirmed and crossDown
plot(baseline, "Baseline", color=color.blue)
plot(displayedOtt, "OTT from two bars ago", color=color.purple, linewidth=2)
plot(longStop, "Long stop", display=display.data_window)
plot(shortStop, "Short stop", display=display.data_window)
plot(direction, "Direction: +1 / -1", display=display.data_window)
plot(rawOtt, "Current raw OTT", display=display.data_window)
plotshape(confirmedUp, "Confirmed baseline cross above", shape.triangleup, location.belowbar, color=color.green, size=size.tiny)
plotshape(confirmedDown, "Confirmed baseline cross below", shape.triangledown, location.abovebar, color=color.red, size=size.tiny)
alertcondition(confirmedUp, "Baseline crossed above OTT", "Confirmed baseline cross above displayed OTT.")
alertcondition(confirmedDown, "Baseline crossed below OTT", "Confirmed baseline cross below displayed OTT.")

Differences from the public v4 script are explicit: only VAR and EMA are offered, percent is restricted to 0.1 through 99, early missing OTT values remain na instead of plotting zero, and the line is purple rather than slope-colored. Markers and alert conditions use confirmed baseline crosses. They do not copy every original display option or alert.

The original optional color compares OTT[2] with OTT[3]; it does not read direction. A price crossing OTT, a baseline crossing OTT and an OTT slope change are separate events. This example requires barstate.isconfirmed for markers, so an intrabar baseline cross alone does not produce a confirmed marker. Live baseline values can still move before the close.

Look for a stable parameter region, then test a new period

Treat the following as a research protocol, not recommended trading settings. Freeze the public version, source, session, timeframe and one signal definition before changing inputs. Test VAR and EMA as separate model choices. A change in baseline type changes the experiment.

  1. For a VAR baseline study, compare lengths 2, 3 and 4 against percentages 1.2, 1.4 and 1.6. That gives nine neighboring settings. A finer or wider grid is a new research choice, not proof of a better result.
  2. For each setting, record signal counts and reversal clusters in trending and sideways samples. For a strategy comparison, also freeze entries, exits, position sizing and fill timing; include commission and slippage.
  3. Review neighboring results together. If 2/1.4 looks attractive but 2/1.2, 2/1.6 and 3/1.4 deteriorate sharply, treat it as an isolated result. A region of similar outcomes is less sensitive to small input changes, but can still fail in a different regime.
  4. Choose the acceptance rules before viewing a held-out time period, freeze settings, and evaluate that later period once. Keep the sideways failure sample alongside the trending sample. Do not keep retuning on the held-out period and call it independent validation.

A wider percentage changes both the stop distance and final OTT adjustment. It can postpone a reversal and miss part of a move; it cannot guarantee fewer losing trades. None of these calculations establishes a profitable configuration. This is educational calculation material, not investment advice.

Use Pineify to make the rule inspectable

Give the Pine Script AI Coding Agent the public version and request: "Explain each OTT state transition, retain the nine-bar VAR calculation and OTT[2], expose intermediate values, and confirm baseline crosses at bar close." Review any generated change against the source and test it in TradingView. If you convert the rule into a strategy with numeric inputs, Strategy Optimizer can compare parameter combinations. You still define the strategy, costs and separate test periods.

OTT questions

Sources and related calculations

Verified October 17, 2026. Worked numbers are synthetic calculations from the stated rules. No historical performance result is claimed.

Compare the EMA baseline with KAMA's different adaptive weight, or return to TradingView indicators.