You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Boutquin.Trading.Recipes project: IBacktestDataset, BacktestDataset, BacktestDatasetBuilder, BacktestDatasetSpec, and FakeBacktestDataset — provides the bridge between the backtest engine and the Boutquin.MarketDataIDataPipeline for production data workflows.
Nine new covariance estimators completing the four-tier lineup (13 total):
Linear shrinkage: LedoitWolfConstantCorrelationEstimator (average-correlation target — recommended default for equities), LedoitWolfSingleFactorEstimator (market factor target), OracleApproximatingShrinkageEstimator (OAS, Chen et al. 2010)
Nonlinear/denoising: QuadraticInverseShrinkageEstimator (per-eigenvalue shrinkage, gold standard for N ≥ 10), TracyWidomDenoisedCovarianceEstimator (sharper finite-sample threshold, preferred when T/N < 5)
CorrelationAnalyzer.Analyze now delegates covariance computation to Boutquin.Numerics.Statistics.SampleCovarianceEstimator, removing the inline two-pass covariance loop (~25 lines). RollingCorrelation now delegates entirely to Boutquin.Numerics.Statistics.PearsonCorrelation.Rolling, removing ~30 lines of inline rolling-window arithmetic.
MonteCarloSimulator.Run now delegates to Boutquin.Numerics.MonteCarlo.BootstrapMonteCarloEngine, removing the inline bootstrap loop, per-simulation mean/std computation, and private Percentile helper (~30 lines).
SampleCovarianceEstimator, ExponentiallyWeightedCovarianceEstimator, LedoitWolfShrinkageEstimator, DenoisedCovarianceEstimator, and DetonedCovarianceEstimator now delegate to Boutquin.Numerics.Statistics, removing ~900 lines of duplicated math.
PrincipalPortfolioAnalyzer, EffectiveNumberOfBets, and PcaRegimeSignal now use Boutquin.Numerics.LinearAlgebra.JacobiEigenDecomposition, removing ~400 lines of inline Jacobi sweeps.
FactorRegressor now uses Boutquin.Numerics.Solvers.OrdinaryLeastSquares<decimal> (Householder QR, 28-digit accuracy) instead of hand-rolled Gaussian elimination in double.
DecimalArrayExtensions.ValueAtRisk now delegates to Boutquin.Numerics.Distributions.InverseNormal.Evaluate, removing the inline 52-line Abramowitz & Stegun rational approximation.
MinimumVarianceConstruction and MeanVarianceConstruction now use Boutquin.Numerics.Solvers.ActiveSetQpSolver (Cholesky active-set with correct KKT cross-covariance handling) instead of the hand-rolled CholeskyQpSolver, which had a bug: it ignored the Σ_FC * w_C cross-covariance adjustment when solving the free-variable sub-problem after fixing weights at bounds, causing constrained solutions to be suboptimal.
MaximumDiversificationConstruction likewise migrated to ActiveSetQpSolver.
DecimalArrayExtensions.Skewness and Kurtosis now delegate to Boutquin.Numerics.Statistics.SampleSkewness.Compute and SampleExcessKurtosis.Compute, removing ~40 lines of duplicated math.
RollingWindow<T> is now consumed from Boutquin.Numerics.Collections instead of the local Domain/Helpers copy.
Boutquin.Numerics version bumped to 1.1.0.
Fixed
Collinear factor inputs to FactorRegressor now correctly throw CalculationException instead of OverflowException. The fix is in Boutquin.Numerics.LinearAlgebra.Internal.HouseholderQr<T>.BuildXtXInverse, which now converts decimal arithmetic overflow to InvalidOperationException.
MinimumVarianceConstruction constrained QP now finds the true global minimum. The old CholeskyQpSolver ignored the KKT cross-covariance term Σ_FC * w_C when fixed-bound variables were present, causing the free-variable sub-problem to be solved against an incorrect RHS and producing a higher-variance portfolio than necessary. ActiveSetQpSolver accounts for the full KKT system and matches scipy SLSQP to float64 precision.
Removed
Asset value object removed from Boutquin.Trading.Domain.ValueObjects; replaced by Boutquin.MarketData.Abstractions.ReferenceData.Symbol. Both are readonly record struct with a Ticker property; Symbol is the canonical type at the data-access layer.
AssetClassCode, ContinentCode, CountryCode, CurrencyCode, DividendType, ExchangeCode, SecuritySymbolStandard, and TimeZoneCode enums removed from Boutquin.Trading.Domain.Enums. All eight are now consumed from Boutquin.MarketData.Abstractions.ReferenceData, which is the canonical source. Boutquin.Trading.Domain.Enums retains only backtest-specific enums (TradeAction, OrderType, SignalType, EconomicRegime, RebalancingFrequency, AccountType, HoldingPeriod, CanadianProvince, UsState).
FamaFrenchDataset enum removed; the IDataPipeline architecture uses Boutquin.MarketData.Abstractions.ReferenceData.FactorDatasetId (a string-typed record struct) for all factor dataset identification.
MarketDataNotFoundException, MarketDataProcessingException, MarketDataRetrievalException, MarketDataStorageException removed from Boutquin.Trading.Domain.Exceptions; canonical versions live in Boutquin.MarketData.Abstractions.Exceptions. Also removed dead-code exceptions SymbolReaderException, NegativeBusinessDaysPerYearException, and NegativeRiskFreeRateException (zero usages).
Domain.Data.MarketData and Domain.Data.FxRateData records removed; backtest infrastructure uses Boutquin.MarketData.Abstractions.Records.Bar and FxRate directly.
Boutquin.Trading.Domain.Helpers.CholeskyQpSolver removed; replaced by Boutquin.Numerics.Solvers.ActiveSetQpSolver.
Boutquin.Trading.Domain.Helpers.RollingWindow<T> removed; replaced by Boutquin.Numerics.Collections.RollingWindow<T>.