namespace QuanTAlib.Tests; public class CovarianceValidationTests { [Fact] public void Covariance_Matches_ManualCalculation() { // Arrange const int period = 10; var cov = new Covariance(period, isPopulation: false); var gbmX = new GBM(startPrice: 100, mu: 0.05, sigma: 0.2, seed: 123); var gbmY = new GBM(startPrice: 100, mu: 0.05, sigma: 0.2, seed: 456); double[] x = new double[100]; double[] y = new double[100]; for (int i = 0; i < 100; i++) { x[i] = gbmX.Next().Close; y[i] = gbmY.Next().Close; cov.Update(x[i], y[i]); if (i >= period - 1) { // Manual calculation for last 'period' items double sumX = 0; double sumY = 0; for (int j = 0; j < period; j++) { sumX += x[i - j]; sumY += y[i - j]; } double meanX = sumX / period; double meanY = sumY / period; double sumProd = 0; for (int j = 0; j < period; j++) { sumProd += (x[i - j] - meanX) * (y[i - j] - meanY); } double expected = sumProd / (period - 1); Assert.Equal(expected, cov.Last.Value, precision: 8); } } } [Fact] public void Covariance_Population_Matches_ManualCalculation() { // Arrange int period = 10; var cov = new Covariance(period, isPopulation: true); var gbmX = new GBM(startPrice: 100, mu: 0.05, sigma: 0.2, seed: 456); var gbmY = new GBM(startPrice: 100, mu: 0.05, sigma: 0.2, seed: 789); double[] x = new double[100]; double[] y = new double[100]; for (int i = 0; i < 100; i++) { x[i] = gbmX.Next().Close; y[i] = gbmY.Next().Close; cov.Update(x[i], y[i]); if (i >= period - 1) { // Manual calculation for last 'period' items double sumX = 0; double sumY = 0; for (int j = 0; j < period; j++) { sumX += x[i - j]; sumY += y[i - j]; } double meanX = sumX / period; double meanY = sumY / period; double sumProd = 0; for (int j = 0; j < period; j++) { sumProd += (x[i - j] - meanX) * (y[i - j] - meanY); } double expected = sumProd / period; Assert.Equal(expected, cov.Last.Value, precision: 8); } } } }