// ENDPOINT MOVING AVERAGE /// <include file='./info.xml' path='indicators/type[@name="Main"]/*' /> /// public static IEnumerable <EpmaResult> GetEpma <TQuote>( IEnumerable <TQuote> history, int lookbackPeriod) where TQuote : IQuote { // check parameter arguments ValidateEpma(history, lookbackPeriod); // initialize List <SlopeResult> slopeResults = GetSlope(history, lookbackPeriod) .ToList(); int size = slopeResults.Count; List <EpmaResult> results = new(size); // roll through history for (int i = 0; i < size; i++) { SlopeResult s = slopeResults[i]; EpmaResult r = new() { Date = s.Date, Epma = 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> history, int?lookbackPeriod = 20, decimal standardDeviations = 2) where TQuote : IQuote { // assume whole history when lookback is null if (lookbackPeriod is null) { lookbackPeriod = history.Count(); } // check parameter arguments ValidateStdDevChannels(history, lookbackPeriod, standardDeviations); // initialize List <SlopeResult> slopeResults = GetSlope(history, (int)lookbackPeriod).ToList(); int size = slopeResults.Count; List <StdDevChannelsResult> results = slopeResults .Select(x => new StdDevChannelsResult { Date = x.Date }) .ToList(); // roll through history in reverse for (int w = size - 1; w >= lookbackPeriod - 1; w -= (int)lookbackPeriod) { SlopeResult s = slopeResults[w]; // add regression line (y = mx + b) and channels for (int p = w - (int)lookbackPeriod + 1; p <= w; p++) { if (p >= 0) { StdDevChannelsResult d = results[p]; d.Centerline = s.Slope * (p + 1) + s.Intercept; decimal width = standardDeviations * (decimal)s.StdDev; d.UpperChannel = d.Centerline + width; d.LowerChannel = d.Centerline - width; d.BreakPoint = (p == w - lookbackPeriod + 1); } } } return(results); }
// SLOPE AND LINEAR REGRESSION /// <include file='./info.xml' path='indicator/*' /> /// public static IEnumerable <SlopeResult> GetSlope <TQuote>( this IEnumerable <TQuote> history, int lookbackPeriod) where TQuote : IQuote { // sort history List <TQuote> historyList = history.Sort(); // check parameter arguments ValidateSlope(history, lookbackPeriod); // initialize int size = historyList.Count; List <SlopeResult> results = new(size); // roll through history for (int i = 0; i < size; i++) { TQuote h = historyList[i]; int index = i + 1; SlopeResult r = new() { Date = h.Date }; results.Add(r); // skip initialization period if (index < lookbackPeriod) { continue; } // get averages for period decimal sumX = 0m; decimal sumY = 0m; for (int p = index - lookbackPeriod; p < index; p++) { TQuote d = historyList[p]; sumX += p + 1m; sumY += d.Close; } decimal avgX = sumX / lookbackPeriod; decimal avgY = sumY / lookbackPeriod; // least squares method decimal sumSqX = 0m; decimal sumSqY = 0m; decimal sumSqXY = 0m; for (int p = index - lookbackPeriod; p < index; p++) { TQuote d = historyList[p]; decimal devX = (p + 1m - avgX); decimal devY = (d.Close - 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 / lookbackPeriod); double stdDevY = Math.Sqrt((double)sumSqY / lookbackPeriod); r.StdDev = stdDevY; if (stdDevX * stdDevY != 0) { double R = ((double)sumSqXY / (stdDevX * stdDevY)) / lookbackPeriod; r.RSquared = R * R; } } // add last Line (y = mx + b) SlopeResult last = results.LastOrDefault(); for (int p = size - lookbackPeriod; p < size; p++) { SlopeResult d = results[p]; d.Line = last.Slope * (p + 1) + last.Intercept; } return(results); }
// SLOPE AND LINEAR REGRESSION public static IEnumerable <SlopeResult> GetSlope(IEnumerable <Quote> history, int lookbackPeriod) { // clean quotes List <Quote> historyList = Cleaners.PrepareHistory(history).ToList(); // validate parameters ValidateSlope(history, lookbackPeriod); // initialize List <SlopeResult> results = new List <SlopeResult>(); // roll through history for interim data for (int i = 0; i < historyList.Count; i++) { Quote h = historyList[i]; SlopeResult r = new SlopeResult { Index = (int)h.Index, Date = h.Date }; results.Add(r); // skip initialization period if (h.Index < lookbackPeriod) { continue; } // get averages for period decimal sumX = 0m; decimal sumY = 0m; for (int p = r.Index - lookbackPeriod; p < r.Index; p++) { Quote d = historyList[p]; sumX += (decimal)d.Index; sumY += d.Close; } decimal avgX = sumX / lookbackPeriod; decimal avgY = sumY / lookbackPeriod; // least squares method decimal sumSqX = 0m; decimal sumSqY = 0m; decimal sumSqXY = 0m; for (int p = r.Index - lookbackPeriod; p < r.Index; p++) { Quote d = historyList[p]; decimal devX = ((decimal)d.Index - avgX); decimal devY = (d.Close - 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 / lookbackPeriod); double stdDevY = Math.Sqrt((double)sumSqY / lookbackPeriod); r.StdDev = stdDevY; if (stdDevX * stdDevY != 0) { double R = ((double)sumSqXY / (stdDevX * stdDevY)) / lookbackPeriod; r.RSquared = R * R; } } // add last Line (y = mx + b) SlopeResult last = results[historyList.Count - 1]; for (int p = last.Index - lookbackPeriod; p < last.Index; p++) { SlopeResult d = results[p]; d.Line = last.Slope * d.Index + last.Intercept; } return(results); }