using KLHZ.Trader.Core.Contracts.Declisions.Dtos; namespace KLHZ.Trader.Core.Math.Declisions.Utils { public static class Statistics { public static decimal Mean(this CachedValue[] values) { return values.Sum(x => x.Count) / values.Length; } public static decimal Mean2(this CachedValue[] values) { return values.Sum(x => x.Price) / values.Length; } private static (decimal mean, decimal std) CaclSigma(decimal[] values) { var mean = values.Sum() / values.Length; var data = new decimal[values.Length]; Array.Copy(values, data, data.Length); for (int i = 0; i < data.Length; i++) { var v = data[i] - mean; data[i] = v * v; } var std = System.Math.Pow((double)(data.Sum() / (data.Length - 1)), 0.5); return (mean, (decimal)std); } public static decimal[] ClearNSigmaReqursive(decimal[] values, int depth = 0, int sigmasCount = 3) { if (values.Length <= 1 || depth > 10) return values; var sigmaRes = CaclSigma(values); var std = sigmaRes.std; var mean = sigmaRes.mean; var forRes = new List(); var _3std = sigmasCount * std; foreach (var v in values) { if (System.Math.Abs(mean - v) < _3std) { forRes.Add(v); } } if (forRes.Count != values.Length) { return ClearNSigmaReqursive(forRes.ToArray(), depth + 1); } else { return forRes.ToArray(); } } public static bool TryCalcTimeWindowsDiff(this CachedValue[] values, TimeSpan boundLeft, TimeSpan boundRight, Func fieldSelector, bool calcMean, out decimal result) { result = default; if (values.Length > 1) { var shiftTimeR = values.Last().Time - boundRight; var shiftTimeL = values.Last().Time - boundLeft; var valuesOld = values.Where(b => b.Time < shiftTimeR && b.Time >= shiftTimeL).ToArray(); var valuesNew = values.Where(b => b.Time >= shiftTimeR).ToArray(); if (valuesOld.Length > 0 && valuesNew.Length > 0) { var valNew = valuesNew.Sum(fieldSelector); var valOld = valuesOld.Sum(fieldSelector); if (calcMean) { valNew = valNew / valuesNew.Length; valOld = valOld / valuesOld.Length; } result = valNew - valOld; return true; } } return false; } public static bool TryCalcPirsonCorrelation(this CachedValue[] values, TimeSpan period, out decimal result) { result = default; if (values.Any()) { var shiftTimeDiffs1 = values.Last().Time - period; values = values.Where(b => b.Time >= shiftTimeDiffs1).ToArray(); if (values.Any()) { var tradevolume_diffMean = values.Mean(); var dprice_diffMean = values.Mean2(); var sum1 = (double)values.Sum(d => (d.Value2 - tradevolume_diffMean) * (d.Value - dprice_diffMean)); var sum2 = values.Sum(d => (d.Value2 - tradevolume_diffMean) * (d.Value2 - tradevolume_diffMean)); var sum3 = values.Sum(d => (d.Value - dprice_diffMean) * (d.Value - dprice_diffMean)); if (sum2 != 0 && sum3 != 0) { result = (decimal)(sum1 / System.Math.Sqrt((double)(sum2 * sum3))); return true; } } } return false; } } }