Files
QuanTAlib/quantower/lib/jbands.pine
T
Miha Kralj 86fe32a682 SIMD Refactor: Merge simd-dev into dev (#55)
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: aider (openrouter/anthropic/claude-sonnet-4) <aider@aider.chat>
Co-authored-by: Warp <agent@warp.dev>
2026-01-18 19:02:03 -08:00

52 lines
2.2 KiB
Plaintext

// The MIT License (MIT)
// © mihakralj
//@version=6
indicator("Jurik Volatility Bands (JBANDS)", "JBANDS", overlay=true)
//@function Calculates JBANDS using adaptive techniques to adjust width to market volatility
//@param source Series to calculate Jvolty from
//@param period Number of bars used in the calculation
//@returns JBANDS volatility bands
//@optimized Uses adaptive volatility weighting with O(1) complexity per bar
jbands(series float source, simple int period) =>
var simple float LEN1 = math.max((math.log(math.sqrt(0.5 * (period - 1))) / math.log(2.0)) + 2.0, 0.0)
var simple float POW1 = math.max(LEN1 - 2.0, 0.5)
var simple float LEN2 = math.sqrt(0.5 * (period - 1)) * LEN1
var simple float AVG_VOLTY_ALPHA = 2.0 / (math.max(4.0 * period, 65.0) + 1.0)
var simple float DIV = 1.0 / (10.0 + 10.0 * (math.min(math.max(period - 10, 0), 100) / 100.0))
var float upperBand = nz(source)
var float lowerBand = nz(source)
var float vSum = 0.0
var float avgVolty = 0.0
if na(source)
na
else
float del1 = (low + high) * 0.5 - upperBand
float del2 = (low + high) * 0.5 - lowerBand
float volty = math.max(math.abs(del1), math.abs(del2))
float past_volty = na(volty[10]) ? 0.0 : volty[10]
vSum := vSum + (volty - past_volty) * DIV
avgVolty := na(avgVolty) ? vSum : avgVolty + AVG_VOLTY_ALPHA * (vSum - avgVolty)
float rvolty = 1.0
if avgVolty > 0.0
rvolty := volty / avgVolty
rvolty := math.min(math.max(rvolty, 1.0), math.pow(LEN1, 1.0 / POW1))
float Kv = math.pow(LEN2 / (LEN2 + 1.0), math.sqrt(math.pow(rvolty, POW1)))
upperBand := del1 > 0.0 ? high : high - Kv * del1
lowerBand := del2 < 0.0 ? low : low - Kv * del2
[upperBand, lowerBand]
// ---------- Main loop ----------
// Inputs
i_period = input.int(10, "Period", minval=1)
i_source = input.source(close, "Source")
// Calculation
[upperBand, lowerBand] = jbands(i_source, i_period)
// Plot
p1 = plot(upperBand, "Upper", color=color.yellow, linewidth=2)
p2 = plot(lowerBand, "Lower", color=color.yellow, linewidth=2)
fill(p1, p2, color=color.new(color.blue, 90), title="Band Fill")