mirror of
https://github.com/mihakralj/QuanTAlib.git
synced 2026-08-25 22:08:05 +00:00
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:
@@ -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));
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user