public void GetStochStandardTest() { int lookbackPeriod = 14; int signalPeriod = 3; int smoothPeriod = 3; IEnumerable <StochResult> results = Indicator.GetStoch( history, lookbackPeriod, signalPeriod, smoothPeriod); // assertions // proper quantities // should always be the same number of results as there is history Assert.AreEqual(502, results.Count()); Assert.AreEqual(487, results.Where(x => x.Oscillator != null).Count()); Assert.AreEqual(485, results.Where(x => x.Signal != null).Count()); Assert.AreEqual(486, results.Where(x => x.IsIncreasing != null).Count()); // sample value StochResult r = results.Where(x => x.Date == DateTime.ParseExact("12/31/2018", "MM/dd/yyyy", null)).FirstOrDefault(); Assert.AreEqual((decimal)43.1353, Math.Round((decimal)r.Oscillator, 4)); Assert.AreEqual((decimal)35.5674, Math.Round((decimal)r.Signal, 4)); Assert.AreEqual(true, r.IsIncreasing); }
// STOCHASTIC RSI /// <include file='./info.xml' path='indicator/*' /> /// public static IEnumerable <StochRsiResult> GetStochRsi <TQuote>( this IEnumerable <TQuote> quotes, int rsiPeriods, int stochPeriods, int signalPeriods, int smoothPeriods = 1) where TQuote : IQuote { // check parameter arguments ValidateStochRsi(rsiPeriods, stochPeriods, signalPeriods, smoothPeriods); // initialize List <RsiResult> rsiResults = GetRsi(quotes, rsiPeriods).ToList(); List <StochRsiResult> results = new(rsiResults.Count); // convert rsi to quote format List <Quote> rsiQuotes = rsiResults .Where(x => x.Rsi != null) .Select(x => new Quote { Date = x.Date, High = (decimal)x.Rsi, Low = (decimal)x.Rsi, Close = (decimal)x.Rsi }) .ToList(); // get Stochastic of RSI List <StochResult> stoResults = GetStoch(rsiQuotes, stochPeriods, signalPeriods, smoothPeriods) .ToList(); // compose for (int i = 0; i < rsiResults.Count; i++) { RsiResult r = rsiResults[i]; int index = i + 1; StochRsiResult result = new() { Date = r.Date }; if (index >= rsiPeriods + stochPeriods) { StochResult sto = stoResults[index - rsiPeriods - 1]; result.StochRsi = sto.Oscillator; result.Signal = sto.Signal; } results.Add(result); } return(results); }
public void Extended() // with extra parameteres { List <StochResult> results = quotes.GetStoch(9, 3, 3, 5, 4, MaType.SMMA) .ToList(); // assertions // proper quantities // should always be the same number of results as there is quotes Assert.AreEqual(502, results.Count); Assert.AreEqual(494, results.Where(x => x.K != null).Count()); Assert.AreEqual(494, results.Where(x => x.D != null).Count()); // sample values StochResult r7 = results[7]; Assert.IsNull(r7.K); Assert.IsNull(r7.D); Assert.IsNull(r7.J); StochResult r8 = results[8]; Assert.AreEqual(81.9178m, Math.Round((decimal)r8.K, 4)); Assert.AreEqual(81.9178m, Math.Round((decimal)r8.D, 4)); Assert.AreEqual(81.9178m, Math.Round((decimal)r8.J, 4)); StochResult r17 = results[17]; Assert.AreEqual(82.5181m, Math.Round((decimal)r17.K, 4)); Assert.AreEqual(76.2603m, Math.Round((decimal)r17.D, 4)); Assert.AreEqual(107.5491m, Math.Round((decimal)r17.J, 4)); StochResult r149 = results[149]; Assert.AreEqual(77.1571m, Math.Round((decimal)r149.K, 4)); Assert.AreEqual(72.8206m, Math.Round((decimal)r149.D, 4)); Assert.AreEqual(94.5030m, Math.Round((decimal)r149.J, 4)); StochResult r249 = results[249]; // also testing aliases here Assert.AreEqual(74.3652m, Math.Round((decimal)r249.K, 4)); Assert.AreEqual(75.5660m, Math.Round((decimal)r249.D, 4)); Assert.AreEqual(69.5621m, Math.Round((decimal)r249.J, 4)); StochResult r501 = results[501]; Assert.AreEqual(46.9807m, Math.Round((decimal)r501.K, 4)); Assert.AreEqual(32.0413m, Math.Round((decimal)r501.D, 4)); Assert.AreEqual(106.7382m, Math.Round((decimal)r501.J, 4)); }
public void Standard() // Slow { int lookbackPeriod = 14; int signalPeriod = 3; int smoothPeriod = 3; List <StochResult> results = Indicator.GetStoch(history, lookbackPeriod, signalPeriod, smoothPeriod) .ToList(); // assertions // proper quantities // should always be the same number of results as there is history Assert.AreEqual(502, results.Count); Assert.AreEqual(487, results.Where(x => x.Oscillator != null).Count()); Assert.AreEqual(485, results.Where(x => x.Signal != null).Count()); // sample values StochResult r1 = results[15]; Assert.AreEqual(81.1253m, Math.Round((decimal)r1.Oscillator, 4)); Assert.IsNull(r1.Signal); Assert.IsNull(r1.PercentJ); StochResult r2 = results[17]; Assert.AreEqual(92.1307m, Math.Round((decimal)r2.Oscillator, 4)); Assert.AreEqual(88.4995m, Math.Round((decimal)r2.Signal, 4)); Assert.AreEqual(99.3929m, Math.Round((decimal)r2.PercentJ, 4)); StochResult r3 = results[149]; Assert.AreEqual(81.6870m, Math.Round((decimal)r3.Oscillator, 4)); Assert.AreEqual(79.7935m, Math.Round((decimal)r3.Signal, 4)); Assert.AreEqual(85.4741m, Math.Round((decimal)r3.PercentJ, 4)); StochResult r4 = results[249]; Assert.AreEqual(83.2020m, Math.Round((decimal)r4.Oscillator, 4)); Assert.AreEqual(83.0813m, Math.Round((decimal)r4.Signal, 4)); Assert.AreEqual(83.4435m, Math.Round((decimal)r4.PercentJ, 4)); StochResult r5 = results[501]; Assert.AreEqual(43.1353m, Math.Round((decimal)r5.Oscillator, 4)); Assert.AreEqual(35.5674m, Math.Round((decimal)r5.Signal, 4)); Assert.AreEqual(58.2712m, Math.Round((decimal)r5.PercentJ, 4)); }
public void Standard() // Slow { int lookbackPeriods = 14; int signalPeriods = 3; int smoothPeriods = 3; List <StochResult> results = quotes.GetStoch(lookbackPeriods, signalPeriods, smoothPeriods) .ToList(); // assertions // proper quantities // should always be the same number of results as there is quotes Assert.AreEqual(502, results.Count); Assert.AreEqual(487, results.Where(x => x.Oscillator != null).Count()); Assert.AreEqual(485, results.Where(x => x.Signal != null).Count()); // sample values StochResult r15 = results[15]; Assert.AreEqual(81.1253m, Math.Round((decimal)r15.Oscillator, 4)); Assert.IsNull(r15.Signal); Assert.IsNull(r15.PercentJ); StochResult r17 = results[17]; Assert.AreEqual(92.1307m, Math.Round((decimal)r17.Oscillator, 4)); Assert.AreEqual(88.4995m, Math.Round((decimal)r17.Signal, 4)); Assert.AreEqual(99.3929m, Math.Round((decimal)r17.PercentJ, 4)); StochResult r149 = results[149]; Assert.AreEqual(81.6870m, Math.Round((decimal)r149.Oscillator, 4)); Assert.AreEqual(79.7935m, Math.Round((decimal)r149.Signal, 4)); Assert.AreEqual(85.4741m, Math.Round((decimal)r149.PercentJ, 4)); StochResult r249 = results[249]; // also testing aliases here Assert.AreEqual(83.2020m, Math.Round((decimal)r249.K, 4)); Assert.AreEqual(83.0813m, Math.Round((decimal)r249.D, 4)); Assert.AreEqual(83.4435m, Math.Round((decimal)r249.J, 4)); StochResult r501 = results[501]; Assert.AreEqual(43.1353m, Math.Round((decimal)r501.Oscillator, 4)); Assert.AreEqual(35.5674m, Math.Round((decimal)r501.Signal, 4)); Assert.AreEqual(58.2712m, Math.Round((decimal)r501.PercentJ, 4)); }
public void GetStochNoSignalTest() { int lookbackPeriod = 5; int signalPeriod = 1; int smoothPeriod = 3; IEnumerable <StochResult> results = Indicator.GetStoch( history, lookbackPeriod, signalPeriod, smoothPeriod); // signal equals oscillator StochResult r1 = results.Where(x => x.Date == DateTime.ParseExact("12/31/2018", "MM/dd/yyyy", null)).FirstOrDefault(); Assert.AreEqual(r1.Oscillator, r1.Signal); StochResult r2 = results.Where(x => x.Date == DateTime.ParseExact("12/10/2018", "MM/dd/yyyy", null)).FirstOrDefault(); Assert.AreEqual(r2.Oscillator, r2.Signal); }
public void GetStochNoSignalTest() { int lookbackPeriod = 5; int signalPeriod = 1; int smoothPeriod = 3; IEnumerable <StochResult> results = Indicator.GetStoch( history, lookbackPeriod, signalPeriod, smoothPeriod); // signal equals oscillator StochResult r1 = results.Where(x => x.Index == 502).FirstOrDefault(); Assert.AreEqual(r1.Oscillator, r1.Signal); StochResult r2 = results.Where(x => x.Index == 488).FirstOrDefault(); Assert.AreEqual(r2.Oscillator, r2.Signal); }
public void GetStochFastSmallPeriodTest() { int lookbackPeriod = 1; int signalPeriod = 10; int smoothPeriod = 1; IEnumerable <StochResult> results = Indicator.GetStoch( history, lookbackPeriod, signalPeriod, smoothPeriod); // sample values StochResult r1 = results.Where(x => x.Index == 71).FirstOrDefault(); Assert.AreEqual(0m, Math.Round((decimal)r1.Oscillator, 4)); StochResult r2 = results.Where(x => x.Index == 72).FirstOrDefault(); Assert.AreEqual(100m, Math.Round((decimal)r2.Oscillator, 4)); }
public void GetStochFastSmall() { int lookbackPeriod = 1; int signalPeriod = 10; int smoothPeriod = 1; List <StochResult> results = Indicator.GetStoch(history, lookbackPeriod, signalPeriod, smoothPeriod) .ToList(); // sample values StochResult r1 = results[70]; Assert.AreEqual(0m, Math.Round((decimal)r1.Oscillator, 4)); StochResult r2 = results[71]; Assert.AreEqual(100m, Math.Round((decimal)r2.Oscillator, 4)); }
public void GetStochNoSignal() { int lookbackPeriod = 5; int signalPeriod = 1; int smoothPeriod = 3; List <StochResult> results = Indicator.GetStoch(history, lookbackPeriod, signalPeriod, smoothPeriod) .ToList(); // signal equals oscillator StochResult r1 = results[501]; Assert.AreEqual(r1.Oscillator, r1.Signal); StochResult r2 = results[487]; Assert.AreEqual(r2.Oscillator, r2.Signal); }
public void Removed() { int lookbackPeriods = 14; int signalPeriods = 3; int smoothPeriods = 3; List <StochResult> results = quotes.GetStoch(lookbackPeriods, signalPeriods, smoothPeriods) .RemoveWarmupPeriods() .ToList(); // assertions Assert.AreEqual(502 - (lookbackPeriods + smoothPeriods - 2), results.Count); StochResult last = results.LastOrDefault(); Assert.AreEqual(43.1353m, Math.Round((decimal)last.Oscillator, 4)); Assert.AreEqual(35.5674m, Math.Round((decimal)last.Signal, 4)); Assert.AreEqual(58.2712m, Math.Round((decimal)last.PercentJ, 4)); }
public void GetStochFastTest() { int lookbackPeriod = 5; int signalPeriod = 10; int smoothPeriod = 1; IEnumerable <StochResult> results = Indicator.GetStoch( history, lookbackPeriod, signalPeriod, smoothPeriod); // sample values StochResult r1 = results.Where(x => x.Index == 502).FirstOrDefault(); Assert.AreEqual(91.6233m, Math.Round((decimal)r1.Oscillator, 4)); Assert.AreEqual(36.0608m, Math.Round((decimal)r1.Signal, 4)); StochResult r2 = results.Where(x => x.Index == 488).FirstOrDefault(); Assert.AreEqual(25.0353m, Math.Round((decimal)r2.Oscillator, 4)); Assert.AreEqual(60.5706m, Math.Round((decimal)r2.Signal, 4)); }
public void GetStochFast() { int lookbackPeriod = 5; int signalPeriod = 10; int smoothPeriod = 1; List <StochResult> results = Indicator.GetStoch(history, lookbackPeriod, signalPeriod, smoothPeriod) .ToList(); // sample values StochResult r1 = results[501]; Assert.AreEqual(91.6233m, Math.Round((decimal)r1.Oscillator, 4)); Assert.AreEqual(36.0608m, Math.Round((decimal)r1.Signal, 4)); StochResult r2 = results[487]; Assert.AreEqual(25.0353m, Math.Round((decimal)r2.Oscillator, 4)); Assert.AreEqual(60.5706m, Math.Round((decimal)r2.Signal, 4)); }
public void GetStochFastTest() { int lookbackPeriod = 5; int signalPeriod = 10; int smoothPeriod = 1; IEnumerable <StochResult> results = Indicator.GetStoch( history, lookbackPeriod, signalPeriod, smoothPeriod); // sample values StochResult r1 = results.Where(x => x.Date == DateTime.ParseExact("12/31/2018", "MM/dd/yyyy", null)).FirstOrDefault(); Assert.AreEqual((decimal)91.6233, Math.Round((decimal)r1.Oscillator, 4)); Assert.AreEqual((decimal)36.0608, Math.Round((decimal)r1.Signal, 4)); Assert.AreEqual(true, r1.IsIncreasing); StochResult r2 = results.Where(x => x.Date == DateTime.ParseExact("12/10/2018", "MM/dd/yyyy", null)).FirstOrDefault(); Assert.AreEqual((decimal)25.0353, Math.Round((decimal)r2.Oscillator, 4)); Assert.AreEqual((decimal)60.5706, Math.Round((decimal)r2.Signal, 4)); Assert.AreEqual(true, r2.IsIncreasing); }
public void GetStochStandardTest() { int lookbackPeriod = 14; int signalPeriod = 3; int smoothPeriod = 3; IEnumerable <StochResult> results = Indicator.GetStoch( history, lookbackPeriod, signalPeriod, smoothPeriod); // assertions // proper quantities // should always be the same number of results as there is history Assert.AreEqual(502, results.Count()); Assert.AreEqual(487, results.Where(x => x.Oscillator != null).Count()); Assert.AreEqual(485, results.Where(x => x.Signal != null).Count()); // sample value StochResult r = results.Where(x => x.Index == 502).FirstOrDefault(); Assert.AreEqual(43.1353m, Math.Round((decimal)r.Oscillator, 4)); Assert.AreEqual(35.5674m, Math.Round((decimal)r.Signal, 4)); }
/// <include file='./info.xml' path='indicator/type[@name="Extended"]/*' /> /// public static IEnumerable <StochResult> GetStoch <TQuote>( this IEnumerable <TQuote> quotes, int lookbackPeriods, int signalPeriods, int smoothPeriods, decimal kFactor, decimal dFactor, MaType movingAverageType) where TQuote : IQuote { // convert quotes List <QuoteD> quotesList = quotes.ConvertToList(); // check parameter arguments ValidateStoch( lookbackPeriods, signalPeriods, smoothPeriods, kFactor, dFactor, movingAverageType); // initialize int length = quotesList.Count; List <StochResult> results = new(length); // roll through quotes for (int i = 0; i < length; i++) { QuoteD q = quotesList[i]; int index = i + 1; StochResult result = new() { Date = q.Date }; if (index >= lookbackPeriods) { double?highHigh = double.MinValue; double?lowLow = double.MaxValue; for (int p = index - lookbackPeriods; p < index; p++) { QuoteD x = quotesList[p]; if (x.High > highHigh) { highHigh = x.High; } if (x.Low < lowLow) { lowLow = x.Low; } } result.Oscillator = lowLow != highHigh ? 100 * (decimal?)((q.Close - lowLow) / (highHigh - lowLow)) : 0; } results.Add(result); } // smooth the oscillator if (smoothPeriods > 1) { results = SmoothOscillator( results, length, lookbackPeriods, smoothPeriods, movingAverageType); } // handle insufficient length if (length < lookbackPeriods - 1) { return(results); } // signal (%D) and %J int signalIndex = lookbackPeriods + smoothPeriods + signalPeriods - 2; double?s = (double?)results[lookbackPeriods - 1].Oscillator; for (int i = lookbackPeriods - 1; i < length; i++) { StochResult r = results[i]; int index = i + 1; // add signal if (signalPeriods <= 1) { r.Signal = r.Oscillator; } // SMA case else if (index >= signalIndex && movingAverageType is MaType.SMA) { double?sumOsc = 0; for (int p = index - signalPeriods; p < index; p++) { StochResult x = results[p]; sumOsc += (double?)x.Oscillator; } r.Signal = (decimal?)(sumOsc / signalPeriods); } // SMMA case else if (i >= lookbackPeriods - 1 && movingAverageType is MaType.SMMA) { s = (s == null) ? (double?)results[i].Oscillator : s; // reset if null s = ((s * (signalPeriods - 1)) + (double?)results[i].Oscillator) / signalPeriods; r.Signal = (decimal?)s; } // %J r.PercentJ = (kFactor * r.Oscillator) - (dFactor * r.Signal); } return(results); }