Coral coefficients and the six-stage recurrence
The equations below describe the active calculation in the Coral Trend Indicator [LazyBear] source. Let N be the smoothing period, D the coefficient parameter and x[t] the closing price. Each stage uses the newly calculated value of the preceding stage on the same bar.
s1[t] = alpha × x[t] + beta × s1[t-1]
sk[t] = alpha × s(k-1)[t] + beta × sk[t-1], k = 2…6
w3 = (1 + D)³
w4 = -3D(1 + D)²
w5 = 3D²(1 + D)
w6 = -D³
Coral[t] = w3 × s3[t] + w4 × s4[t] + w5 × s5[t] + w6 × s6[t]
The published intermediate period is (N - 1)/2 + 1, which simplifies to alpha = 4/(N + 3). At N = 21, alpha = 1/6, the coefficient of an 11-period EMA, not a 21-period EMA. At D = 0.4, the weights on stages 3, 4, 5 and 6 are 2.744, -2.352, 0.672 and -0.064. They sum to 1, but negative weights permit overshoot.
D = 0 reduces the output to stage 3. N = 1 gives alpha = 1, so every stage and the final line equal the current source, apart from floating-point rounding. D changes the weights; it is not a volatility measurement. The example constrains D to 0 through 1 as an explicit implementation choice.
Zero initialization and the startup period
The reference uses zero when a previous stage is unavailable. For the first input of 100 at N = 21, the six stages are 100/6, 100/36, 100/216, 100/1296, 100/7776 and 100/46656. Combining them gives 1.09739369. Seeding every stage at the first source instead gives 100 immediately, but changes the initialization contract.
| Observation | Zero fallback | Source seed |
|---|---|---|
| 1 | 1.097394 | 100.000000 |
| 2 | 3.703704 | 100.000000 |
| 3 | 7.824646 | 100.000000 |
| 21 | 97.467163 | 100.000000 |
| 42 | 100.719724 | 100.000000 |
| 63 | 100.027264 | 100.000000 |
| 100 | 99.999893 | 100.000000 |
A numeric output does not mean the filter has settled. The zero-seeded example overshoots 100 and later falls even though every input is 100. Compare results with a longer history and a chosen tolerance, such as a fraction of a tick. Skipping 100 bars in the code is a configurable demonstration setting, not proof that every period, D or market has converged.
Chart history changes can alter the starting state. Match the symbol, timeframe, session, source and history before comparing two versions. This example expects a non-missing closing price; it does not implement a general policy for gaps in an external indicator series.
Price crosses and slope color changes answer different questions
| Event | Exact rule | What it measures |
|---|---|---|
| Price crosses up | x[t] > C[t] and x[t-1] ≤ C[t-1] | Input moves from at/below to above the line |
| Slope turns up | C[t] > C[t-1] and prior slope ≤ 0 | Line starts rising after flat or falling |
| Green line | C[t] > C[t-1] | Rising state, not a new event on every bar |
| Blue line | C[t] = C[t-1] | Exact equality, not a sideways-market detector |
A concrete disagreement: initialize all stages at 100, use N = 5 and D = 0.4, then feed 101, 99 and 100. Coral is 100.216, 100.054 and 99.9505. The third price crosses above Coral, yet Coral is still falling from 100.054. A bullish price-cross marker and a red line are consistent with these rules.
The active reference rule has no near-flat tolerance. A tiny positive difference remains green; display rounding can make two values look equal even when they are not. If you introduce a dead band, define a nonnegative epsilon and classify changes above epsilon, below negative epsilon, and between them. That is a modified signal, not the default Coral color rule.
A sideways sequence can flip colors on every bar
Start all stages at 100 with N = 5 and D = 0.4, then alternate between 101 and 99. Alpha is 0.5. On the first update the stages are 100.5, 100.25, 100.125, 100.0625, 100.03125 and 100.015625. The weighted result is 100.216. Repeating the recurrence gives the table below.
| Range bar | Input | Coral | Slope state |
|---|---|---|---|
| 1 | 101 | 100.216000 | Rising |
| 2 | 99 | 100.054000 | Falling |
| 3 | 101 | 100.166500 | Rising |
| 4 | 99 | 99.979625 | Falling |
| 5 | 101 | 100.104375 | Rising |
| 6 | 99 | 99.938281 | Falling |
| 7 | 101 | 100.080531 | Rising |
| 8 | 99 | 99.926078 | Falling |
Smoothing does not remove this alternating direction. The eight bars contain seven slope-state reversals with no expanding price range. A longer period or additional confirmation changes the response and can delay signals; neither guarantees that losing trades disappear. A trading test also needs exits, position sizing, transaction costs and data outside the tuning sample. This guide is technical education, not investment advice.
Pine Script v6: compare both events on the chart
This educational implementation keeps the public coefficients and default zero fallback. It adds an optional source seed, synthetic inputs and separate markers: S for a slope turn and P for an input cross. Line, ribbon and bar-color modes remain available. It places no orders.
//@version=6
// Educational implementation of the public Coral formula.
// Reference: Coral Trend Indicator [LazyBear], TradingView script qyUwc2Al.
indicator("Coral: slope and price-cross comparison", overlay=true)
period = input.int(21, "Smoothing period", minval=1)
d = input.float(0.4, "Constant D", minval=0, maxval=1, step=0.05)
seedFromPrice = input.bool(false, "Seed stages from first source (changes startup)")
testInput = input.string("Chart close", "Input", options=["Chart close", "Constant 100", "Alternating 101 / 99"])
waitBars = input.int(100, "Bars to skip before signals", minval=0)
colorBars = input.bool(false, "Color bars")
ribbonMode = input.bool(false, "Ribbon mode")
// Alternating test begins at dataset index 100 after 100 flat bars.
x = testInput == "Chart close" ? close : testInput == "Constant 100" ? 100.0 : bar_index < 100 ? 100.0 : bar_index % 2 == 0 ? 101.0 : 99.0
alpha = 4.0 / (period + 3.0)
beta = 1.0 - alpha
fallback = seedFromPrice ? x : 0.0
var float stage1 = na
var float stage2 = na
var float stage3 = na
var float stage4 = na
var float stage5 = na
var float stage6 = na
stage1 := alpha * x + beta * nz(stage1[1], fallback)
stage2 := alpha * stage1 + beta * nz(stage2[1], fallback)
stage3 := alpha * stage2 + beta * nz(stage3[1], fallback)
stage4 := alpha * stage3 + beta * nz(stage4[1], fallback)
stage5 := alpha * stage4 + beta * nz(stage5[1], fallback)
stage6 := alpha * stage5 + beta * nz(stage6[1], fallback)
weight3 = math.pow(1.0 + d, 3)
weight4 = -3.0 * d * math.pow(1.0 + d, 2)
weight5 = 3.0 * d * d * (1.0 + d)
weight6 = -math.pow(d, 3)
coral = weight3 * stage3 + weight4 * stage4 + weight5 * stage5 + weight6 * stage6
slope = coral > nz(coral[1]) ? 1 : coral < nz(coral[1]) ? -1 : 0
lineColor = slope > 0 ? color.green : slope < 0 ? color.red : color.blue
crossUp = ta.crossover(x, coral)
crossDown = ta.crossunder(x, coral)
ready = bar_index >= waitBars and not na(coral[1])
confirmed = ready and barstate.isconfirmed
turnUp = confirmed and slope == 1 and slope[1] != 1
turnDown = confirmed and slope == -1 and slope[1] != -1
priceUp = confirmed and crossUp
priceDown = confirmed and crossDown
plot(ribbonMode ? na : coral, "Coral", color=colorBars ? color.gray : lineColor, linewidth=3)
bgcolor(ribbonMode ? color.new(lineColor, 85) : na)
barcolor(colorBars ? lineColor : na)
plot(x, "Input used", display=display.data_window)
plot(slope, "Slope: rising 1, falling -1, flat 0", display=display.data_window)
plotshape(turnUp, "Slope turns up", shape.triangleup, location.belowbar, color.green, text="S+")
plotshape(turnDown, "Slope turns down", shape.triangledown, location.abovebar, color.red, text="S-")
plotshape(priceUp, "Input crosses above", shape.circle, location.belowbar, color.blue, text="P+")
plotshape(priceDown, "Input crosses below", shape.circle, location.abovebar, color.orange, text="P-")
alertcondition(priceUp and testInput == "Chart close", "Close crosses above Coral", "Confirmed close crossed above Coral.")
alertcondition(priceDown and testInput == "Chart close", "Close crosses below Coral", "Confirmed close crossed below Coral.")
alertcondition(turnUp and testInput == "Chart close", "Coral slope turns up", "Confirmed Coral slope turned up.")
alertcondition(turnDown and testInput == "Chart close", "Coral slope turns down", "Confirmed Coral slope turned down.")- Paste the script into TradingView's Pine Editor, save it and add it to the chart. Compare Coral with the reference using period 21, D = 0.4, zero fallback and the same loaded history.
- For the startup table, select Constant 100. Observation 1 corresponds to bar_index 0. Inspect Coral in the Data Window, then enable the source seed to compare initialization.
- For the range table, set period 5, D = 0.4, enable the source seed and select Alternating 101 / 99. Range bar 1 is dataset index 100. Load at least 108 bars.
- Return to Chart close before creating an alert. Choose the specific price-cross or slope-turn condition and Once Per Bar Close. Synthetic modes disable alert conditions.
Markers and alert conditions require barstate.isconfirmed. The plotted line still updates intrabar. Confirming a chart bar does not make every upstream data source immutable; see TradingView's repainting documentation. Verify chart values before creating alerts, and recreate an alert after changing script inputs that it must use.
Describe the Coral rules to Pineify
Pine Script AI Coding Agent can help draft and edit a script from a written specification. Its syntax-check tool can inspect the code when requested. Give it the formula and test values so that review covers numerical behavior as well as compilation.
Use the public Coral formula with alpha = 4/(N + 3), N = 21, D = 0.4 and zero fallback. Keep slope colors separate from close-cross events. Check that constant input 100 starts at 1.09739369. Add alerts only on confirmed chart bars after a configurable startup interval. Run a syntax check and explain what still needs comparison in TradingView.
Review the output against the public reference and the numeric cases above. A successful syntax check does not prove identical values, profitable signals or access to a protected script.
Open Pine Script AI Coding AgentCoral Trend questions
Sources and related calculations
Formula and active color rule checked against LazyBear's open-source TradingView publication on October 17, 2026. The seed comparisons and synthetic values are calculations defined on this page, not reported market performance. TradingView documents alert execution and saved alert settings.
Read the EMA guide for recursive weighting or ZLEMA guide for another filter that can overshoot. Browse the TradingView indicators hub for the wider collection.