feat(family-15): add 17 risk/performance metrics (#54)
* feat(family-15): add 17 risk/performance metrics Implements Family 15 pragmatically as standard `Indicator`s instead of a separate `wickra-metrics` crate. Input is scalar `f64` per bar — period return, equity sample, or per-trade P&L depending on the metric. Scalar `Indicator<f64>` (14): - SharpeRatio(period, risk_free) - SortinoRatio(period, mar) - CalmarRatio(period) - OmegaRatio(period, threshold) - MaxDrawdown(period) — rolling, peak-to-trough - AverageDrawdown(period) - DrawdownDuration — cumulative, bars under water (u32 output) - PainIndex(period) - ValueAtRisk(period, confidence) - ConditionalValueAtRisk(period, confidence) - ProfitFactor(period) - GainLossRatio(period) - RecoveryFactor — cumulative, net return / max drawdown - KellyCriterion(period) Two-series `Indicator<(f64, f64)>` for (asset, benchmark) returns (3): - TreynorRatio(period, risk_free) - InformationRatio(period) - Alpha(period, risk_free) — Jensen / CAPM Touchpoints: - 17 new files under `crates/wickra-core/src/indicators/`. - `mod.rs` + `lib.rs` re-exports. - Python bindings (`bindings/python/src/lib.rs`, `__init__.py`). - Node bindings (`bindings/node/src/lib.rs`, `index.js`). - WASM bindings (`bindings/wasm/src/lib.rs`). - Fuzz: scalar metrics appended to `indicator_update.rs`; new `indicator_update_pair.rs` fuzz target for `(f64, f64)` indicators. - Python tests: SCALAR + new PAIR parameter lists in `test_new_indicators.py`, reference-value cases in `test_known_values.py`. - Node tests: scalar factories + new pair-factory block in `bindings/node/__tests__/indicators.test.js`. - Benches: 5 Family-15 benches added in `crates/wickra/benches/indicators.rs`. - Docs: README family-table row + counter (71 -> 88), CHANGELOG entry under [Unreleased]. Note: Family 12 (statistik-regression, PR #51) introduces `node_pair_indicator!` and `wasm_pair_indicator!` macros for Pearson / Beta / Spearman. Family 15 needs the same pair-input pattern but Family 12 is not yet in main, so the three pair wrappers below are written by hand in this PR. When PR #51 lands, the trivial merge-conflict is resolved by keeping the macros from Family 12 and re-using them for Treynor / IR / Alpha (drop the three handwritten wrappers). cargo check --workspace --all-features: green. * fix(family-15): satisfy clippy doc_markdown / if_not_else / digit_grouping * fix(family-15): unused TreynorRatio import, duplicate pairFactories, _eq_nan inf handling * fix(family-15): node eq() handles matching infinities for ratio indicators * test(family-15): cover cold paths flagged by codecov patch
This commit is contained in:
@@ -20,22 +20,23 @@ use criterion::{criterion_group, criterion_main, BenchmarkId, Criterion, Through
|
||||
use std::hint::black_box;
|
||||
use wickra::{
|
||||
AccelerationBands, AdOscillator, AdaptiveCycle, Adxr, Alma, AnchoredVwap, Atr, AtrBands,
|
||||
Autocorrelation, BatchExt, BollingerBands, Camarilla, Candle, CenterOfGravity, ClassicPivots,
|
||||
CoefficientOfVariation, CyberneticCycle, Decycler, DecyclerOscillator, DemandIndex,
|
||||
DemarkPivots, DetrendedStdDev, Doji, DonchianStop, DoubleBollinger, EhlersStochastic, Ema,
|
||||
EmpiricalModeDecomposition, Engulfing, Fama, FibonacciPivots, FisherTransform,
|
||||
FractalChaosBands, Frama, GarmanKlassVolatility, Hammer, HeikinAshi, HiLoActivator,
|
||||
HilbertDominantCycle, HurstChannel, HurstExponent, Ichimoku, Indicator, InitialBalance,
|
||||
InstantaneousTrendline, InverseFisherTransform, Jma, Kst, Kurtosis, Kvo, LinRegChannel,
|
||||
MaEnvelope, MacdIndicator, Mama, MarketFacilitationIndex, McGinleyDynamic,
|
||||
MedianAbsoluteDeviation, MorningEveningStar, Nvi, Obv, OpeningRange, ParkinsonVolatility,
|
||||
PercentageTrailingStop, Pgo, Pvi, RSquared, RenkoTrailingStop, RogersSatchellVolatility,
|
||||
RoofingFilter, Rsi, Rvi, RviVolatility, Rwi, SineWave, Skewness, Sma, StandardError,
|
||||
StandardErrorBands, StarcBands, StepTrailingStop, Stochastic, SuperSmoother, TdCombo,
|
||||
TdCountdown, TdDeMarker, TdDifferential, TdLines, TdOpen, TdPressure, TdRangeProjection, TdRei,
|
||||
TdRiskLevel, TdSequential, TdSetup, ThreeInside, Tii, Tsv, TtmSqueeze, ValueArea, Variance,
|
||||
Vidya, VoltyStop, VolumeOscillator, VwapStdDevBands, Vzo, WaveTrend, WilliamsFractals, Wma,
|
||||
WoodiePivots, YangZhangVolatility, YoyoExit, ZigZag,
|
||||
Autocorrelation, BatchExt, BollingerBands, CalmarRatio, Camarilla, Candle, CenterOfGravity,
|
||||
ClassicPivots, CoefficientOfVariation, CyberneticCycle, Decycler, DecyclerOscillator,
|
||||
DemandIndex, DemarkPivots, DetrendedStdDev, Doji, DonchianStop, DoubleBollinger,
|
||||
EhlersStochastic, Ema, EmpiricalModeDecomposition, Engulfing, Fama, FibonacciPivots,
|
||||
FisherTransform, FractalChaosBands, Frama, GarmanKlassVolatility, Hammer, HeikinAshi,
|
||||
HiLoActivator, HilbertDominantCycle, HurstChannel, HurstExponent, Ichimoku, Indicator,
|
||||
InitialBalance, InstantaneousTrendline, InverseFisherTransform, Jma, Kst, Kurtosis, Kvo,
|
||||
LinRegChannel, MaEnvelope, MacdIndicator, Mama, MarketFacilitationIndex, MaxDrawdown,
|
||||
McGinleyDynamic, MedianAbsoluteDeviation, MorningEveningStar, Nvi, Obv, OpeningRange,
|
||||
ParkinsonVolatility, PercentageTrailingStop, Pgo, ProfitFactor, Pvi, RSquared,
|
||||
RenkoTrailingStop, RogersSatchellVolatility, RoofingFilter, Rsi, Rvi, RviVolatility, Rwi,
|
||||
SharpeRatio, SineWave, Skewness, Sma, StandardError, StandardErrorBands, StarcBands,
|
||||
StepTrailingStop, Stochastic, SuperSmoother, TdCombo, TdCountdown, TdDeMarker, TdDifferential,
|
||||
TdLines, TdOpen, TdPressure, TdRangeProjection, TdRei, TdRiskLevel, TdSequential, TdSetup,
|
||||
ThreeInside, Tii, Tsv, TtmSqueeze, ValueArea, ValueAtRisk, Variance, Vidya, VoltyStop,
|
||||
VolumeOscillator, VwapStdDevBands, Vzo, WaveTrend, WilliamsFractals, Wma, WoodiePivots,
|
||||
YangZhangVolatility, YoyoExit, ZigZag,
|
||||
};
|
||||
use wickra_data::csv::CandleReader;
|
||||
|
||||
@@ -408,6 +409,21 @@ fn benches(c: &mut Criterion) {
|
||||
bench_candle_input(c, "opening_range", &candles, || {
|
||||
OpeningRange::new(6).unwrap()
|
||||
});
|
||||
|
||||
// --- Family 15: Risk / Performance Metrics ---
|
||||
// Close-prices stand in for the equity curve / return stream; absolute
|
||||
// numbers aren't meaningful here — what matters is the per-update cost.
|
||||
bench_scalar(c, "sharpe_ratio", &closes, || {
|
||||
SharpeRatio::new(20, 0.0).unwrap()
|
||||
});
|
||||
bench_scalar(c, "max_drawdown", &closes, || MaxDrawdown::new(20).unwrap());
|
||||
bench_scalar(c, "profit_factor", &closes, || {
|
||||
ProfitFactor::new(20).unwrap()
|
||||
});
|
||||
bench_scalar(c, "calmar_ratio", &closes, || CalmarRatio::new(20).unwrap());
|
||||
bench_scalar(c, "value_at_risk", &closes, || {
|
||||
ValueAtRisk::new(50, 0.95).unwrap()
|
||||
});
|
||||
}
|
||||
|
||||
/// Variant of `bench_scalar` for scalar-input indicators whose output is *not*
|
||||
|
||||
Reference in New Issue
Block a user