Ichimoku Oscillator: Four Layers and an Explicit Alignment Score
An Ichimoku oscillator expresses price and cloud relationships as cumulative numeric layers in a separate pane. This page supplies a transparent four-layer reference and a score recalculated on each bar. It is an indicator, not a position manager: full alignment does not establish a profitable entry, and an alignment-loss marker does not execute an exit.
Inspect the Pine ScriptIdentify the variant before comparing results
LonesomeTheBlue’s published Ichimoku Oscillator is an example of an oscillator built from Ichimoku layers and entry/exit logic. The reference here is deliberately a smaller implementation with explicit formulas, warm-up requirements and confirmed markers. It does not claim full equivalence with that script or with every Pineify-generated configuration.
The inputs start at conversion 8, base 13, Span B 26 and displacement 13. These are this example’s choices, not the conventional 9/26/52 Ichimoku set or a proven optimum. There are no ATR-tolerance, bounce-entry, partial-profit or persistent-position features in this reference. The EMA is a displayed average of the final layer.
Start with the cloud references, including the second shift
Conversion and base are high/low range midpoints over their respective windows. Span A averages conversion and base; Span B is the longer range midpoint. With d = displacement − 1, CloudMin = min(SpanA[d], SpanB[d]) and CloudMax = max(SpanA[d], SpanB[d]). The default displacement 13 therefore references spans calculated 12 bars earlier.
The additional lagging term uses CloudMin[d] or CloudMax[d]. Those boundaries already contain a shift, so their underlying spans were calculated 2d bars earlier: 24 bars with the defaults. This is not simply another reference to the same 12-bar-old cloud, and it is not the conventional back-plotted close line.
No plot in this oscillator uses a display offset. All layers are drawn at the current timestamp. The history references affect their calculations. For the distinction between calculation and display, see the Ichimoku Cloud alignment reference.
Build the four cumulative layers
The macro direction is +1 above CloudMax, −1 below CloudMin and 0 inside or exactly on a boundary. In the positive branch, Oscline = close − CloudMin. Lagging adds max(close − older CloudMax, 0). ConvBase then adds max(conversion − base, 0). Cloud adds max(current SpanA − current SpanB, 0).
In the negative or neutral branch, Oscline = close − CloudMax. Lagging adds min(close − older CloudMin, 0), ConvBase adds min(conversion − base, 0), and Cloud adds min(current SpanA − current SpanB, 0). These clipped additions preserve the branch direction. Inside the cloud, the numeric layers can remain negative even though the macro direction and score are zero.
The outputs are cumulative price-unit quantities, not four independent percentages or a bounded −100 to +100 oscillator. The area plots overlap from a zero baseline. Their colors in this reference follow the macro direction, with gray inside the cloud; colors do not separately test every scoring condition.
A worked positive, negative and neutral calculation
These are hypothetical inputs to the formulas. Suppose close is 110, the aligned cloud runs from 100 to 105, and the older cloud’s upper boundary is 104. If conversion is 108, base 106, current Span A 107 and Span B 103, the layers are Oscline 10, Lagging 16, ConvBase 18 and Cloud 22.
The positive score receives one point for price above the cloud, one for the strictly positive lagging addition, one if conversion is at least base and either line rose from its previous value, and one if current Span A is at least Span B. The numerical values above reach +4 only if that separate rising condition also holds. If both conversion and base were unchanged, the score would be +3 despite the same four layer values.
For a negative example, use close 95, cloud 100–105, older lower boundary 98, conversion 99, base 101, current Span A 100 and Span B 102. The layers are −10, −13, −15 and −17. A falling conversion or base, together with the other conditions, produces −4.
For a neutral example, let close be 103 inside cloud 100–105, older lower boundary 99, conversion 104, base 105 and current spans 104 and 106. The layers are −2, −2, −3 and −5, but the score is 0. A negative layer alone therefore does not establish a full bearish alignment.
Score transitions are not a trade ledger
The score is recomputed from present conditions on every bar. It does not accumulate one point each day and does not persist at ±4 until an ATR stop is breached. Above the cloud its possible values are +1 through +4; below, −1 through −4; inside, it is zero. The component tests share price data and are not independent statistical evidence.
The green triangle marks a transition into +4 and the red triangle a transition into −4. An orange cross marks a change away from a previous ±4 score. A direct transition from +4 to −4 can produce both an alignment-loss marker and a new bearish marker on the same bar. This is consistent with score events, not an instruction to assume particular order fills.
Markers require the current bar to be confirmed and both current and previous samples to be ready. The first ready bar does not create a transition marker without a ready predecessor. The plotted layers and score can still develop on an open bar. No alertcondition(), strategy order, position size or profit calculation is present.
Warm-up, scale and the next verification step
The code requires a consecutive valid high/low/close window of max(conversion length, base length, Span B length) + 2d bars. With 8/13/26 and d = 12, that is 50 bars. This covers the oldest shifted range window used in the layer calculation. Missing OHLC observations make the current sample unavailable instead of replacing a missing value with zero.
The EMA begins from available Cloud-layer observations; its startup can depend on available history. Its length changes only that displayed average, not the alignment score. Changing displacement changes two history references and the required window, while changing a range length changes the extrema used. A larger setting does not guarantee fewer losing signals.
For comparison across instruments, remember that 22 means 22 price units in the worked example, not 22 percent or a probability. A normalization would need its own denominator and zero policy. Timeframe changes also change the underlying bars; there is no best interval or measured win rate established here.
Before testing a strategy, reconcile each layer and score on a closed bar, then define entries, exits, fees, slippage and position sizing separately. TradingView’s bar-state documentation explains confirmation timing; it does not guarantee future prices or prevent data revisions.
Pine Script v6: implementation and limits
Paste the full reference into Pine Editor. Calculation inputs are explicit. The five plots show four cumulative layers and their EMA; the Data Window exposes the score. Triangles and crosses mark confirmed alignment events only. The script has no trade execution or profitability model.
// This source code is subject to the terms of the Mozilla Public License 2.0 at https://mozilla.org/MPL/2.0/
// © Pineify
//@version=6
indicator("Ichimoku Oscillator: Layer and Score Reference", overlay=false)
conversionLength = input.int(8, "Conversion length", minval=1, maxval=250)
baseLength = input.int(13, "Base length", minval=1, maxval=250)
spanBLength = input.int(26, "Span B length", minval=1, maxval=250)
displacement = input.int(13, "Displacement convention", minval=2, maxval=100)
emaLength = input.int(9, "Layer EMA length", minval=1, maxval=250)
midpoint(simple int length) =>
math.avg(ta.highest(high, length), ta.lowest(low, length))
conversion = midpoint(conversionLength)
base = midpoint(baseLength)
spanA = math.avg(conversion, base)
spanB = midpoint(spanBLength)
shift = displacement - 1
cloudMin = math.min(spanA[shift], spanB[shift])
cloudMax = math.max(spanA[shift], spanB[shift])
olderMin = cloudMin[shift]
olderMax = cloudMax[shift]
neededBars = math.max(conversionLength, math.max(baseLength, spanBLength)) + 2 * shift
valid = not na(high) and not na(low) and not na(close)
ready = math.sum(valid ? 1.0 : 0.0, neededBars) == neededBars
macro = ready ? (close > cloudMax ? 1 : close < cloudMin ? -1 : 0) : 0
inside = ready and close >= cloudMin and close <= cloudMax
osc = ready ? (macro == 1 ? close - cloudMin : close - cloudMax) : na
lagging = osc + (macro == 1 ? math.max(close - olderMax, 0) : math.min(close - olderMin, 0))
convBase = lagging + (macro == 1 ? math.max(conversion - base, 0) : math.min(conversion - base, 0))
layerCloud = convBase + (macro == 1 ? math.max(spanA - spanB, 0) : math.min(spanA - spanB, 0))
rising = conversion > conversion[1] or base > base[1]
falling = conversion < conversion[1] or base < base[1]
int score = 0
if macro == 1
score := 1 + (lagging > osc ? 1 : 0) + (conversion >= base and rising ? 1 : 0) + (spanA >= spanB ? 1 : 0)
else if macro == -1
score := -1 - (lagging < osc ? 1 : 0) - (conversion <= base and falling ? 1 : 0) - (spanA <= spanB ? 1 : 0)
layerEma = ta.ema(layerCloud, emaLength)
confirmedEvent = ready and ready[1] and barstate.isconfirmed
bullAlignment = confirmedEvent and score == 4 and score[1] != 4
bearAlignment = confirmedEvent and score == -4 and score[1] != -4
alignmentLost = confirmedEvent and math.abs(score[1]) == 4 and score != score[1]
layerColor = macro == 1 ? color.green : macro == -1 ? color.red : color.gray
plot(layerCloud, "Cloud cumulative layer", color=color.new(layerColor, 70), style=plot.style_area)
plot(convBase, "ConvBase cumulative layer", color=color.new(layerColor, 55), style=plot.style_area)
plot(lagging, "Lagging cumulative layer", color=color.new(layerColor, 40), style=plot.style_area)
plot(osc, "Price/cloud layer", color=inside ? color.gray : layerColor, style=plot.style_area)
plot(layerEma, "EMA of Cloud layer", color=color.purple)
plot(ready ? score : na, "Alignment score", display=display.data_window)
hline(0, "Zero", color=color.gray)
plotshape(bullAlignment ? 0 : na, "New +4 alignment", shape.triangleup, location.absolute, color.green, size=size.small)
plotshape(bearAlignment ? 0 : na, "New -4 alignment", shape.triangledown, location.absolute, color.red, size=size.small)
plotshape(alignmentLost ? layerCloud : na, "Prior full alignment lost", shape.xcross, location.absolute, color.orange, size=size.small)

Specify a checkable adaptation in Pineify
Specify the four layer formulas, both history shifts, whether the score is stateless or persistent, and what each marker means. Request actual position tracking separately if you need trade management. Inspect inputs, readiness and confirmation behavior, run syntax validation and compare a closed-bar numerical example before evaluating any strategy.
Open Pine Script AI Coding AgentEducational indicator analysis. No measured trading performance is established here. Syntax validation does not prove formula equivalence, execution assumptions or profitability.