Files

78 lines
2.3 KiB
Plaintext

// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Jurik Composite Fractal Behavior", "CFB", overlay=false)
//@function Calculates Jurik Composite Fractal Behavior (Trend Duration Index)
//@param source Series to calculate CFB from
//@param maxLength Maximum lookback length (default 192, lengths 2,4,6,...,maxLength used)
//@returns CFB value - weighted average of efficient trend lengths, minimum 1
cfb(series float source, simple int maxLength = 192) =>
// Generate lengths array: 2, 4, 6, ..., maxLength
int numLengths = int(maxLength / 2)
// Persistent state
var float prevCfb = 1.0
var array<float> runningSums = array.new_float(numLengths, 0.0)
float currentVol = bar_index == 0 ? 0.0 : math.abs(source - source[1])
float sumWeightedLen = 0.0
float sumWeights = 0.0
// Update running sums and calculate ratios for each length
for i = 0 to numLengths - 1
int L = (i + 1) * 2
// Update running sum of volatility
float oldSum = array.get(runningSums, i)
float volToRemove = bar_index > L ? math.abs(source[L] - source[L + 1]) : 0.0
float newSum = oldSum + currentVol - volToRemove
array.set(runningSums, i, newSum)
// Skip if not enough bars
if bar_index < L
continue
// Skip if very small volatility
if newSum < 1e-12
continue
// Net move over L bars
float netMove = math.abs(source - source[L])
float ratio = netMove / newSum
if ratio >= 0.25
sumWeightedLen += float(L) * ratio
sumWeights += ratio
// Calculate CFB
float cfbVal = 1.0
if sumWeights > 0.25
cfbVal := sumWeightedLen / sumWeights
else
cfbVal := prevCfb > 1.0 ? prevCfb * 0.5 : 1.0
if cfbVal < 1.0
cfbVal := 1.0
cfbVal := math.round(cfbVal)
if cfbVal < 1.0
cfbVal := 1.0
prevCfb := cfbVal
cfbVal
// ---------- Main loop ----------
// Inputs
i_maxLength = input.int(192, "Max Length", minval=4, step=2, tooltip="Maximum lookback length. Lengths 2,4,6,...,maxLength are used")
i_source = input.source(close, "Source")
// Calculation
cfb_value = cfb(i_source, i_maxLength)
// Plot
plot(cfb_value, "CFB", color=color.yellow, linewidth=2)
hline(1, "Min", color=color.gray, linestyle=hline.style_dotted)