Files
QuanTAlib/lib/channels/mmchannel/mmchannel.pine
T

50 lines
2.0 KiB
Plaintext

// Licensed under the Apache License, Version 2.0
// © mihakralj
//@version=6
indicator("Min-Max Channel (MMCHANNEL)", "MMCHANNEL", overlay=true)
//@function Calculates the Min-Max Channel efficiently using monotonic deques
//@param hi Source series for the highest high calculation (usually high)
//@param lo Source series for the lowest low calculation (usually low)
//@param period Lookback period (period > 0)
//@returns Tuple containing [highest_high, lowest_low]
//@optimized Uses monotonic deque for O(1) amortized complexity per bar
mmchannel(series float hi, series float lo, simple int period) =>
if period <= 0
runtime.error("Period must be > 0")
var float[] hbuf = array.new_float(period, na)
var float[] lbuf = array.new_float(period, na)
var int[] hq = array.new_int()
var int[] lq = array.new_int()
int idx = bar_index % period
array.set(hbuf, idx, hi)
array.set(lbuf, idx, lo)
while array.size(hq) > 0 and array.get(hq, 0) <= bar_index - period
array.shift(hq)
while array.size(hq) > 0 and array.get(hbuf, array.get(hq, -1) % period) <= hi
array.pop(hq)
array.push(hq, bar_index)
while array.size(lq) > 0 and array.get(lq, 0) <= bar_index - period
array.shift(lq)
while array.size(lq) > 0 and array.get(lbuf, array.get(lq, -1) % period) >= lo
array.pop(lq)
array.push(lq, bar_index)
float highest = array.get(hbuf, array.get(hq, 0) % period)
float lowest = array.get(lbuf, array.get(lq, 0) % period)
[highest, lowest]
// ---------- Main loop ----------
// Inputs
i_period = input.int(20, "Period", minval=1)
i_high = input.source(high, "High Source")
i_low = input.source(low, "Low Source")
// Calculation
[highest, lowest] = mmchannel(i_high, i_low, i_period)
// Plot
p1 = plot(highest, "Highest High", color=color.yellow, linewidth=2)
p2 = plot(lowest, "Lowest Low", color=color.yellow, linewidth=2)
fill(p1, p2, color=color.new(color.blue, 90), title="Band Fill")