Example Of Implementation |
Let us implement NewExtremum (IsNewHigh / IsNewLow) technical indicator.
(NewHigh/NewLow) reference: Indicator has two periods (first and second), one of the values of indicator is highest (lowest) price on short period, and second value is highest (lowest) price on long period. Market signal on this indicator generated analyzing is there highest (lowest) value of long period lay on short period.
We need only one single value – current price (it may be close, typical price or something else), so indicator type is BaseSimpleIndicator.
We want to store four values highest/lowest price on short/long period so our indicator return value is Slice, so we inherit our indicator as following:
1using System; 2using System.Collections.Generic; 3using FinAnalysis.Base; 4 5namespace FinAnalysis.TA 6{ 7 public class NewExtremum : BaseSimpleIndicator<NewExtremum.Slice> 8 { 9 private MinMaxQueue longHighQueue; 10 private MinMaxQueue longLowQueue; 11 private MinMaxQueue shortHighQueue; 12 private MinMaxQueue shortLowQueue; 13 14 public struct Slice 15 { 16 public double LongHigh; 17 public double LongLow; 18 public double ShortHigh; 19 public double ShortLow; 20 } 21 } 22}
The next step is to implement appropriate constructors. As you see indicator has two parameters short and long period, also there are no problems with support time based periods (we may use MinMaxQueue to maintain this situation), so we create our constructors:
1private MinMaxQueue longHighQueue; 2private MinMaxQueue longLowQueue; 3private MinMaxQueue shortHighQueue; 4private MinMaxQueue shortLowQueue; 5public NewExtremum() 6: this(14,28) 7{ 8} 9 10public NewExtremum(int shortPeriod, int longPeriod) 11{ 12 if (longPeriod < shortPeriod) 13 throw new ArgumentException("Long period must be longer than short."); 14 15 unstableValuesCount = longPeriod; 16 17 longHighQueue = new MinMaxQueue(longPeriod, MinMaxQueue.MinOrMax.CalcMax); 18 longLowQueue = new MinMaxQueue(longPeriod, MinMaxQueue.MinOrMax.CalcMin); 19 shortHighQueue = new MinMaxQueue(shortPeriod, MinMaxQueue.MinOrMax.CalcMax); 20 shortLowQueue = new MinMaxQueue(shortPeriod, MinMaxQueue.MinOrMax.CalcMin); 21} 22 23public NewExtremum(TimeSpan shortPeriod, TimeSpan longPeriod) 24{ 25 EnsureDateTime(); 26 if (longPeriod < shortPeriod) 27 throw new ArgumentException("Long period must be longer than short."); 28 29 unstablePeriod = longPeriod; 30 31 longHighQueue = new MinMaxQueue(longPeriod, MinMaxQueue.MinOrMax.CalcMax); 32 longLowQueue = new MinMaxQueue(longPeriod, MinMaxQueue.MinOrMax.CalcMin); 33 shortHighQueue = new MinMaxQueue(shortPeriod, MinMaxQueue.MinOrMax.CalcMax); 34 shortLowQueue = new MinMaxQueue(shortPeriod, MinMaxQueue.MinOrMax.CalcMin); 35}
Period of instability indicator values equal to indicator long period. Do not forget to call EnsureDateTime() for time based constructor.
Going further we need to implement update method, all we need it’s supply data for our queues, and store high and low values:
1protected override bool Update(double value, DateTime time, out NewExtremum.Slice result) 2{ 3 longHighQueue.Put(value, time); 4 longLowQueue.Put(value, time); 5 shortHighQueue.Put(value, time); 6 shortLowQueue.Put(value, time); 7 8 Slice slice = new Slice(); 9 slice.LongHigh = longHighQueue.Extremum; 10 slice.LongLow = longLowQueue.Extremum; 11 slice.ShortHigh = shortHighQueue.Extremum; 12 slice.ShortLow = shortLowQueue.Extremum; 13 14 result = slice; 15 16 return true; 17}
And now we can specify output properties:
1public Double LongHigh { get { return Last.LongHigh; } } 2public Double LongLow { get { return Last.LongLow; } } 3public Double ShortHigh { get { return Last.ShortHigh; } } 4public Double ShortLow { get { return Last.ShortLow; } }
And you specify few custom properties and method if you want. For example you can return date and time when current extremum occur:
1public DateTime LongHighTime { get { return longHighQueue.ExtremumDateTime; } } 2public DateTime LongLowTime { get { return longLowQueue.ExtremumDateTime; } } 3public DateTime ShortHighTime { get { return shortHighQueue.ExtremumDateTime; } } 4public DateTime ShortLowTime { get { return shortLowQueue.ExtremumDateTime; } }
And the last step (this step is necessary only for charting) is setting up Attributes.
Indicator name, short name, description and type before indicator definition:
1[IndicatorCategory(IndicatorCategory.BandIndicator)] 2[Indicator("NewExtremum", "NewExtremum", "NewExtremum (agregation of NewHigh and NewLow) indicate price range on specified long and short periods.")] 3public class NewExtremum : BaseSimpleIndicator<NewExtremum.Slice> 4….
Mark constructors and constructor’s parameters with appropriate attributes:
1[Constructor("Point Window")] 2public NewExtremum([Parameter("Fast Period", 14)]int shortPeriod, [Parameter("Slow Period", 28)]int longPeriod) 3... 4 5[Constructor("Time Window")] 6public NewExtremum([Parameter("Fast Time Period", null)]TimeSpan shortPeriod, [Parameter("Slow Time Period", null)]TimeSpan longPeriod) 7...
And specify attributes for indicator’s output values:
1[OutputProperty("Long-term High", ChartPlacement.PriceChart)] 2public Double LongHigh { get { return Last.LongHigh; } } 3[OutputProperty("Long-term Low", ChartPlacement.PriceChart)] 4public Double LongLow { get { return Last.LongLow; } } 5[OutputProperty("Short-term High", ChartPlacement.PriceChart)] 6public Double ShortHigh { get { return Last.ShortHigh; } } 7[OutputProperty("Short-term Low", ChartPlacement.PriceChart)] 8public Double ShortLow { get { return Last.ShortLow; } }
That’s all. Our indicator is ready for usage. Compile it and use.