// CORRELATION COEFFICIENT public static IEnumerable <CorrResult> GetCorrelation( IEnumerable <Quote> historyA, IEnumerable <Quote> historyB, int lookbackPeriod) { // clean quotes historyA = Cleaners.PrepareHistory(historyA); historyB = Cleaners.PrepareHistory(historyB); // check exceptions int qtyHistory = historyA.Count(); int minHistory = lookbackPeriod; if (qtyHistory < minHistory) { throw new BadHistoryException("Insufficient history provided for Correlation. " + string.Format("You provided {0} periods of history when {1} is required.", qtyHistory, minHistory)); } // initialize List <CorrResult> results = new List <CorrResult>(); // roll through history for interim data foreach (Quote a in historyA) { Quote b = historyB.Where(x => x.Date == a.Date).FirstOrDefault(); if (b == null) { throw new BadHistoryException("Correlation requires matching dates in provided histories. {0} not found in historyB."); } CorrResult result = new CorrResult { Index = (int)a.Index, Date = a.Date, PriceA = a.Close, PriceB = b.Close // other values calculated in class properties }; results.Add(result); } // compute correlation foreach (CorrResult r in results.Where(x => x.Index >= lookbackPeriod)) { IEnumerable <CorrResult> period = results.Where(x => x.Index > (r.Index - lookbackPeriod) && x.Index <= r.Index); decimal avgA = period.Select(x => x.PriceA).Average(); decimal avgB = period.Select(x => x.PriceB).Average(); decimal avgA2 = period.Select(x => x.PriceA2).Average(); decimal avgB2 = period.Select(x => x.PriceB2).Average(); decimal avgAB = period.Select(x => x.PriceAB).Average(); r.VarianceA = avgA2 - avgA * avgA; r.VarianceB = avgB2 - avgB * avgB; r.Covariance = avgAB - avgA * avgB; r.Correlation = r.Covariance / (decimal)Math.Sqrt((double)(r.VarianceA * r.VarianceB)); } return(results); }
// BETA COEFFICIENT public static IEnumerable <BetaResult> GetBeta( IEnumerable <Quote> historyMarket, IEnumerable <Quote> historyEval, int lookbackPeriod) { // clean quotes historyMarket = Cleaners.PrepareHistory(historyMarket); historyEval = Cleaners.PrepareHistory(historyEval); // initialize results List <BetaResult> results = new List <BetaResult>(); // get prerequisite data IEnumerable <CorrResult> correlation = GetCorrelation(historyMarket, historyEval, lookbackPeriod); // roll through history for interim data foreach (Quote e in historyEval) { BetaResult result = new BetaResult { Index = (int)e.Index, Date = e.Date }; // calculate beta, if available CorrResult c = correlation.Where(x => x.Date == e.Date).FirstOrDefault(); if (c.Covariance != null && c.VarianceA != null && c.VarianceA != 0) { result.Beta = c.Covariance / c.VarianceA; } results.Add(result); } return(results); }
// BETA COEFFICIENT public static IEnumerable <BetaResult> GetBeta( IEnumerable <Quote> historyMarket, IEnumerable <Quote> historyEval, int lookbackPeriod) { // clean quotes historyMarket = Cleaners.PrepareHistory(historyMarket); historyEval = Cleaners.PrepareHistory(historyEval); // check exceptions int qtyHistory = historyEval.Count(); int minHistory = lookbackPeriod; if (qtyHistory < minHistory) { throw new BadHistoryException("Insufficient history provided for Beta. " + string.Format("You provided {0} periods of history when {1} is required." , qtyHistory, minHistory)); } // initialize results List <BetaResult> results = new List <BetaResult>(); // get prerequisite data IEnumerable <CorrResult> correlation = GetCorrelation(historyMarket, historyEval, lookbackPeriod); // roll through history for interim data foreach (Quote e in historyEval) { BetaResult result = new BetaResult { Index = (int)e.Index, Date = e.Date }; // calculate beta, if available CorrResult c = correlation.Where(x => x.Date == e.Date).FirstOrDefault(); if (c.Covariance != null && c.VarianceA != null && c.VarianceA != 0) { result.Beta = c.Covariance / c.VarianceA; } results.Add(result); } return(results); }
// BETA COEFFICIENT public static IEnumerable <BetaResult> GetBeta <TQuote>( IEnumerable <TQuote> historyMarket, IEnumerable <TQuote> historyEval, int lookbackPeriod) where TQuote : IQuote { // clean quotes List <TQuote> historyEvalList = historyEval.Sort(); // validate parameters ValidateBeta(historyMarket, historyEval, lookbackPeriod); // initialize results List <BetaResult> results = new List <BetaResult>(); // get prerequisite data List <CorrResult> correlation = GetCorrelation(historyMarket, historyEval, lookbackPeriod).ToList(); // roll through history for interim data for (int i = 0; i < historyEvalList.Count; i++) { TQuote e = historyEvalList[i]; BetaResult result = new BetaResult { Date = e.Date }; // calculate beta, if available CorrResult c = correlation[i]; if (c.Covariance != null && c.VarianceA != null && c.VarianceA != 0) { result.Beta = c.Covariance / c.VarianceA; } results.Add(result); } return(results); }
// CORRELATION COEFFICIENT public static IEnumerable <CorrResult> GetCorrelation <TQuote>( IEnumerable <TQuote> historyA, IEnumerable <TQuote> historyB, int lookbackPeriod) where TQuote : IQuote { // clean quotes List <TQuote> historyListA = historyA.Sort(); List <TQuote> historyListB = historyB.Sort(); // validate parameters ValidateCorrelation(historyA, historyB, lookbackPeriod); // initialize List <CorrResult> results = new List <CorrResult>(); // roll through history for interim data for (int i = 0; i < historyListA.Count; i++) { TQuote a = historyListA[i]; TQuote b = historyListB[i]; int index = i + 1; if (a.Date != b.Date) { throw new BadHistoryException(nameof(historyA), a.Date, "Date sequence does not match. Correlation requires matching dates in provided histories."); } CorrResult r = new CorrResult { Date = a.Date }; // compute correlation if (index >= lookbackPeriod) { decimal sumPriceA = 0m; decimal sumPriceB = 0m; decimal sumPriceA2 = 0m; decimal sumPriceB2 = 0m; decimal sumPriceAB = 0m; for (int p = index - lookbackPeriod; p < index; p++) { TQuote qa = historyListA[p]; TQuote qb = historyListB[p]; sumPriceA += qa.Close; sumPriceB += qb.Close; sumPriceA2 += qa.Close * qa.Close; sumPriceB2 += qb.Close * qb.Close; sumPriceAB += qa.Close * qb.Close; } decimal avgA = sumPriceA / lookbackPeriod; decimal avgB = sumPriceB / lookbackPeriod; decimal avgA2 = sumPriceA2 / lookbackPeriod; decimal avgB2 = sumPriceB2 / lookbackPeriod; decimal avgAB = sumPriceAB / lookbackPeriod; r.VarianceA = avgA2 - avgA * avgA; r.VarianceB = avgB2 - avgB * avgB; r.Covariance = avgAB - avgA * avgB; r.Correlation = (r.VarianceA == 0 || r.VarianceB == 0) ? null : r.Covariance / (decimal)Math.Sqrt((double)(r.VarianceA * r.VarianceB)); r.RSquared = r.Correlation * r.Correlation; } results.Add(r); } return(results); }
// CORRELATION COEFFICIENT public static IEnumerable <CorrResult> GetCorrelation( IEnumerable <Quote> historyA, IEnumerable <Quote> historyB, int lookbackPeriod) { // clean quotes List <Quote> historyListA = Cleaners.PrepareHistory(historyA).ToList(); List <Quote> historyListB = Cleaners.PrepareHistory(historyB).ToList(); // validate parameters ValidateCorrelation(historyListA, historyListB, lookbackPeriod); // initialize List <CorrResult> results = new List <CorrResult>(); // roll through history for interim data for (int i = 0; i < historyListA.Count; i++) { Quote a = historyListA[i]; Quote b = historyListB[i]; if (a.Date != b.Date) { throw new BadHistoryException( "Date sequence does not match. Correlation requires matching dates in provided histories."); } CorrResult result = new CorrResult { Index = (int)a.Index, Date = a.Date, PriceA = a.Close, PriceB = b.Close // other values calculated in class properties }; results.Add(result); } // compute correlation for (int i = lookbackPeriod - 1; i < results.Count; i++) { CorrResult r = results[i]; List <CorrResult> period = results .Where(x => x.Index > (r.Index - lookbackPeriod) && x.Index <= r.Index) .ToList(); decimal avgA = period.Select(x => x.PriceA).Average(); decimal avgB = period.Select(x => x.PriceB).Average(); decimal avgA2 = period.Select(x => x.PriceA2).Average(); decimal avgB2 = period.Select(x => x.PriceB2).Average(); decimal avgAB = period.Select(x => x.PriceAB).Average(); r.VarianceA = avgA2 - avgA * avgA; r.VarianceB = avgB2 - avgB * avgB; r.Covariance = avgAB - avgA * avgB; r.Correlation = r.Covariance / (decimal)Math.Sqrt((double)(r.VarianceA * r.VarianceB)); r.RSquared = r.Correlation * r.Correlation; } return(results); }
// CORRELATION COEFFICIENT public static IEnumerable <CorrResult> GetCorrelation( IEnumerable <Quote> historyA, IEnumerable <Quote> historyB, int lookbackPeriod) { // clean quotes List <Quote> historyListA = Cleaners.PrepareHistory(historyA).ToList(); List <Quote> historyListB = Cleaners.PrepareHistory(historyB).ToList(); // validate parameters ValidateCorrelation(historyA, historyB, lookbackPeriod); // initialize List <CorrResult> results = new List <CorrResult>(); // roll through history for interim data for (int i = 0; i < historyListA.Count; i++) { Quote a = historyListA[i]; Quote b = historyListB[i]; if (a.Date != b.Date) { throw new BadHistoryException( "Date sequence does not match. Correlation requires matching dates in provided histories."); } CorrResult r = new CorrResult { Index = (int)a.Index, Date = a.Date, PriceA = a.Close, PriceB = b.Close, PriceA2 = a.Close * a.Close, PriceB2 = b.Close * b.Close, PriceAB = a.Close * b.Close }; results.Add(r); // compute correlation if (i + 1 >= lookbackPeriod) { decimal sumPriceA = 0m; decimal sumPriceB = 0m; decimal sumPriceA2 = 0m; decimal sumPriceB2 = 0m; decimal sumPriceAB = 0m; for (int p = r.Index - lookbackPeriod; p < r.Index; p++) { CorrResult d = results[p]; sumPriceA += d.PriceA; sumPriceB += d.PriceB; sumPriceA2 += d.PriceA2; sumPriceB2 += d.PriceB2; sumPriceAB += d.PriceAB; } decimal avgA = sumPriceA / lookbackPeriod; decimal avgB = sumPriceB / lookbackPeriod; decimal avgA2 = sumPriceA2 / lookbackPeriod; decimal avgB2 = sumPriceB2 / lookbackPeriod; decimal avgAB = sumPriceAB / lookbackPeriod; r.VarianceA = avgA2 - avgA * avgA; r.VarianceB = avgB2 - avgB * avgB; r.Covariance = avgAB - avgA * avgB; r.Correlation = r.Covariance / (decimal)Math.Sqrt((double)(r.VarianceA * r.VarianceB)); r.RSquared = r.Correlation * r.Correlation; } } return(results); }