OptimizationStatistics¶
Statistical utilities for analyzing optimization results.
Overview¶
OptimizationStatistics provides statistical functions for analyzing and comparing backtest results: confidence intervals, significance tests, correlations, and reporting.
Header¶
Helper Functions (detail namespace)¶
namespace detail {
double mean(const std::vector<double>& data);
double variance(const std::vector<double>& data);
double stddev(const std::vector<double>& data);
}
Basic statistical functions. Returns 0.0 for empty data.
extractMetric¶
template <typename ParamsT>
std::vector<double> extractMetric(
const std::vector<OptimizationResult<ParamsT>>& results,
RankMetric metric);
Extract specified metric values from all results.
Example:
auto sharpes = extractMetric(results, RankMetric::SharpeRatio);
double avgSharpe = detail::mean(sharpes);
Class Definition¶
template <typename ParamsT, typename GridT>
class OptimizationStatistics {
public:
struct ConfidenceInterval {
double lower;
double median;
double upper;
};
static double permutationTest(
const std::vector<double>& group1,
const std::vector<double>& group2,
size_t numPermutations = 10000,
std::uint64_t seed = 42u);
static double correlation(
const std::vector<double>& x,
const std::vector<double>& y);
static ConfidenceInterval bootstrapCI(
const std::vector<double>& data,
double confidenceLevel = 0.95,
size_t numSamples = 10000,
std::uint64_t seed = 42u);
static void printSummary(
const std::vector<OptimizationResult<ParamsT>>& results);
static bool generateReport(
const std::vector<OptimizationResult<ParamsT>>& results,
const std::filesystem::path& outputPath);
};
Methods¶
permutationTest¶
static double permutationTest(
const std::vector<double>& group1,
const std::vector<double>& group2,
size_t numPermutations = 10000,
std::uint64_t seed = 42u);
Two-sample permutation test for comparing group means. Returns a p-value,
always strictly greater than zero: the p-value is (extreme + 1) /
(numPermutations + 1), the standard add-one correction (the observed
arrangement is itself one of the possible outcomes under the null).
The resample is seeded (default 42, matching
whitesRealityCheck), so the
same inputs always return the same p-value. Pass a different seed to draw
an independent resample.
Example:
// Compare two parameter configurations
std::vector<double> configA = {1.2, 1.5, 1.3};
std::vector<double> configB = {0.8, 0.9, 0.7};
double pValue = Stats::permutationTest(configA, configB);
// pValue < 0.05 suggests significant difference
correlation¶
Pearson correlation coefficient between two vectors. Returns value in [-1, 1].
Example:
auto sharpes = extractMetric(results, RankMetric::SharpeRatio);
auto returns = extractMetric(results, RankMetric::TotalReturn);
double r = Stats::correlation(sharpes, returns);
bootstrapCI¶
static ConfidenceInterval bootstrapCI(
const std::vector<double>& data,
double confidenceLevel = 0.95,
size_t numSamples = 10000,
std::uint64_t seed = 42u);
Bootstrap confidence interval for the mean. confidenceLevel is clamped to
[0, 1]; numSamples == 0 returns {0.0, 0.0, 0.0} instead of resampling.
Seeded the same way as permutationTest above: deterministic by default,
override seed for an independent resample.
Example:
auto sharpes = extractMetric(results, RankMetric::SharpeRatio);
auto ci = Stats::bootstrapCI(sharpes, 0.95);
// ci.lower, ci.median, ci.upper
printSummary¶
Print optimization summary to log. Shows total combinations, mean/stddev Sharpe, and best result details.
generateReport¶
static bool generateReport(
const std::vector<OptimizationResult<ParamsT>>& results,
const std::filesystem::path& outputPath);
Generate a Markdown report with a top-10 results table and statistics.
Returns true on success; false (and an error logged) if outputPath
could not be opened for writing, e.g. a nonexistent parent directory.
Example¶
using Stats = OptimizationStatistics<MAParams, MAGrid>;
// Run optimization
auto results = optimizer.runLocal();
// Quick summary
Stats::printSummary(results);
// Full report
Stats::generateReport(results, "optimization_report.md");
// Statistical analysis
auto sharpes = extractMetric(results, RankMetric::SharpeRatio);
auto ci = Stats::bootstrapCI(sharpes);
std::cout << "95% CI: [" << ci.lower << ", " << ci.upper << "]\n";
// Compare top vs bottom half
auto ranked = optimizer.rankResults(results, RankMetric::SharpeRatio);
size_t mid = ranked.size() / 2;
std::vector<double> topHalf, bottomHalf;
for (size_t i = 0; i < mid; ++i) {
topHalf.push_back(ranked[i].sharpeRatio());
bottomHalf.push_back(ranked[mid + i].sharpeRatio());
}
double pValue = Stats::permutationTest(topHalf, bottomHalf);