Remove multiple Pine Script indicators: SSFDSP, STARCHANNEL, STBANDS, STC, UBANDS, UCHANNEL, VWAPBANDS, and VWAPSD. These indicators were deleted to streamline the library and remove unused or redundant code.

This commit is contained in:
Miha Kralj
2026-02-20 18:44:56 -08:00
parent 3dd05f23e4
commit cbeefc9d64
283 changed files with 23963 additions and 3838 deletions
@@ -14,9 +14,12 @@ namespace QuanTAlib;
/// </summary>
public sealed class StarchannelIndicator : Indicator, IWatchlistIndicator
{
[InputParameter("Period", sortIndex: 10, minimum: 1, maximum: 500, increment: 1, decimalPlaces: 0)]
[InputParameter("SMA Period", sortIndex: 10, minimum: 1, maximum: 500, increment: 1, decimalPlaces: 0)]
public int Period { get; set; } = 20;
[InputParameter("ATR Period (0 = same as SMA)", sortIndex: 15, minimum: 0, maximum: 500, increment: 1, decimalPlaces: 0)]
public int AtrPeriod { get; set; } = 0;
[InputParameter("Multiplier", sortIndex: 20, minimum: 0.1, maximum: 10.0, increment: 0.1, decimalPlaces: 1)]
public double Multiplier { get; set; } = 2.0;
@@ -25,8 +28,10 @@ public sealed class StarchannelIndicator : Indicator, IWatchlistIndicator
private Starchannel? _indicator;
public int MinHistoryDepths => Period;
public override string ShortName => $"Starchannel({Period},{Multiplier})";
public int MinHistoryDepths => Math.Max(Period, AtrPeriod > 0 ? AtrPeriod : Period);
public override string ShortName => AtrPeriod > 0 && AtrPeriod != Period
? $"Starchannel({Period},{Multiplier},{AtrPeriod})"
: $"Starchannel({Period},{Multiplier})";
public StarchannelIndicator()
{
@@ -38,7 +43,7 @@ public sealed class StarchannelIndicator : Indicator, IWatchlistIndicator
protected override void OnInit()
{
_indicator = new Starchannel(Period, Multiplier);
_indicator = new Starchannel(Period, Multiplier, AtrPeriod);
AddLineSeries(new LineSeries("Middle", Color.DodgerBlue, 2, LineStyle.Solid));
AddLineSeries(new LineSeries("Upper", Color.FromArgb(255, 180, 180), 1, LineStyle.Dash));
+34 -18
View File
@@ -7,14 +7,16 @@ namespace QuanTAlib;
/// STARCHANNEL: Stoller Average Range Channel
/// A volatility-based envelope using SMA as the middle line and ATR for band width.
/// Middle = SMA(source, period)
/// Upper = Middle + (multiplier × ATR)
/// Lower = Middle - (multiplier × ATR)
/// Upper = Middle + (multiplier × ATR(atrPeriod))
/// Lower = Middle - (multiplier × ATR(atrPeriod))
/// ATR uses RMA (Wilder's smoothing) with warmup compensation.
/// Supports separate SMA and ATR periods for traditional Stoller dual-period design.
/// </summary>
[SkipLocalsInit]
public sealed class Starchannel : ITValuePublisher
{
private readonly int _period;
private readonly int _atrPeriod;
private readonly double _multiplier;
private readonly double _atrAlpha;
private readonly RingBuffer _smaBuffer;
@@ -46,7 +48,7 @@ public sealed class Starchannel : ITValuePublisher
public event TValuePublishedHandler? Pub;
public Starchannel(int period = 20, double multiplier = 2.0)
public Starchannel(int period = 20, double multiplier = 2.0, int atrPeriod = 0)
{
if (period < 1)
{
@@ -58,20 +60,30 @@ public sealed class Starchannel : ITValuePublisher
throw new ArgumentOutOfRangeException(nameof(multiplier), "Multiplier must be > 0.");
}
// Default atrPeriod to period when 0 (backward compatible)
int effectiveAtrPeriod = atrPeriod > 0 ? atrPeriod : period;
if (effectiveAtrPeriod < 1)
{
throw new ArgumentOutOfRangeException(nameof(atrPeriod), "ATR period must be >= 1.");
}
_period = period;
_atrPeriod = effectiveAtrPeriod;
_multiplier = multiplier;
_atrAlpha = 1.0 / period;
_atrAlpha = 1.0 / effectiveAtrPeriod;
_smaBuffer = new RingBuffer(period);
WarmupPeriod = period;
WarmupPeriod = Math.Max(period, effectiveAtrPeriod);
Name = $"Starchannel({period},{multiplier})";
Name = effectiveAtrPeriod == period
? $"Starchannel({period},{multiplier})"
: $"Starchannel({period},{multiplier},{effectiveAtrPeriod})";
_barHandler = HandleBar;
Reset();
}
public Starchannel(TBarSeries source, int period = 20, double multiplier = 2.0) : this(period, multiplier)
public Starchannel(TBarSeries source, int period = 20, double multiplier = 2.0, int atrPeriod = 0) : this(period, multiplier, atrPeriod)
{
Prime(source);
source.Pub += _barHandler;
@@ -179,8 +191,8 @@ public sealed class Starchannel : ITValuePublisher
double tr3 = Math.Abs(low - prevClose);
double trueRange = Math.Max(tr1, Math.Max(tr2, tr3));
// ATR using RMA with warmup compensation
double newRawRma = (_state.RawRma * (_period - 1) + trueRange) / _period;
// ATR using RMA with warmup compensation (uses _atrPeriod for separate ATR smoothing)
double newRawRma = (_state.RawRma * (_atrPeriod - 1) + trueRange) / _atrPeriod;
double newE = (1.0 - _atrAlpha) * _state.E;
double atrValue = newE > Epsilon ? newRawRma / (1.0 - newE) : newRawRma;
@@ -238,7 +250,7 @@ public sealed class Starchannel : ITValuePublisher
var vLowerSpan = CollectionsMarshal.AsSpan(vLower);
Batch(source.HighValues, source.LowValues, source.CloseValues,
vMiddleSpan, vUpperSpan, vLowerSpan, _period, _multiplier);
vMiddleSpan, vUpperSpan, vLowerSpan, _period, _multiplier, _atrPeriod);
source.Times.CopyTo(tSpan);
tSpan.CopyTo(CollectionsMarshal.AsSpan(tUpper));
@@ -281,7 +293,8 @@ public sealed class Starchannel : ITValuePublisher
Span<double> upper,
Span<double> lower,
int period,
double multiplier = 2.0)
double multiplier = 2.0,
int atrPeriod = 0)
{
if (period < 1)
{
@@ -293,6 +306,9 @@ public sealed class Starchannel : ITValuePublisher
throw new ArgumentOutOfRangeException(nameof(multiplier), "Multiplier must be > 0.");
}
// Default atrPeriod to period when 0 (backward compatible)
int effectiveAtrPeriod = atrPeriod > 0 ? atrPeriod : period;
if (high.Length != low.Length || high.Length != close.Length)
{
throw new ArgumentException("High, Low, and Close spans must have the same length", nameof(high));
@@ -309,7 +325,7 @@ public sealed class Starchannel : ITValuePublisher
return;
}
double atrAlpha = 1.0 / period;
double atrAlpha = 1.0 / effectiveAtrPeriod;
// First bar - sanitize first values
double lastValidClose = double.IsFinite(close[0]) ? close[0] : 0;
@@ -389,8 +405,8 @@ public sealed class Starchannel : ITValuePublisher
double tr3 = Math.Abs(l - prevClose);
double tr = Math.Max(tr1, Math.Max(tr2, tr3));
// ATR (RMA with warmup compensation)
rawRma = (rawRma * (period - 1) + tr) / period;
// ATR (RMA with warmup compensation, uses effectiveAtrPeriod)
rawRma = (rawRma * (effectiveAtrPeriod - 1) + tr) / effectiveAtrPeriod;
e = (1.0 - atrAlpha) * e;
double atr = e > Epsilon ? rawRma / (1.0 - e) : rawRma;
@@ -403,7 +419,7 @@ public sealed class Starchannel : ITValuePublisher
}
}
public static (TSeries Middle, TSeries Upper, TSeries Lower) Batch(TBarSeries source, int period = 20, double multiplier = 2.0)
public static (TSeries Middle, TSeries Upper, TSeries Lower) Batch(TBarSeries source, int period = 20, double multiplier = 2.0, int atrPeriod = 0)
{
int len = source.Count;
var tMiddle = new List<long>(len);
@@ -424,7 +440,7 @@ public sealed class Starchannel : ITValuePublisher
CollectionsMarshal.AsSpan(vMiddle),
CollectionsMarshal.AsSpan(vUpper),
CollectionsMarshal.AsSpan(vLower),
period, multiplier);
period, multiplier, atrPeriod);
source.Times.CopyTo(CollectionsMarshal.AsSpan(tMiddle));
CollectionsMarshal.AsSpan(tMiddle).CopyTo(CollectionsMarshal.AsSpan(tUpper));
@@ -433,9 +449,9 @@ public sealed class Starchannel : ITValuePublisher
return (new TSeries(tMiddle, vMiddle), new TSeries(tUpper, vUpper), new TSeries(tLower, vLower));
}
public static ((TSeries Middle, TSeries Upper, TSeries Lower) Results, Starchannel Indicator) Calculate(TBarSeries source, int period = 20, double multiplier = 2.0)
public static ((TSeries Middle, TSeries Upper, TSeries Lower) Results, Starchannel Indicator) Calculate(TBarSeries source, int period = 20, double multiplier = 2.0, int atrPeriod = 0)
{
var indicator = new Starchannel(source, period, multiplier);
var indicator = new Starchannel(source, period, multiplier, atrPeriod);
var results = indicator.Update(source);
return (results, indicator);
}
+9 -6
View File
@@ -5,13 +5,15 @@ indicator("Stoller Average Range Channel (STARCHANNEL)", "STARCHANNEL", overlay=
//@function Calculates Stoller Average Range Channel using ATR for width and SMA for center
//@param source Source series for the center line
//@param length Period for ATR and SMA calculations
//@param length Period for SMA calculation
//@param multiplier ATR multiplier for band width
//@param atr_length Period for ATR calculation (0 = same as length)
//@returns tuple with [middle, upper, lower] band values
//@optimized Uses circular buffer for SMA and ATR with compensator, O(1) complexity
starchannel(series float source, simple int length, simple float multiplier) =>
starchannel(series float source, simple int length, simple float multiplier, simple int atr_length = 0) =>
if length <= 0 or multiplier <= 0.0
runtime.error("Length and multiplier must be greater than 0")
int effective_atr_length = atr_length > 0 ? atr_length : length
var float prevClose = close
float tr1 = high - low
float tr2 = math.abs(high - prevClose)
@@ -44,8 +46,8 @@ starchannel(series float source, simple int length, simple float multiplier) =>
var float e = 1.0
float atrValue = na
if not na(trueRange)
float alpha = 1.0 / float(length)
raw_rma := (raw_rma * (length - 1) + trueRange) / length
float alpha = 1.0 / float(effective_atr_length)
raw_rma := (raw_rma * (effective_atr_length - 1) + trueRange) / effective_atr_length
e := (1.0 - alpha) * e
atrValue := e > EPSILON ? raw_rma / (1.0 - e) : raw_rma
float middleBand = nz(sumSource / count, source)
@@ -56,11 +58,12 @@ starchannel(series float source, simple int length, simple float multiplier) =>
// Inputs
i_source = input.source(close, "Source")
i_length = input.int(20, "Length", minval=1)
i_length = input.int(20, "SMA Length", minval=1)
i_atr_length = input.int(0, "ATR Length (0 = same as SMA)", minval=0)
i_mult = input.float(2.0, "ATR Multiplier", minval=0.001)
// Calculation
[middle, upper, lower] = starchannel(i_source, i_length, i_mult)
[middle, upper, lower] = starchannel(i_source, i_length, i_mult, i_atr_length)
// Plot
plot(middle, "Middle", color=color.yellow, linewidth=2)