namespace KLHZ.Trader.Core.Math.Declisions.Utils { public static class ShapeAreaCalculator { // Метод для расчёта площади треугольника public static double CalculateTriangleArea( DateTime pointA_X, decimal pointA_Y, DateTime pointB_X, decimal pointB_Y, DateTime pointC_X, decimal pointC_Y) { // Определяем самую позднюю точку DateTime latestPoint = new[] { pointA_X, pointB_X, pointC_X }.Max(); // Смещённые координаты double offsetA = GetOffsetInSeconds(latestPoint, pointA_X); double offsetB = GetOffsetInSeconds(latestPoint, pointB_X); double offsetC = GetOffsetInSeconds(latestPoint, pointC_X); // Расчёт расстояний double sideAB = DistanceBetweenPoints(offsetA, (double)pointA_Y, offsetB, (double)pointB_Y); double sideBC = DistanceBetweenPoints(offsetB, (double)pointB_Y, offsetC, (double)pointC_Y); double sideCA = DistanceBetweenPoints(offsetC, (double)pointC_Y, offsetA, (double)pointA_Y); // Формула Герона double semiPerimeter = (sideAB + sideBC + sideCA) / 2; return System.Math.Sqrt(semiPerimeter * (semiPerimeter - sideAB) * (semiPerimeter - sideBC) * (semiPerimeter - sideCA)); } // Метод для расчёта площади четырёхугольника public static double CalculateQuadrilateralArea( DateTime pointA_X, decimal pointA_Y, DateTime pointB_X, decimal pointB_Y, DateTime pointC_X, decimal pointC_Y, DateTime pointD_X, decimal pointD_Y) { // Определяем самую позднюю точку DateTime latestPoint = new[] { pointA_X, pointB_X, pointC_X, pointD_X }.Max(); // Смещённые координаты double offsetA = GetOffsetInSeconds(latestPoint, pointA_X); double offsetB = GetOffsetInSeconds(latestPoint, pointB_X); double offsetC = GetOffsetInSeconds(latestPoint, pointC_X); double offsetD = GetOffsetInSeconds(latestPoint, pointD_X); // Суммируем площади двух треугольников double firstTriangleArea = CalculateTriangleArea(pointA_X, pointA_Y, pointB_X, pointB_Y, pointD_X, pointD_Y); double secondTriangleArea = CalculateTriangleArea(pointB_X, pointB_Y, pointC_X, pointC_Y, pointD_X, pointD_Y); return firstTriangleArea + secondTriangleArea; } // Вспомогательные методы // Конвертация разницы времён в секунды private static double GetOffsetInSeconds(DateTime referencePoint, DateTime targetPoint) { return (referencePoint - targetPoint).TotalSeconds; } // Евклидово расстояние между двумя точками private static double DistanceBetweenPoints(double x1, double y1, double x2, double y2) { return System.Math.Sqrt(System.Math.Pow(x2 - x1, 2) + System.Math.Pow(y2 - y1, 2)); } public static bool TryGetAreasRelation(DateTime[] times, decimal[] values, decimal currentValue, TimeSpan boundTimeSpan, out double relation) { var upArea = 0d; var downArea = 0d; var startTime = times[times.Length - 1]; for (int i = 1; i < times.Length - 2; i++) { var k = values.Length - i; if (startTime - times[k] > boundTimeSpan) { break; } var point = (double)(values[k] - currentValue); var time = times[k]; var timePrev = times[k - 1]; var dt = (time - timePrev).TotalSeconds; var ar = dt * point; if (ar > 0) { upArea += ar; } else { downArea += System.Math.Abs(ar); } } var area = downArea + upArea; relation = area != 0 ? (double)upArea / area * 100 : 0; return area != 0; } } }