mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-07-29 18:17:43 +00:00
65 lines
2.3 KiB
Plaintext
65 lines
2.3 KiB
Plaintext
// Licensed under the Apache License, Version 2.0
|
|
// © mihakralj
|
|
//@version=6
|
|
indicator("Choppiness Index", "CHOP", overlay=false)
|
|
|
|
//@function Calculates Choppiness Index to measure market trendiness
|
|
//@param length Lookback period for calculation
|
|
//@returns CHOP value between 0 and 100 (lower=trending, higher=choppy)
|
|
//@references E.W. Dreiss, Australian commodity trader
|
|
//@optimized O(n) with circular buffers for TR sum and high/low tracking
|
|
chop(simple int length) =>
|
|
if length <= 1
|
|
runtime.error("Length must be > 1")
|
|
var float sum_tr = 0.0
|
|
var int head = 0
|
|
var int filled = 0
|
|
var array<float> atr_buf = array.new_float(length, na)
|
|
var array<float> high_buf = array.new_float(length, na)
|
|
var array<float> low_buf = array.new_float(length, na)
|
|
float prevClose = nz(close[1], close)
|
|
float tr = math.max(high - low, math.max(math.abs(high - prevClose), math.abs(low - prevClose)))
|
|
float out = array.get(atr_buf, head)
|
|
if not na(out)
|
|
sum_tr -= out
|
|
else
|
|
filled += 1
|
|
array.set(atr_buf, head, tr)
|
|
array.set(high_buf, head, high)
|
|
array.set(low_buf, head, low)
|
|
sum_tr += tr
|
|
int win = math.min(filled, length)
|
|
float hhv = -1e100
|
|
float llv = 1e100
|
|
for k = 0 to win - 1
|
|
int idx = (head - k + length) % length
|
|
float h = array.get(high_buf, idx)
|
|
float l = array.get(low_buf, idx)
|
|
if not na(h)
|
|
hhv := math.max(hhv, h)
|
|
if not na(l)
|
|
llv := math.min(llv, l)
|
|
head := (head + 1) % length
|
|
float price_range = hhv - llv
|
|
float chop_value = na
|
|
if win >= 2 and price_range > 0
|
|
float log_ratio = math.log(sum_tr / price_range) / math.log(10)
|
|
float log_len = math.log(win) / math.log(10)
|
|
chop_value := 100.0 * log_ratio / log_len
|
|
chop_value := math.max(0.0, math.min(100.0, chop_value))
|
|
chop_value
|
|
|
|
// ---------- Main loop ----------
|
|
|
|
// Inputs
|
|
i_length = input.int(14, "Length", minval=2)
|
|
|
|
// Calculation
|
|
chop_value = chop(i_length)
|
|
|
|
// Plot
|
|
plot(chop_value, "CHOP", color=color.yellow, linewidth=2)
|
|
hline(61.8, "High Threshold", color=color.new(color.red, 50), linestyle=hline.style_dashed)
|
|
hline(38.2, "Low Threshold", color=color.new(color.green, 50), linestyle=hline.style_dashed)
|
|
hline(50, "Midline", color=color.new(color.gray, 70), linestyle=hline.style_dotted)
|