diff --git a/src/_common/Results/Result.Models.cs b/src/_common/Results/Result.Models.cs index e966f5d4e..f031f7d84 100644 --- a/src/_common/Results/Result.Models.cs +++ b/src/_common/Results/Result.Models.cs @@ -2,17 +2,13 @@ namespace Skender.Stock.Indicators; // RESULT MODELS -public interface IResult : ISeries -{ -} - -public interface IReusableResult : IResult +public interface IReusableResult : ISeries { public double? Value { get; } } [Serializable] -public abstract class ResultBase : IResult +public abstract class ResultBase : ISeries { public DateTime Date { get; set; } } diff --git a/src/_common/Results/Result.Syncing.cs b/src/_common/Results/Result.Syncing.cs index 01dce0467..fbee8b4db 100644 --- a/src/_common/Results/Result.Syncing.cs +++ b/src/_common/Results/Result.Syncing.cs @@ -11,8 +11,8 @@ public static IEnumerable SyncIndex( this IEnumerable syncMe, IEnumerable toMatch, SyncType syncType = SyncType.FullMatch) - where TResultA : IResult - where TResultB : IResult + where TResultA : ISeries + where TResultB : ISeries { // initialize List syncMeList = syncMe.ToSortedList(); diff --git a/src/a-d/Atr/Atr.Series.cs b/src/a-d/Atr/Atr.Series.cs index 7d2523ade..d04a72d2b 100644 --- a/src/a-d/Atr/Atr.Series.cs +++ b/src/a-d/Atr/Atr.Series.cs @@ -20,7 +20,8 @@ internal static List CalcAtr( // roll through quotes for (int i = 0; i < qdList.Count; i++) { - double hmpc, lmpc; + double hmpc; + double lmpc; QuoteD q = qdList[i]; AtrResult r = new(q.Date); diff --git a/src/e-k/Ema/Ema.Stream.cs b/src/e-k/Ema/Ema.Stream.cs index e5472fd16..fad65dc99 100644 --- a/src/e-k/Ema/Ema.Stream.cs +++ b/src/e-k/Ema/Ema.Stream.cs @@ -1,7 +1,7 @@ namespace Skender.Stock.Indicators; // EXPONENTIAL MOVING AVERAGE (STREAMING) -internal class EmaBase +public class EmaBase { // initialize base internal EmaBase(IEnumerable<(DateTime, double)> tpQuotes, int lookbackPeriods) diff --git a/src/e-k/Fcb/Fcb.Series.cs b/src/e-k/Fcb/Fcb.Series.cs index fdfb62d36..6689bc1d7 100644 --- a/src/e-k/Fcb/Fcb.Series.cs +++ b/src/e-k/Fcb/Fcb.Series.cs @@ -18,7 +18,8 @@ internal static List CalcFcb( int length = fractals.Count; List results = new(length); - decimal? upperLine = null, lowerLine = null; + decimal? upperLine = null; + decimal? lowerLine = null; // roll through quotes for (int i = 0; i < length; i++) diff --git a/src/e-k/ForceIndex/ForceIndex.Series.cs b/src/e-k/ForceIndex/ForceIndex.Series.cs index 72b5affc5..fa1c23515 100644 --- a/src/e-k/ForceIndex/ForceIndex.Series.cs +++ b/src/e-k/ForceIndex/ForceIndex.Series.cs @@ -13,7 +13,9 @@ internal static List CalcForceIndex( // initialize int length = qdList.Count; List results = new(length); - double? prevClose = null, prevFI = null, sumRawFI = 0; + double? prevClose = null; + double? prevFI = null; + double? sumRawFI = 0; double k = 2d / (lookbackPeriods + 1); // roll through quotes diff --git a/src/s-z/Tsi/Tsi.Series.cs b/src/s-z/Tsi/Tsi.Series.cs index f244e6a50..c89f62891 100644 --- a/src/s-z/Tsi/Tsi.Series.cs +++ b/src/s-z/Tsi/Tsi.Series.cs @@ -70,21 +70,25 @@ internal static List CalcTsi( // signal line if (signalPeriods > 0) { - if (i >= lookbackPeriods + smoothPeriods + signalPeriods - 1) + int startSignal = lookbackPeriods + smoothPeriods + signalPeriods - 1; + + if (i >= startSignal) { r.Signal = ((tsi - results[i - 1].Signal) * multS).NaN2Null() + results[i - 1].Signal; } // initialize signal - else + else if (i == startSignal - 1) { sumS += tsi; + r.Signal = sumS / signalPeriods; + } - if (i == lookbackPeriods + smoothPeriods + signalPeriods - 2) - { - r.Signal = sumS / signalPeriods; - } + // warmup signal + else + { + sumS += tsi; } } } diff --git a/tests/indicators/_common/Results/Result.Syncing.Tests.cs b/tests/indicators/_common/Results/Result.Syncing.Tests.cs index f611b951b..4142c71f5 100644 --- a/tests/indicators/_common/Results/Result.Syncing.Tests.cs +++ b/tests/indicators/_common/Results/Result.Syncing.Tests.cs @@ -96,5 +96,9 @@ public void SyncIndex() Assert.IsFalse(noBaseResults.Any()); Assert.IsFalse(noEvalResults.Any()); + + // bad sync type + Assert.ThrowsException(() + => eval.SyncIndex(baseline, (SyncType)int.MaxValue)); } } diff --git a/tests/indicators/a-d/Chandelier/Chandelier.Tests.cs b/tests/indicators/a-d/Chandelier/Chandelier.Tests.cs index 3851ccb74..09f6b543a 100644 --- a/tests/indicators/a-d/Chandelier/Chandelier.Tests.cs +++ b/tests/indicators/a-d/Chandelier/Chandelier.Tests.cs @@ -100,5 +100,9 @@ public void Exceptions() // bad multiplier Assert.ThrowsException(() => quotes.GetChandelier(25, 0)); + + // bad type + Assert.ThrowsException(() => + quotes.GetChandelier(25, 2, (ChandelierType)int.MaxValue)); } } diff --git a/tests/indicators/m-r/Renko/Renko.Tests.cs b/tests/indicators/m-r/Renko/Renko.Tests.cs index df915da71..e650e0257 100644 --- a/tests/indicators/m-r/Renko/Renko.Tests.cs +++ b/tests/indicators/m-r/Renko/Renko.Tests.cs @@ -139,9 +139,15 @@ public void NoQuotes() Assert.AreEqual(0, r0.Count); } - // bad arguments [TestMethod] public void Exceptions() - => Assert.ThrowsException(() + { + // bad arguments + Assert.ThrowsException(() => quotes.GetRenko(0)); + + // bad end type + Assert.ThrowsException(() + => quotes.GetRenko(2, (EndType)int.MaxValue)); + } } diff --git a/tests/indicators/s-z/ZigZag/ZigZag.Tests.cs b/tests/indicators/s-z/ZigZag/ZigZag.Tests.cs index 9293369ca..8a6ecca46 100644 --- a/tests/indicators/s-z/ZigZag/ZigZag.Tests.cs +++ b/tests/indicators/s-z/ZigZag/ZigZag.Tests.cs @@ -220,9 +220,15 @@ public void SchrodingerScenario() Assert.AreEqual(342, r2.Count); } - // bad lookback period [TestMethod] public void Exceptions() - => Assert.ThrowsException(() + { + // bad lookback period + Assert.ThrowsException(() => quotes.GetZigZag(EndType.Close, 0)); + + // bad end type + Assert.ThrowsException(() + => quotes.GetZigZag((EndType)int.MaxValue, 2)); + } }