public void Removed() { List <RocWbResult> results = quotes.GetRocWb(20, 3, 20) .RemoveWarmupPeriods() .ToList(); // assertions Assert.AreEqual(502 - (20 + 3 + 100), results.Count); RocWbResult last = results.LastOrDefault(); Assert.AreEqual(-8.2482, Math.Round(last.Roc.Value, 4)); Assert.AreEqual(-8.3390, Math.Round(last.RocEma.Value, 4)); Assert.AreEqual(6.1294, Math.Round(last.UpperBand.Value, 4)); Assert.AreEqual(-6.1294, Math.Round(last.LowerBand.Value, 4)); }
public void Standard() { List <RocWbResult> results = quotes.GetRocWb(20, 3, 20).ToList(); // assertions // proper quantities // should always be the same number of results as there is quotes Assert.AreEqual(502, results.Count); Assert.AreEqual(482, results.Where(x => x.Roc != null).Count()); Assert.AreEqual(480, results.Where(x => x.RocEma != null).Count()); Assert.AreEqual(463, results.Where(x => x.UpperBand != null).Count()); Assert.AreEqual(463, results.Where(x => x.LowerBand != null).Count()); // sample values RocWbResult r19 = results[19]; Assert.IsNull(r19.Roc); Assert.IsNull(r19.RocEma); Assert.IsNull(r19.UpperBand); Assert.IsNull(r19.LowerBand); RocWbResult r20 = results[20]; Assert.AreEqual(1.0573, Math.Round(r20.Roc.Value, 4)); Assert.IsNull(r20.RocEma); Assert.IsNull(r20.UpperBand); Assert.IsNull(r20.LowerBand); RocWbResult r22 = results[22]; Assert.AreEqual(0.9617, Math.Round(r22.RocEma.Value, 4)); Assert.IsNull(r22.UpperBand); Assert.IsNull(r22.LowerBand); RocWbResult r23 = results[23]; Assert.AreEqual(0.8582, Math.Round(r23.RocEma.Value, 4)); Assert.IsNull(r23.UpperBand); Assert.IsNull(r23.LowerBand); RocWbResult r38 = results[38]; Assert.AreEqual(3.6872, Math.Round(r38.RocEma.Value, 4)); Assert.IsNull(r38.UpperBand); Assert.IsNull(r38.LowerBand); RocWbResult r39 = results[39]; Assert.AreEqual(4.5348, Math.Round(r39.RocEma.Value, 4)); Assert.AreEqual(3.0359, Math.Round(r39.UpperBand.Value, 4)); Assert.AreEqual(-3.0359, Math.Round(r39.LowerBand.Value, 4)); RocWbResult r49 = results[49]; Assert.AreEqual(2.3147, Math.Round(r49.RocEma.Value, 4)); Assert.AreEqual(3.6761, Math.Round(r49.UpperBand.Value, 4)); RocWbResult r149 = results[149]; Assert.AreEqual(1.7377, Math.Round(r149.UpperBand.Value, 4)); RocWbResult r249 = results[249]; Assert.AreEqual(3.0683, Math.Round(r249.UpperBand.Value, 4)); RocWbResult r501 = results[501]; Assert.AreEqual(-8.2482, Math.Round(r501.Roc.Value, 4)); Assert.AreEqual(-8.3390, Math.Round(r501.RocEma.Value, 4)); Assert.AreEqual(6.1294, Math.Round(r501.UpperBand.Value, 4)); Assert.AreEqual(-6.1294, Math.Round(r501.LowerBand.Value, 4)); }
// RATE OF CHANGE (ROC) WITH BANDS /// <include file='./info.xml' path='indicator/type[@name="WithBands"]/*' /> /// public static IEnumerable <RocWbResult> GetRocWb <TQuote>( this IEnumerable <TQuote> quotes, int lookbackPeriods, int emaPeriods, int stdDevPeriods) where TQuote : IQuote { // check parameter arguments ValidateRocWb(lookbackPeriods, emaPeriods, stdDevPeriods); // initialize List <RocWbResult> results = GetRoc(quotes, lookbackPeriods) .Select(x => new RocWbResult { Date = x.Date, Roc = x.Roc }) .ToList(); double k = 2d / (emaPeriods + 1); double?lastEma = 0; int length = results.Count; if (length > lookbackPeriods) { int initPeriods = Math.Min(lookbackPeriods + emaPeriods, length); for (int i = lookbackPeriods; i < initPeriods; i++) { lastEma += results[i].Roc; } lastEma /= emaPeriods; } double?[] rocSq = results .Select(x => x.Roc * x.Roc) .ToArray(); // roll through quotes for (int i = lookbackPeriods; i < length; i++) { RocWbResult r = results[i]; int index = i + 1; // exponential moving average if (index > lookbackPeriods + emaPeriods) { r.RocEma = lastEma + (k * (r.Roc - lastEma)); lastEma = r.RocEma; } else if (index == lookbackPeriods + emaPeriods) { r.RocEma = lastEma; } // ROC deviation if (index >= lookbackPeriods + stdDevPeriods) { double?sumSq = 0; for (int p = i - stdDevPeriods + 1; p <= i; p++) { sumSq += rocSq[p]; } if (sumSq is not null) { double?rocDev = Math.Sqrt((double)sumSq / stdDevPeriods); r.UpperBand = rocDev; r.LowerBand = -rocDev; } } } return(results); }