Paste the complete indicator into TradingView Pine Editor. Leave the fixture enabled for the table above: it occupies the first 16 loaded bars, and the on-chart table retains those rows even when they are offscreen. At least 16 loaded bars are needed. Change the fixture selector for the controls, or turn the fixture off for chart OHLC. The default is a calculation demonstration, not an order-generating strategy.
Complete Pine v6 indicator. Syntax checked on 2026-10-18. Explicit window and gap policies make the fixture reproducible; syntax checking does not verify market performance.pine
//@version=6
indicator("Stochastic vs Stoch RSI controlled comparison", overlay=false, max_bars_back=1000)
fixture = input.bool(true, "Use the 16-bar fixture")
variant = input.string("Base", "Fixture variant", options=["Base", "Wider wicks", "Flat", "Missing close", "Rising closes"])
priceLen = input.int(3, "Price range length", minval=1, maxval=100)
rsiLen = input.int(3, "RSI length", minval=1, maxval=100)
rsiRangeLen = input.int(3, "RSI range length", minval=1, maxval=100)
kLen = input.int(1, "K SMA length (both)", minval=1, maxval=100)
dLen = input.int(3, "D SMA length (both)", minval=1, maxval=100)
// Every observation in the window must exist. No partial windows.
fullRange(float src, float hi, float lo, int n) =>
float top = na
float bottom = na
bool valid = true
for j = 0 to n - 1
valid := valid and not na(src[j]) and not na(hi[j]) and not na(lo[j])
valid := valid and hi[j] >= src[j] and src[j] >= lo[j]
top := na(top) ? hi[j] : math.max(top, hi[j])
bottom := na(bottom) ? lo[j] : math.min(bottom, lo[j])
valid and top > bottom ? 100 * (src - bottom) / (top - bottom) : na
fullSma(float src, int n) =>
float total = 0.0
bool valid = true
for j = 0 to n - 1
valid := valid and not na(src[j])
total += src[j]
valid ? total / n : na
// Seed with n consecutive changes. A missing change restarts the seed.
strictRsi(float src, int n) =>
float delta = src - src[1]
var float gains = 0.0
var float losses = 0.0
var int count = 0
if na(delta)
gains := 0.0
losses := 0.0
count := 0
else if count < n
gains += math.max(delta, 0)
losses += math.max(-delta, 0)
count += 1
if count == n
gains /= n
losses /= n
else
gains := ((n - 1) * gains + math.max(delta, 0)) / n
losses := ((n - 1) * losses + math.max(-delta, 0)) / n
count == n and gains + losses > 0 ? (losses == 0 ? 100.0 : gains == 0 ? 0.0 : 100 * gains / (gains + losses)) : na
var values = array.from(100.0, 99.0, 100.0, 99.0, 100.0, 100.2, 100.4, 100.3, 100.5, 100.6, 100.4, 100.7, 100.6, 100.8, 100.7, 101.0)
float fixtureClose = bar_index < array.size(values) ? array.get(values, bar_index) : na
if variant == "Flat"
fixtureClose := bar_index < 16 ? 100.0 : na
if variant == "Rising closes"
fixtureClose := bar_index < 16 ? 100.0 + bar_index * 0.1 : na
if variant == "Missing close" and bar_index == 6
fixtureClose := na
float c = fixture ? fixtureClose : close
float h = fixture ? (variant == "Flat" ? 100.0 : variant == "Wider wicks" ? 120.0 : 110.0) : high
float l = fixture ? (variant == "Flat" ? 100.0 : variant == "Wider wicks" ? 80.0 : 90.0) : low
float r = strictRsi(c, rsiLen)
float priceRaw = fullRange(c, h, l, priceLen)
float rsiRaw = fullRange(r, r, r, rsiRangeLen)
float priceK = fullSma(priceRaw, kLen)
float rsiK = fullSma(rsiRaw, kLen)
float priceD = fullSma(priceK, dLen)
float rsiD = fullSma(rsiK, dLen)
bool ready = not na(priceK) and not na(rsiK)
bool pair = ready and ready[1] and barstate.isconfirmed
bool priceUpperEntry = pair and priceK > 80 and priceK[1] <= 80
bool rsiUpperEntry = pair and rsiK > 80 and rsiK[1] <= 80
plot(barstate.isconfirmed ? priceK : na, "Price K", color=color.blue)
plot(barstate.isconfirmed ? rsiK : na, "Stoch RSI K", color=color.orange)
plot(barstate.isconfirmed ? priceD : na, "Price D", color=color.new(color.blue, 60))
plot(barstate.isconfirmed ? rsiD : na, "Stoch RSI D", color=color.new(color.orange, 60))
plot(r, "Underlying RSI", display=display.data_window)
plot(c, "Source close", display=display.data_window)
plot(bar_index, "Fixture bar index", display=display.data_window)
plot(priceUpperEntry ? 1 : 0, "Price upper entry", display=display.data_window)
plot(rsiUpperEntry ? 1 : 0, "RSI range upper entry", display=display.data_window)
hline(80, "Upper")
hline(20, "Lower")
f(float x) =>
na(x) ? "na" : str.tostring(x, "#.####")
var table results = table.new(position.top_right, 7, 17, border_width=1)
if barstate.isfirst and fixture
table.cell(results, 0, 0, "Bar")
table.cell(results, 1, 0, "Close")
table.cell(results, 2, 0, "RSI")
table.cell(results, 3, 0, "Price K")
table.cell(results, 4, 0, "RSI K")
table.cell(results, 5, 0, "Price D")
table.cell(results, 6, 0, "RSI D")
if fixture and bar_index < 16 and barstate.isconfirmed
table.cell(results, 0, bar_index + 1, str.tostring(bar_index))
table.cell(results, 1, bar_index + 1, f(c))
table.cell(results, 2, bar_index + 1, f(r))
table.cell(results, 3, bar_index + 1, f(priceK))
table.cell(results, 4, bar_index + 1, f(rsiK))
table.cell(results, 5, bar_index + 1, f(priceD))
table.cell(results, 6, bar_index + 1, f(rsiD))