Skip to content

Commit

Permalink
Refactor Squeeze Momentum indicator
Browse files Browse the repository at this point in the history
- Make the Bollinger Bands and Keltner Channels indicators public.
- In IndicatorBase -> Update, if T is IndicatorDataPoint, then create a new
  IndicatorDataPoint.
  • Loading branch information
JosueNina committed Dec 20, 2024
1 parent 7772ccc commit 7597d3c
Show file tree
Hide file tree
Showing 2 changed files with 18 additions and 14 deletions.
6 changes: 5 additions & 1 deletion Indicators/IndicatorBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ public abstract class IndicatorBase<T> : IndicatorBase
/// <param name="name">The name of this indicator</param>
protected IndicatorBase(string name)
: base(name)
{}
{ }

/// <summary>
/// Updates the state of this indicator with the given value and returns true
Expand All @@ -253,6 +253,10 @@ protected IndicatorBase(string name)
/// <returns>True if this indicator is ready, false otherwise</returns>
public override bool Update(IBaseData input)
{
if (typeof(T) == typeof(IndicatorDataPoint))
{
input = new IndicatorDataPoint(input.EndTime, input.Value);
}
T _previousSymbolInput = default(T);
if (_previousInput.TryGetValue(input.Symbol.ID, out _previousSymbolInput) && input.EndTime < _previousSymbolInput.EndTime)
{
Expand Down
26 changes: 13 additions & 13 deletions Indicators/SqueezeMomentum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,12 +28,12 @@ public class SqueezeMomentum : BarIndicator, IIndicatorWarmUpPeriodProvider
/// <summary>
/// The Bollinger Bands indicator used to calculate the upper, lower, and middle bands.
/// </summary>
private readonly BollingerBands _bollingerBands;
public BollingerBands BollingerBands { get; }

/// <summary>
/// The Keltner Channels indicator used to calculate the upper, lower, and middle channels.
/// </summary>
private readonly KeltnerChannels _keltnerChannels;
public KeltnerChannels KeltnerChannels { get; }

/// <summary>
/// Initializes a new instance of the <see cref="SqueezeMomentum"/> class.
Expand All @@ -45,8 +45,8 @@ public class SqueezeMomentum : BarIndicator, IIndicatorWarmUpPeriodProvider
/// <param name="keltnerMultiplier">The multiplier applied to the ATR for calculating Keltner Channels.</param>
public SqueezeMomentum(string name, int bollingerPeriod, decimal bollingerMultiplier, int keltnerPeriod, decimal keltnerMultiplier) : base(name)
{
_bollingerBands = new BollingerBands(bollingerPeriod, bollingerMultiplier);
_keltnerChannels = new KeltnerChannels(keltnerPeriod, keltnerMultiplier, MovingAverageType.Exponential);
BollingerBands = new BollingerBands(bollingerPeriod, bollingerMultiplier);
KeltnerChannels = new KeltnerChannels(keltnerPeriod, keltnerMultiplier, MovingAverageType.Exponential);
WarmUpPeriod = Math.Max(bollingerPeriod, keltnerPeriod);
}

Expand All @@ -60,7 +60,7 @@ public SqueezeMomentum(string name, int bollingerPeriod, decimal bollingerMultip
/// Indicates whether the indicator is ready and has enough data for computation.
/// The indicator is ready when both the Bollinger Bands and the Average True Range are ready.
/// </summary>
public override bool IsReady => _bollingerBands.IsReady && _keltnerChannels.IsReady;
public override bool IsReady => BollingerBands.IsReady && KeltnerChannels.IsReady;

/// <summary>
/// Computes the next value of the indicator based on the input data bar.
Expand All @@ -72,20 +72,20 @@ public SqueezeMomentum(string name, int bollingerPeriod, decimal bollingerMultip
/// </returns>
protected override decimal ComputeNextValue(IBaseDataBar input)
{
_bollingerBands.Update(new IndicatorDataPoint(input.EndTime, input.Close));
_keltnerChannels.Update(input);
BollingerBands.Update(input);
KeltnerChannels.Update(input);
if (!IsReady)
{
return decimal.Zero;
}

// Calculate Bollinger Bands upper, lower
var bbUpper = _bollingerBands.UpperBand.Current.Value;
var bbLower = _bollingerBands.LowerBand.Current.Value;
var bbUpper = BollingerBands.UpperBand.Current.Value;
var bbLower = BollingerBands.LowerBand.Current.Value;

// Calculate Keltner Channels upper and lower bounds
var kcUpper = _keltnerChannels.UpperBand.Current.Value;
var kcLower = _keltnerChannels.LowerBand.Current.Value;
var kcUpper = KeltnerChannels.UpperBand.Current.Value;
var kcLower = KeltnerChannels.LowerBand.Current.Value;

// Determine if the squeeze condition is on or off
return (kcUpper > bbUpper && kcLower < bbLower) ? 1m : -1m;
Expand All @@ -96,8 +96,8 @@ protected override decimal ComputeNextValue(IBaseDataBar input)
/// </summary>
public override void Reset()
{
_bollingerBands.Reset();
_keltnerChannels.Reset();
BollingerBands.Reset();
KeltnerChannels.Reset();
base.Reset();
}
}
Expand Down

0 comments on commit 7597d3c

Please sign in to comment.