Skip to content

Commit

Permalink
Switched to using Keltner indicator instead of manual calculation
Browse files Browse the repository at this point in the history
  • Loading branch information
JosueNina committed Dec 19, 2024
1 parent 7501578 commit 7772ccc
Show file tree
Hide file tree
Showing 3 changed files with 997 additions and 515 deletions.
4 changes: 2 additions & 2 deletions Indicators/KeltnerChannels.cs
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ public KeltnerChannels(string name, int period, decimal k, MovingAverageType mov
WarmUpPeriod = period;

//Initialise ATR and SMA
AverageTrueRange = new AverageTrueRange(name + "_AverageTrueRange", period, movingAverageType);
AverageTrueRange = new AverageTrueRange(name + "_AverageTrueRange", period, MovingAverageType.Simple);
MiddleBand = movingAverageType.AsIndicator(name + "_MiddleBand", period);

//Compute Lower Band
Expand Down Expand Up @@ -117,7 +117,7 @@ protected override decimal ComputeNextValue(IBaseDataBar input)
{
AverageTrueRange.Update(input);

var typicalPrice = (input.High + input.Low + input.Close)/3m;
var typicalPrice = (input.High + input.Low + input.Close) / 3m;
MiddleBand.Update(input.EndTime, typicalPrice);

// poke the upper/lower bands, they actually don't use the input, they compute
Expand Down
31 changes: 12 additions & 19 deletions Indicators/SqueezeMomentum.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,9 @@ public class SqueezeMomentum : BarIndicator, IIndicatorWarmUpPeriodProvider
private readonly BollingerBands _bollingerBands;

/// <summary>
/// The Average True Range (ATR) indicator used to calculate the Keltner Channels.
/// The Keltner Channels indicator used to calculate the upper, lower, and middle channels.
/// </summary>
private readonly AverageTrueRange _averageTrueRange;

/// <summary>
/// The multiplier applied to the Average True Range for calculating Keltner Channels.
/// </summary>
private readonly decimal _keltnerMultiplier;
private readonly KeltnerChannels _keltnerChannels;

/// <summary>
/// Initializes a new instance of the <see cref="SqueezeMomentum"/> class.
Expand All @@ -51,8 +46,7 @@ public class SqueezeMomentum : BarIndicator, IIndicatorWarmUpPeriodProvider
public SqueezeMomentum(string name, int bollingerPeriod, decimal bollingerMultiplier, int keltnerPeriod, decimal keltnerMultiplier) : base(name)
{
_bollingerBands = new BollingerBands(bollingerPeriod, bollingerMultiplier);
_averageTrueRange = new AverageTrueRange(keltnerPeriod, MovingAverageType.Simple);
_keltnerMultiplier = keltnerMultiplier;
_keltnerChannels = new KeltnerChannels(keltnerPeriod, keltnerMultiplier, MovingAverageType.Exponential);
WarmUpPeriod = Math.Max(bollingerPeriod, keltnerPeriod);
}

Expand All @@ -66,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 && _averageTrueRange.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 @@ -79,23 +73,22 @@ public SqueezeMomentum(string name, int bollingerPeriod, decimal bollingerMultip
protected override decimal ComputeNextValue(IBaseDataBar input)
{
_bollingerBands.Update(new IndicatorDataPoint(input.EndTime, input.Close));
_averageTrueRange.Update(input);
_keltnerChannels.Update(input);
if (!IsReady)
{
return decimal.Zero;
}

// Calculate Bollinger Bands upper, lower, and middle bands
var bbHigh = _bollingerBands.UpperBand.Current.Value;
var bbLow = _bollingerBands.LowerBand.Current.Value;
var simpleMovingAverage = _bollingerBands.MiddleBand.Current.Value;
// Calculate Bollinger Bands upper, lower
var bbUpper = _bollingerBands.UpperBand.Current.Value;
var bbLower = _bollingerBands.LowerBand.Current.Value;

// Calculate Keltner Channels upper and lower bounds
var kcLow = simpleMovingAverage - _keltnerMultiplier * _averageTrueRange.Current.Value;
var kcHigh = simpleMovingAverage + _keltnerMultiplier * _averageTrueRange.Current.Value;
var kcUpper = _keltnerChannels.UpperBand.Current.Value;
var kcLower = _keltnerChannels.LowerBand.Current.Value;

// Determine if the squeeze condition is on or off
return (kcHigh > bbHigh && kcLow < bbLow) ? 1m : -1m;
return (kcUpper > bbUpper && kcLower < bbLower) ? 1m : -1m;
}

/// <summary>
Expand All @@ -104,7 +97,7 @@ protected override decimal ComputeNextValue(IBaseDataBar input)
public override void Reset()
{
_bollingerBands.Reset();
_averageTrueRange.Reset();
_keltnerChannels.Reset();
base.Reset();
}
}
Expand Down
Loading

0 comments on commit 7772ccc

Please sign in to comment.