2026-09-09 01:19:31 +03:00 | | | //+------------------------------------------------------------------+
|
2026-09-10 16:43:28 +03:00 | | | //| BenchmarkStatistics.mqh |
|
2026-09-16 15:37:55 +03:00 | | | //| Copyright 2026, MetaQuotes Ltd. |
|
2026-09-10 16:43:28 +03:00 | | | //| www.mql5.com |
|
2026-09-09 01:19:31 +03:00 | | | //+------------------------------------------------------------------+
|
| | | #ifndef REQUEST_LATENCY_LAB_LEGACY_BENCHMARK_STATISTICS_MQH
|
| | | #define REQUEST_LATENCY_LAB_LEGACY_BENCHMARK_STATISTICS_MQH
|
2026-09-12 22:14:24 +03:00 | | | //+-------------------------------------------------------------------+
|
| | | //| Исходные реализации (без изменений алгоритма) — для проверки |
|
| | | //| согласованности адаптированных функций с исходным кодом (DEP-02). |
|
| | | //| Исходное поведение на пустом входе: возврат 0. |
|
| | | //+-------------------------------------------------------------------+
|
| | | double LegacyMinValue(const double &arr[], const int count)
|
2026-09-09 01:19:31 +03:00 | | | {
|
2026-09-12 22:14:24 +03:00 | | | if(count <= 0)
|
2026-09-10 16:43:28 +03:00 | | | return(0);
|
2026-09-12 22:14:24 +03:00 | | | double m = arr[0];
|
| | | for(int i = 1; i < count; i++)
|
| | | if(arr[i] < m)
|
| | | m = arr[i];
|
2026-09-10 16:43:28 +03:00 | | | return(m);
|
2026-09-09 01:19:31 +03:00 | | | }
|
2026-09-12 22:14:24 +03:00 | | | //+------------------------------------------------------------------+
|
| | | //| Максимум первых count элементов (исходная реализация) |
|
| | | //+------------------------------------------------------------------+
|
| | | double LegacyMaxValue(const double &arr[], const int count)
|
2026-09-09 01:19:31 +03:00 | | | {
|
2026-09-12 22:14:24 +03:00 | | | if(count <= 0)
|
2026-09-10 16:43:28 +03:00 | | | return(0);
|
2026-09-12 22:14:24 +03:00 | | | double m = arr[0];
|
| | | for(int i = 1; i < count; i++)
|
| | | if(arr[i] > m)
|
| | | m = arr[i];
|
2026-09-10 16:43:28 +03:00 | | | return(m);
|
2026-09-09 01:19:31 +03:00 | | | }
|
2026-09-12 22:14:24 +03:00 | | | //+------------------------------------------------------------------+
|
| | | //| Среднее первых count элементов (исходная реализация) |
|
| | | //+------------------------------------------------------------------+
|
| | | double LegacyAvgValue(const double &arr[], const int count)
|
2026-09-09 01:19:31 +03:00 | | | {
|
2026-09-12 22:14:24 +03:00 | | | if(count <= 0)
|
2026-09-10 16:43:28 +03:00 | | | return(0);
|
2026-09-12 22:14:24 +03:00 | | | double s = 0;
|
| | | for(int i = 0; i < count; i++)
|
| | | s += arr[i];
|
| | | return(s / count);
|
2026-09-09 01:19:31 +03:00 | | | }
|
| | | //+------------------------------------------------------------------+
|
| | | //| Перцентиль p (0..100) по первым count элементам массива. |
|
| | | //| Работает на КОПИИ данных (ArraySort не портит исходный массив). |
|
| | | //| Линейная интерполяция между соседними отсортированными. |
|
| | | //+------------------------------------------------------------------+
|
2026-09-12 22:14:24 +03:00 | | | double LegacyPercentile(const double &arr[], const int count, const double p)
|
2026-09-09 01:19:31 +03:00 | | | {
|
2026-09-12 22:14:24 +03:00 | | | if(count <= 0)
|
2026-09-10 16:43:28 +03:00 | | | return(0);
|
2026-09-12 22:14:24 +03:00 | | | if(count == 1)
|
2026-09-10 16:43:28 +03:00 | | | return(arr[0]);
|
2026-09-09 01:19:31 +03:00 | | | double tmp[];
|
2026-09-12 22:14:24 +03:00 | | | if(ArrayResize(tmp, count) != count)
|
2026-09-10 16:43:28 +03:00 | | | return(0);
|
2026-09-12 22:14:24 +03:00 | | | for(int i = 0; i < count; i++)
|
| | | tmp[i] = arr[i];
|
2026-09-09 01:19:31 +03:00 | | | ArraySort(tmp);
|
2026-09-12 22:14:24 +03:00 | | | const double pos = p / 100.0 * (count - 1);
|
| | | const int lo = (int)MathFloor(pos);
|
| | | const int hi = (int)MathCeil(pos);
|
| | | if(lo == hi)
|
2026-09-10 16:43:28 +03:00 | | | return(tmp[lo]);
|
2026-09-12 22:14:24 +03:00 | | | const double frac = pos - lo;
|
| | | return(tmp[lo] + (tmp[hi] - tmp[lo]) * frac);
|
2026-09-09 01:19:31 +03:00 | | | }
|
| | | //+------------------------------------------------------------------+
|
| | | //| Адаптированные проверяемые версии для лаборатории. |
|
| | | //| Возвращают false при пустой выборке, нулевом count, некорректном |
|
| | | //| p или невозможности выделить память; значение не выдумывается. |
|
| | | //+------------------------------------------------------------------+
|
2026-09-12 22:14:24 +03:00 | | | bool LabMinValue(const double &arr[], const int count, double &result)
|
2026-09-09 01:19:31 +03:00 | | | {
|
2026-09-12 22:14:24 +03:00 | | | if(count <= 0)
|
2026-09-10 16:43:28 +03:00 | | | return(false);
|
2026-09-12 22:14:24 +03:00 | | | result = arr[0];
|
| | | for(int i = 1; i < count; i++)
|
| | | if(arr[i] < result)
|
| | | result = arr[i];
|
2026-09-10 16:43:28 +03:00 | | | return(true);
|
2026-09-09 01:19:31 +03:00 | | | }
|
2026-09-12 22:14:24 +03:00 | | | //+------------------------------------------------------------------+
|
| | | //| Максимум выборки (адаптированная версия) |
|
| | | //+------------------------------------------------------------------+
|
| | | bool LabMaxValue(const double &arr[], const int count, double &result)
|
2026-09-09 01:19:31 +03:00 | | | {
|
2026-09-12 22:14:24 +03:00 | | | if(count <= 0)
|
2026-09-10 16:43:28 +03:00 | | | return(false);
|
2026-09-12 22:14:24 +03:00 | | | result = arr[0];
|
| | | for(int i = 1; i < count; i++)
|
| | | if(arr[i] > result)
|
| | | result = arr[i];
|
2026-09-10 16:43:28 +03:00 | | | return(true);
|
2026-09-09 01:19:31 +03:00 | | | }
|
2026-09-12 22:14:24 +03:00 | | | //+------------------------------------------------------------------+
|
| | | //| Среднее выборки (адаптированная версия) |
|
| | | //+------------------------------------------------------------------+
|
| | | bool LabAvgValue(const double &arr[], const int count, double &result)
|
2026-09-09 01:19:31 +03:00 | | | {
|
2026-09-12 22:14:24 +03:00 | | | if(count <= 0)
|
2026-09-10 16:43:28 +03:00 | | | return(false);
|
2026-09-12 22:14:24 +03:00 | | | double s = 0;
|
| | | for(int i = 0; i < count; i++)
|
| | | s += arr[i];
|
| | | result = s / count;
|
2026-09-10 16:43:28 +03:00 | | | return(true);
|
2026-09-09 01:19:31 +03:00 | | | }
|
| | | //+------------------------------------------------------------------+
|
| | | //| Проверяемый перцентиль. p задан явно в шкале 0..100 (допустим |
|
| | | //| дробный p, например 99.9). Алгоритм совпадает с LegacyPercentile |
|
| | | //| на допустимых входах. |
|
| | | //+------------------------------------------------------------------+
|
2026-09-12 22:14:24 +03:00 | | | bool LabPercentile(const double &arr[], const int count,
|
| | | const double p0_100, double &result)
|
2026-09-09 01:19:31 +03:00 | | | {
|
2026-09-12 22:14:24 +03:00 | | | if(count <= 0)
|
2026-09-10 16:43:28 +03:00 | | | return(false);
|
2026-09-12 22:14:24 +03:00 | | | if(p0_100 < 0.0 || p0_100 > 100.0)
|
2026-09-10 16:43:28 +03:00 | | | return(false);
|
2026-09-12 22:14:24 +03:00 | | | if(count == 1)
|
2026-09-09 01:19:31 +03:00 | | | {
|
2026-09-12 22:14:24 +03:00 | | | result = arr[0];
|
2026-09-10 16:43:28 +03:00 | | | return(true);
|
2026-09-09 01:19:31 +03:00 | | | }
|
| | | double tmp[];
|
2026-09-12 22:14:24 +03:00 | | | if(ArrayResize(tmp, count) != count)
|
2026-09-10 16:43:28 +03:00 | | | return(false);
|
2026-09-12 22:14:24 +03:00 | | | for(int i = 0; i < count; i++)
|
| | | tmp[i] = arr[i];
|
2026-09-09 01:19:31 +03:00 | | | ArraySort(tmp);
|
2026-09-12 22:14:24 +03:00 | | | const double pos = p0_100 / 100.0 * (count - 1); // h=(n-1)*p
|
| | | const int lo = (int)MathFloor(pos);
|
| | | const int hi = (int)MathCeil(pos);
|
| | | if(lo == hi)
|
2026-09-09 01:19:31 +03:00 | | | {
|
2026-09-12 22:14:24 +03:00 | | | result = tmp[lo];
|
2026-09-10 16:43:28 +03:00 | | | return(true);
|
2026-09-09 01:19:31 +03:00 | | | }
|
2026-09-12 22:14:24 +03:00 | | | const double frac = pos - lo;
|
| | | result = tmp[lo] + (tmp[hi] - tmp[lo]) * frac; // линейная интерполяция
|
2026-09-10 16:43:28 +03:00 | | | return(true);
|
2026-09-09 01:19:31 +03:00 | | | }
|
| | | //+------------------------------------------------------------------+
|
| | | //| Выборочное стандартное отклонение (делитель n-1). |
|
| | | //| n=0 и n=1 -> false (значение пустое). |
|
| | | //+------------------------------------------------------------------+
|
2026-09-12 22:14:24 +03:00 | | | bool LabStdDev(const double &arr[], const int count, double &result)
|
2026-09-09 01:19:31 +03:00 | | | {
|
2026-09-12 22:14:24 +03:00 | | | if(count <= 1)
|
2026-09-10 16:43:28 +03:00 | | | return(false);
|
2026-09-12 22:14:24 +03:00 | | | double mean = 0;
|
| | | if(!LabAvgValue(arr, count, mean))
|
2026-09-10 16:43:28 +03:00 | | | return(false);
|
2026-09-12 22:14:24 +03:00 | | | double acc = 0;
|
| | | for(int i = 0; i < count; i++)
|
2026-09-09 01:19:31 +03:00 | | | {
|
2026-09-12 22:14:24 +03:00 | | | const double d = arr[i] - mean;
|
| | | acc += d * d;
|
2026-09-09 01:19:31 +03:00 | | | }
|
2026-09-12 22:14:24 +03:00 | | | result = MathSqrt(acc / (count - 1));
|
2026-09-10 16:43:28 +03:00 | | | return(true);
|
2026-09-09 01:19:31 +03:00 | | | }
|
| | |
|
2026-09-12 22:14:24 +03:00 | | | #endif // REQUEST_LATENCY_LAB_LEGACY_BENCHMARK_STATISTICS_MQH
|
| | | //+------------------------------------------------------------------+
|