// ENDPOINT MOVING AVERAGE /// <include file='./info.xml' path='indicator/*' /> /// public static IEnumerable <EpmaResult> GetEpma <TQuote>( this IEnumerable <TQuote> quotes, int lookbackPeriods) where TQuote : IQuote { // check parameter arguments ValidateEpma(lookbackPeriods); // initialize List <SlopeResult> slopeResults = GetSlope(quotes, lookbackPeriods) .ToList(); int length = slopeResults.Count; List <EpmaResult> results = new(length); // roll through quotes for (int i = 0; i < length; i++) { SlopeResult s = slopeResults[i]; EpmaResult r = new() { Date = s.Date, Epma = (decimal?)((s.Slope * (i + 1)) + s.Intercept) }; results.Add(r); } return(results); }
// STANDARD DEVIATION CHANNELS /// <include file='./info.xml' path='indicator/*' /> /// public static IEnumerable <StdDevChannelsResult> GetStdDevChannels <TQuote>( this IEnumerable <TQuote> quotes, int?lookbackPeriods = 20, double standardDeviations = 2) where TQuote : IQuote { // assume whole quotes when lookback is null if (lookbackPeriods is null) { lookbackPeriods = quotes.Count(); } // check parameter arguments ValidateStdDevChannels(lookbackPeriods, standardDeviations); // initialize List <SlopeResult> slopeResults = GetSlope(quotes, (int)lookbackPeriods).ToList(); int length = slopeResults.Count; List <StdDevChannelsResult> results = slopeResults .Select(x => new StdDevChannelsResult { Date = x.Date }) .ToList(); // roll through quotes in reverse for (int w = length - 1; w >= lookbackPeriods - 1; w -= (int)lookbackPeriods) { SlopeResult s = slopeResults[w]; decimal? width = (decimal?)(standardDeviations * s.StdDev); // add regression line (y = mx + b) and channels for (int p = w - (int)lookbackPeriods + 1; p <= w; p++) { if (p >= 0) { StdDevChannelsResult d = results[p]; d.Centerline = (decimal?)((s.Slope * (p + 1)) + s.Intercept); d.UpperChannel = d.Centerline + width; d.LowerChannel = d.Centerline - width; d.BreakPoint = p == w - lookbackPeriods + 1; } } } return(results); }
public void Removed() { List <SlopeResult> results = quotes.GetSlope(20) .RemoveWarmupPeriods() .ToList(); // assertions Assert.AreEqual(502 - 19, results.Count); SlopeResult last = results.LastOrDefault(); Assert.AreEqual(-1.689143, Math.Round((double)last.Slope, 6)); Assert.AreEqual(1083.7629, Math.Round((double)last.Intercept, 4)); Assert.AreEqual(0.7955, Math.Round((double)last.RSquared, 4)); Assert.AreEqual(10.9202, Math.Round((double)last.StdDev, 4)); Assert.AreEqual(235.8131m, Math.Round((decimal)last.Line, 4)); }
public void Standard() { int lookbackPeriod = 20; List <SlopeResult> results = Indicator.GetSlope(history, lookbackPeriod) .ToList(); // assertions // proper quantities // should always be the same number of results as there is history Assert.AreEqual(502, results.Count); Assert.AreEqual(483, results.Where(x => x.Slope != null).Count()); Assert.AreEqual(483, results.Where(x => x.StdDev != null).Count()); Assert.AreEqual(lookbackPeriod, results.Where(x => x.Line != null).Count()); // sample values SlopeResult r1 = results[249]; Assert.AreEqual(0.312406m, Math.Round((decimal)r1.Slope, 6)); Assert.AreEqual(180.4164m, Math.Round((decimal)r1.Intercept, 4)); Assert.AreEqual(0.8056m, Math.Round((decimal)r1.RSquared, 4)); Assert.AreEqual(2.0071m, Math.Round((decimal)r1.StdDev, 4)); Assert.AreEqual(null, r1.Line); SlopeResult r2 = results[482]; Assert.AreEqual(-0.337015m, Math.Round((decimal)r2.Slope, 6)); Assert.AreEqual(425.1111m, Math.Round((decimal)r2.Intercept, 4)); Assert.AreEqual(0.1730m, Math.Round((decimal)r2.RSquared, 4)); Assert.AreEqual(4.6719m, Math.Round((decimal)r2.StdDev, 4)); Assert.AreEqual(267.9069m, Math.Round((decimal)r2.Line, 4)); SlopeResult r3 = results[501]; Assert.AreEqual(-1.689143m, Math.Round((decimal)r3.Slope, 6)); Assert.AreEqual(1083.7629m, Math.Round((decimal)r3.Intercept, 4)); Assert.AreEqual(0.7955m, Math.Round((decimal)r3.RSquared, 4)); Assert.AreEqual(10.9202m, Math.Round((decimal)r3.StdDev, 4)); Assert.AreEqual(235.8131m, Math.Round((decimal)r3.Line, 4)); }
public void Standard() { List <SlopeResult> results = quotes.GetSlope(20).ToList(); // assertions // proper quantities // should always be the same number of results as there is quotes Assert.AreEqual(502, results.Count); Assert.AreEqual(483, results.Where(x => x.Slope != null).Count()); Assert.AreEqual(483, results.Where(x => x.StdDev != null).Count()); Assert.AreEqual(20, results.Where(x => x.Line != null).Count()); // sample values SlopeResult r1 = results[249]; Assert.AreEqual(0.312406, Math.Round((double)r1.Slope, 6)); Assert.AreEqual(180.4164, Math.Round((double)r1.Intercept, 4)); Assert.AreEqual(0.8056, Math.Round((double)r1.RSquared, 4)); Assert.AreEqual(2.0071, Math.Round((double)r1.StdDev, 4)); Assert.AreEqual(null, r1.Line); SlopeResult r2 = results[482]; Assert.AreEqual(-0.337015, Math.Round((double)r2.Slope, 6)); Assert.AreEqual(425.1111, Math.Round((double)r2.Intercept, 4)); Assert.AreEqual(0.1730, Math.Round((double)r2.RSquared, 4)); Assert.AreEqual(4.6719, Math.Round((double)r2.StdDev, 4)); Assert.AreEqual(267.9069m, Math.Round((decimal)r2.Line, 4)); SlopeResult r3 = results[501]; Assert.AreEqual(-1.689143, Math.Round((double)r3.Slope, 6)); Assert.AreEqual(1083.7629, Math.Round((double)r3.Intercept, 4)); Assert.AreEqual(0.7955, Math.Round((double)r3.RSquared, 4)); Assert.AreEqual(10.9202, Math.Round((double)r3.StdDev, 4)); Assert.AreEqual(235.8131m, Math.Round((decimal)r3.Line, 4)); }
// SLOPE AND LINEAR REGRESSION /// <include file='./info.xml' path='indicator/*' /> /// public static IEnumerable <SlopeResult> GetSlope <TQuote>( this IEnumerable <TQuote> quotes, int lookbackPeriods) where TQuote : IQuote { // convert quotes List <BasicD> bdList = quotes.ConvertToBasic(CandlePart.Close); // check parameter arguments ValidateSlope(lookbackPeriods); // initialize int length = bdList.Count; List <SlopeResult> results = new(length); // roll through quotes for (int i = 0; i < length; i++) { BasicD q = bdList[i]; int index = i + 1; SlopeResult r = new() { Date = q.Date }; results.Add(r); // skip initialization period if (index < lookbackPeriods) { continue; } // get averages for period double sumX = 0; double sumY = 0; for (int p = index - lookbackPeriods; p < index; p++) { BasicD d = bdList[p]; sumX += p + 1d; sumY += d.Value; } double avgX = sumX / lookbackPeriods; double avgY = sumY / lookbackPeriods; // least squares method double sumSqX = 0; double sumSqY = 0; double sumSqXY = 0; for (int p = index - lookbackPeriods; p < index; p++) { BasicD d = bdList[p]; double devX = p + 1d - avgX; double devY = d.Value - avgY; sumSqX += devX * devX; sumSqY += devY * devY; sumSqXY += devX * devY; } r.Slope = sumSqXY / sumSqX; r.Intercept = avgY - (r.Slope * avgX); // calculate Standard Deviation and R-Squared double stdDevX = Math.Sqrt((double)sumSqX / lookbackPeriods); double stdDevY = Math.Sqrt((double)sumSqY / lookbackPeriods); r.StdDev = stdDevY; if (stdDevX * stdDevY != 0) { double arrr = (double)sumSqXY / (stdDevX * stdDevY) / lookbackPeriods; r.RSquared = arrr * arrr; } } // add last Line (y = mx + b) if (length >= lookbackPeriods) { SlopeResult last = results.LastOrDefault(); for (int p = length - lookbackPeriods; p < length; p++) { SlopeResult d = results[p]; d.Line = (decimal?)((last.Slope * (p + 1)) + last.Intercept); } } return(results); }