1mod acceleration_bands;
8mod accelerator_oscillator;
9mod ad_oscillator;
10mod adaptive_cycle;
11mod adl;
12mod adx;
13mod adxr;
14mod alligator;
15mod alma;
16mod alpha;
17mod anchored_vwap;
18mod apo;
19mod aroon;
20mod aroon_oscillator;
21mod atr;
22mod atr_bands;
23mod atr_trailing_stop;
24mod autocorrelation;
25mod average_drawdown;
26mod awesome_oscillator;
27mod awesome_oscillator_histogram;
28mod balance_of_power;
29mod beta;
30mod bollinger;
31mod bollinger_bandwidth;
32mod calmar_ratio;
33mod camarilla_pivots;
34mod cci;
35mod center_of_gravity;
36mod cfo;
37mod chaikin_oscillator;
38mod chaikin_volatility;
39mod chande_kroll_stop;
40mod chandelier_exit;
41mod choppiness_index;
42mod classic_pivots;
43mod cmf;
44mod cmo;
45mod coefficient_of_variation;
46mod cointegration;
47mod conditional_value_at_risk;
48mod connors_rsi;
49mod coppock;
50mod cvd;
51mod cybernetic_cycle;
52mod decycler;
53mod decycler_oscillator;
54mod dema;
55mod demand_index;
56mod demark_pivots;
57mod detrended_std_dev;
58mod doji;
59mod donchian;
60mod donchian_stop;
61mod double_bollinger;
62mod dpo;
63mod drawdown_duration;
64mod ease_of_movement;
65mod ehlers_stochastic;
66mod elder_impulse;
67mod ema;
68mod empirical_mode_decomposition;
69mod engulfing;
70mod evwma;
71mod fama;
72mod fibonacci_pivots;
73mod fisher_transform;
74mod force_index;
75mod fractal_chaos_bands;
76mod frama;
77mod gain_loss_ratio;
78mod garman_klass;
79mod hammer;
80mod hanging_man;
81mod harami;
82mod heikin_ashi;
83mod hilbert_dominant_cycle;
84mod hilo_activator;
85mod historical_volatility;
86mod hma;
87mod hurst_channel;
88mod hurst_exponent;
89mod ichimoku;
90mod inertia;
91mod information_ratio;
92mod initial_balance;
93mod instantaneous_trendline;
94mod inverse_fisher_transform;
95mod inverted_hammer;
96mod jma;
97mod kama;
98mod kelly_criterion;
99mod keltner;
100mod kst;
101mod kurtosis;
102mod kvo;
103mod laguerre_rsi;
104mod lead_lag_cross_correlation;
105mod linreg;
106mod linreg_angle;
107mod linreg_channel;
108mod linreg_slope;
109mod ma_envelope;
110mod macd;
111mod mama;
112mod market_facilitation_index;
113mod marubozu;
114mod mass_index;
115mod max_drawdown;
116mod mcginley_dynamic;
117mod median_absolute_deviation;
118mod median_price;
119mod mfi;
120mod microprice;
121mod mom;
122mod morning_evening_star;
123mod natr;
124mod nvi;
125mod ob_imbalance_full;
126mod ob_imbalance_top1;
127mod ob_imbalance_topn;
128mod obv;
129mod omega_ratio;
130mod opening_range;
131mod pain_index;
132mod pair_spread_zscore;
133mod pairwise_beta;
134mod parkinson;
135mod pearson_correlation;
136mod percent_b;
137mod percentage_trailing_stop;
138mod pgo;
139mod piercing_dark_cloud;
140mod pmo;
141mod ppo;
142mod profit_factor;
143mod psar;
144mod pvi;
145mod quoted_spread;
146mod r_squared;
147mod recovery_factor;
148mod relative_strength_ab;
149mod renko_trailing_stop;
150mod roc;
151mod rogers_satchell;
152mod roofing_filter;
153mod rsi;
154mod rvi;
155mod rvi_volatility;
156mod rwi;
157mod sharpe_ratio;
158mod shooting_star;
159mod signed_volume;
160mod sine_wave;
161mod skewness;
162mod sma;
163mod smi;
164mod smma;
165mod sortino_ratio;
166mod spearman_correlation;
167mod spinning_top;
168mod standard_error;
169mod standard_error_bands;
170mod starc_bands;
171mod stc;
172mod std_dev;
173mod step_trailing_stop;
174mod stoch_rsi;
175mod stochastic;
176mod super_smoother;
177mod super_trend;
178mod t3;
179mod td_combo;
180mod td_countdown;
181mod td_demarker;
182mod td_differential;
183mod td_lines;
184mod td_open;
185mod td_pressure;
186mod td_range_projection;
187mod td_rei;
188mod td_risk_level;
189mod td_sequential;
190mod td_setup;
191mod tema;
192mod three_inside;
193mod three_outside;
194mod three_soldiers_or_crows;
195mod tii;
196mod trade_imbalance;
197mod treynor_ratio;
198mod trima;
199mod trix;
200mod true_range;
201mod tsi;
202mod tsv;
203mod ttm_squeeze;
204mod tweezer;
205mod typical_price;
206mod ulcer_index;
207mod ultimate_oscillator;
208mod value_area;
209mod value_at_risk;
210mod variance;
211mod vertical_horizontal_filter;
212mod vidya;
213mod volty_stop;
214mod volume_oscillator;
215mod vortex;
216mod vpt;
217mod vwap;
218mod vwap_stddev_bands;
219mod vwma;
220mod vzo;
221mod wave_trend;
222mod weighted_close;
223mod williams_fractals;
224mod williams_r;
225mod wma;
226mod woodie_pivots;
227mod yang_zhang;
228mod yoyo_exit;
229mod z_score;
230mod zero_lag_macd;
231mod zig_zag;
232mod zlema;
233
234pub use acceleration_bands::{AccelerationBands, AccelerationBandsOutput};
235pub use accelerator_oscillator::AcceleratorOscillator;
236pub use ad_oscillator::AdOscillator;
237pub use adaptive_cycle::AdaptiveCycle;
238pub use adl::Adl;
239pub use adx::{Adx, AdxOutput};
240pub use adxr::Adxr;
241pub use alligator::{Alligator, AlligatorOutput};
242pub use alma::Alma;
243pub use alpha::Alpha;
244pub use anchored_vwap::AnchoredVwap;
245pub use apo::Apo;
246pub use aroon::{Aroon, AroonOutput};
247pub use aroon_oscillator::AroonOscillator;
248pub use atr::Atr;
249pub use atr_bands::{AtrBands, AtrBandsOutput};
250pub use atr_trailing_stop::AtrTrailingStop;
251pub use autocorrelation::Autocorrelation;
252pub use average_drawdown::AverageDrawdown;
253pub use awesome_oscillator::AwesomeOscillator;
254pub use awesome_oscillator_histogram::AwesomeOscillatorHistogram;
255pub use balance_of_power::BalanceOfPower;
256pub use beta::Beta;
257pub use bollinger::{BollingerBands, BollingerOutput};
258pub use bollinger_bandwidth::BollingerBandwidth;
259pub use calmar_ratio::CalmarRatio;
260pub use camarilla_pivots::{Camarilla, CamarillaPivotsOutput};
261pub use cci::Cci;
262pub use center_of_gravity::CenterOfGravity;
263pub use cfo::Cfo;
264pub use chaikin_oscillator::ChaikinOscillator;
265pub use chaikin_volatility::ChaikinVolatility;
266pub use chande_kroll_stop::{ChandeKrollStop, ChandeKrollStopOutput};
267pub use chandelier_exit::{ChandelierExit, ChandelierExitOutput};
268pub use choppiness_index::ChoppinessIndex;
269pub use classic_pivots::{ClassicPivots, ClassicPivotsOutput};
270pub use cmf::ChaikinMoneyFlow;
271pub use cmo::Cmo;
272pub use coefficient_of_variation::CoefficientOfVariation;
273pub use cointegration::{Cointegration, CointegrationOutput};
274pub use conditional_value_at_risk::ConditionalValueAtRisk;
275pub use connors_rsi::ConnorsRsi;
276pub use coppock::Coppock;
277pub use cvd::CumulativeVolumeDelta;
278pub use cybernetic_cycle::CyberneticCycle;
279pub use decycler::Decycler;
280pub use decycler_oscillator::DecyclerOscillator;
281pub use dema::Dema;
282pub use demand_index::DemandIndex;
283pub use demark_pivots::{DemarkPivots, DemarkPivotsOutput};
284pub use detrended_std_dev::DetrendedStdDev;
285pub use doji::Doji;
286pub use donchian::{Donchian, DonchianOutput};
287pub use donchian_stop::{DonchianStop, DonchianStopOutput};
288pub use double_bollinger::{DoubleBollinger, DoubleBollingerOutput};
289pub use dpo::Dpo;
290pub use drawdown_duration::DrawdownDuration;
291pub use ease_of_movement::EaseOfMovement;
292pub use ehlers_stochastic::EhlersStochastic;
293pub use elder_impulse::ElderImpulse;
294pub use ema::Ema;
295pub use empirical_mode_decomposition::EmpiricalModeDecomposition;
296pub use engulfing::Engulfing;
297pub use evwma::Evwma;
298pub use fama::Fama;
299pub use fibonacci_pivots::{FibonacciPivots, FibonacciPivotsOutput};
300pub use fisher_transform::FisherTransform;
301pub use force_index::ForceIndex;
302pub use fractal_chaos_bands::{FractalChaosBands, FractalChaosBandsOutput};
303pub use frama::Frama;
304pub use gain_loss_ratio::GainLossRatio;
305pub use garman_klass::GarmanKlassVolatility;
306pub use hammer::Hammer;
307pub use hanging_man::HangingMan;
308pub use harami::Harami;
309pub use heikin_ashi::{HeikinAshi, HeikinAshiOutput};
310pub use hilbert_dominant_cycle::HilbertDominantCycle;
311pub use hilo_activator::HiLoActivator;
312pub use historical_volatility::HistoricalVolatility;
313pub use hma::Hma;
314pub use hurst_channel::{HurstChannel, HurstChannelOutput};
315pub use hurst_exponent::HurstExponent;
316pub use ichimoku::{Ichimoku, IchimokuOutput};
317pub use inertia::Inertia;
318pub use information_ratio::InformationRatio;
319pub use initial_balance::{InitialBalance, InitialBalanceOutput};
320pub use instantaneous_trendline::InstantaneousTrendline;
321pub use inverse_fisher_transform::InverseFisherTransform;
322pub use inverted_hammer::InvertedHammer;
323pub use jma::Jma;
324pub use kama::Kama;
325pub use kelly_criterion::KellyCriterion;
326pub use keltner::{Keltner, KeltnerOutput};
327pub use kst::{Kst, KstOutput};
328pub use kurtosis::Kurtosis;
329pub use kvo::Kvo;
330pub use laguerre_rsi::LaguerreRsi;
331pub use lead_lag_cross_correlation::{LeadLagCrossCorrelation, LeadLagCrossCorrelationOutput};
332pub use linreg::LinearRegression;
333pub use linreg_angle::LinRegAngle;
334pub use linreg_channel::{LinRegChannel, LinRegChannelOutput};
335pub use linreg_slope::LinRegSlope;
336pub use ma_envelope::{MaEnvelope, MaEnvelopeOutput};
337pub use macd::{MacdIndicator, MacdOutput};
338pub use mama::{Mama, MamaOutput};
339pub use market_facilitation_index::MarketFacilitationIndex;
340pub use marubozu::Marubozu;
341pub use mass_index::MassIndex;
342pub use max_drawdown::MaxDrawdown;
343pub use mcginley_dynamic::McGinleyDynamic;
344pub use median_absolute_deviation::MedianAbsoluteDeviation;
345pub use median_price::MedianPrice;
346pub use mfi::Mfi;
347pub use microprice::Microprice;
348pub use mom::Mom;
349pub use morning_evening_star::MorningEveningStar;
350pub use natr::Natr;
351pub use nvi::Nvi;
352pub use ob_imbalance_full::OrderBookImbalanceFull;
353pub use ob_imbalance_top1::OrderBookImbalanceTop1;
354pub use ob_imbalance_topn::OrderBookImbalanceTopN;
355pub use obv::Obv;
356pub use omega_ratio::OmegaRatio;
357pub use opening_range::{OpeningRange, OpeningRangeOutput};
358pub use pain_index::PainIndex;
359pub use pair_spread_zscore::PairSpreadZScore;
360pub use pairwise_beta::PairwiseBeta;
361pub use parkinson::ParkinsonVolatility;
362pub use pearson_correlation::PearsonCorrelation;
363pub use percent_b::PercentB;
364pub use percentage_trailing_stop::PercentageTrailingStop;
365pub use pgo::Pgo;
366pub use piercing_dark_cloud::PiercingDarkCloud;
367pub use pmo::Pmo;
368pub use ppo::Ppo;
369pub use profit_factor::ProfitFactor;
370pub use psar::Psar;
371pub use pvi::Pvi;
372pub use quoted_spread::QuotedSpread;
373pub use r_squared::RSquared;
374pub use recovery_factor::RecoveryFactor;
375pub use relative_strength_ab::{RelativeStrengthAB, RelativeStrengthOutput};
376pub use renko_trailing_stop::RenkoTrailingStop;
377pub use roc::Roc;
378pub use rogers_satchell::RogersSatchellVolatility;
379pub use roofing_filter::RoofingFilter;
380pub use rsi::Rsi;
381pub use rvi::Rvi;
382pub use rvi_volatility::RviVolatility;
383pub use rwi::{Rwi, RwiOutput};
384pub use sharpe_ratio::SharpeRatio;
385pub use shooting_star::ShootingStar;
386pub use signed_volume::SignedVolume;
387pub use sine_wave::SineWave;
388pub use skewness::Skewness;
389pub use sma::Sma;
390pub use smi::Smi;
391pub use smma::Smma;
392pub use sortino_ratio::SortinoRatio;
393pub use spearman_correlation::SpearmanCorrelation;
394pub use spinning_top::SpinningTop;
395pub use standard_error::StandardError;
396pub use standard_error_bands::{StandardErrorBands, StandardErrorBandsOutput};
397pub use starc_bands::{StarcBands, StarcBandsOutput};
398pub use stc::Stc;
399pub use std_dev::StdDev;
400pub use step_trailing_stop::StepTrailingStop;
401pub use stoch_rsi::StochRsi;
402pub use stochastic::{Stochastic, StochasticOutput};
403pub use super_smoother::SuperSmoother;
404pub use super_trend::{SuperTrend, SuperTrendOutput};
405pub use t3::T3;
406pub use td_combo::TdCombo;
407pub use td_countdown::TdCountdown;
408pub use td_demarker::TdDeMarker;
409pub use td_differential::TdDifferential;
410pub use td_lines::{TdLines, TdLinesOutput};
411pub use td_open::TdOpen;
412pub use td_pressure::TdPressure;
413pub use td_range_projection::{TdRangeProjection, TdRangeProjectionOutput};
414pub use td_rei::TdRei;
415pub use td_risk_level::{TdRiskLevel, TdRiskLevelOutput};
416pub use td_sequential::{TdSequential, TdSequentialOutput};
417pub use td_setup::TdSetup;
418pub use tema::Tema;
419pub use three_inside::ThreeInside;
420pub use three_outside::ThreeOutside;
421pub use three_soldiers_or_crows::ThreeSoldiersOrCrows;
422pub use tii::Tii;
423pub use trade_imbalance::TradeImbalance;
424pub use treynor_ratio::TreynorRatio;
425pub use trima::Trima;
426pub use trix::Trix;
427pub use true_range::TrueRange;
428pub use tsi::Tsi;
429pub use tsv::Tsv;
430pub use ttm_squeeze::{TtmSqueeze, TtmSqueezeOutput};
431pub use tweezer::Tweezer;
432pub use typical_price::TypicalPrice;
433pub use ulcer_index::UlcerIndex;
434pub use ultimate_oscillator::UltimateOscillator;
435pub use value_area::{ValueArea, ValueAreaOutput};
436pub use value_at_risk::ValueAtRisk;
437pub use variance::Variance;
438pub use vertical_horizontal_filter::VerticalHorizontalFilter;
439pub use vidya::Vidya;
440pub use volty_stop::VoltyStop;
441pub use volume_oscillator::VolumeOscillator;
442pub use vortex::{Vortex, VortexOutput};
443pub use vpt::VolumePriceTrend;
444pub use vwap::{RollingVwap, Vwap};
445pub use vwap_stddev_bands::{VwapStdDevBands, VwapStdDevBandsOutput};
446pub use vwma::Vwma;
447pub use vzo::Vzo;
448pub use wave_trend::{WaveTrend, WaveTrendOutput};
449pub use weighted_close::WeightedClose;
450pub use williams_fractals::{WilliamsFractals, WilliamsFractalsOutput};
451pub use williams_r::WilliamsR;
452pub use wma::Wma;
453pub use woodie_pivots::{WoodiePivots, WoodiePivotsOutput};
454pub use yang_zhang::YangZhangVolatility;
455pub use yoyo_exit::YoyoExit;
456pub use z_score::ZScore;
457pub use zero_lag_macd::{ZeroLagMacd, ZeroLagMacdOutput};
458pub use zig_zag::{ZigZag, ZigZagOutput};
459pub use zlema::Zlema;
460
461pub const FAMILIES: &[(&str, &[&str])] = &[
468 (
469 "Moving Averages",
470 &[
471 "Sma",
472 "Ema",
473 "Wma",
474 "Dema",
475 "Tema",
476 "Hma",
477 "Kama",
478 "Smma",
479 "Trima",
480 "Zlema",
481 "T3",
482 "Vwma",
483 "Alma",
484 "McGinleyDynamic",
485 "Frama",
486 "Vidya",
487 "Jma",
488 "Alligator",
489 "Evwma",
490 ],
491 ),
492 (
493 "Momentum Oscillators",
494 &[
495 "Rsi",
496 "Stochastic",
497 "Cci",
498 "Roc",
499 "WilliamsR",
500 "Mfi",
501 "AwesomeOscillator",
502 "Mom",
503 "Cmo",
504 "Tsi",
505 "Pmo",
506 "StochRsi",
507 "UltimateOscillator",
508 "Rvi",
509 "Pgo",
510 "Kst",
511 "Smi",
512 "LaguerreRsi",
513 "ConnorsRsi",
514 "Inertia",
515 ],
516 ),
517 (
518 "Trend & Directional",
519 &[
520 "MacdIndicator",
521 "Adx",
522 "Adxr",
523 "Aroon",
524 "Trix",
525 "AroonOscillator",
526 "Vortex",
527 "Rwi",
528 "Tii",
529 "WaveTrend",
530 "MassIndex",
531 "ChoppinessIndex",
532 "VerticalHorizontalFilter",
533 ],
534 ),
535 (
536 "Price Oscillators",
537 &[
538 "Ppo",
539 "Dpo",
540 "Coppock",
541 "AcceleratorOscillator",
542 "BalanceOfPower",
543 "Apo",
544 "AwesomeOscillatorHistogram",
545 "Cfo",
546 "ZeroLagMacd",
547 "ElderImpulse",
548 "Stc",
549 ],
550 ),
551 (
552 "Volatility & Bands",
553 &[
554 "Atr",
555 "BollingerBands",
556 "Keltner",
557 "Donchian",
558 "Natr",
559 "StdDev",
560 "UlcerIndex",
561 "HistoricalVolatility",
562 "BollingerBandwidth",
563 "PercentB",
564 "TrueRange",
565 "ChaikinVolatility",
566 "RviVolatility",
567 "ParkinsonVolatility",
568 "GarmanKlassVolatility",
569 "RogersSatchellVolatility",
570 "YangZhangVolatility",
571 ],
572 ),
573 (
574 "Bands & Channels",
575 &[
576 "MaEnvelope",
577 "AccelerationBands",
578 "StarcBands",
579 "AtrBands",
580 "HurstChannel",
581 "LinRegChannel",
582 "StandardErrorBands",
583 "DoubleBollinger",
584 "TtmSqueeze",
585 "FractalChaosBands",
586 "VwapStdDevBands",
587 ],
588 ),
589 (
590 "Trailing Stops",
591 &[
592 "Psar",
593 "SuperTrend",
594 "ChandelierExit",
595 "ChandeKrollStop",
596 "AtrTrailingStop",
597 "HiLoActivator",
598 "VoltyStop",
599 "YoyoExit",
600 "DonchianStop",
601 "PercentageTrailingStop",
602 "StepTrailingStop",
603 "RenkoTrailingStop",
604 ],
605 ),
606 (
607 "Volume",
608 &[
609 "Obv",
610 "Vwap",
611 "RollingVwap",
612 "Adl",
613 "VolumePriceTrend",
614 "ChaikinMoneyFlow",
615 "ChaikinOscillator",
616 "ForceIndex",
617 "EaseOfMovement",
618 "Kvo",
619 "VolumeOscillator",
620 "Nvi",
621 "Pvi",
622 "AdOscillator",
623 "AnchoredVwap",
624 "DemandIndex",
625 "Tsv",
626 "Vzo",
627 "MarketFacilitationIndex",
628 ],
629 ),
630 (
631 "Price Statistics",
632 &[
633 "TypicalPrice",
634 "MedianPrice",
635 "WeightedClose",
636 "LinearRegression",
637 "LinRegSlope",
638 "ZScore",
639 "LinRegAngle",
640 "Variance",
641 "CoefficientOfVariation",
642 "Skewness",
643 "Kurtosis",
644 "StandardError",
645 "DetrendedStdDev",
646 "RSquared",
647 "MedianAbsoluteDeviation",
648 "Autocorrelation",
649 "HurstExponent",
650 "PearsonCorrelation",
651 "Beta",
652 "SpearmanCorrelation",
653 ],
654 ),
655 (
656 "Ehlers / Cycle (DSP)",
657 &[
658 "Mama",
659 "Fama",
660 "FisherTransform",
661 "InverseFisherTransform",
662 "SuperSmoother",
663 "HilbertDominantCycle",
664 "SineWave",
665 "Decycler",
666 "DecyclerOscillator",
667 "RoofingFilter",
668 "CenterOfGravity",
669 "CyberneticCycle",
670 "AdaptiveCycle",
671 "EmpiricalModeDecomposition",
672 "EhlersStochastic",
673 "InstantaneousTrendline",
674 ],
675 ),
676 (
677 "Pivots & S/R",
678 &[
679 "ClassicPivots",
680 "FibonacciPivots",
681 "Camarilla",
682 "WoodiePivots",
683 "DemarkPivots",
684 "WilliamsFractals",
685 "ZigZag",
686 ],
687 ),
688 (
689 "DeMark",
690 &[
691 "TdSetup",
692 "TdSequential",
693 "TdDeMarker",
694 "TdRei",
695 "TdPressure",
696 "TdCombo",
697 "TdCountdown",
698 "TdLines",
699 "TdRangeProjection",
700 "TdDifferential",
701 "TdOpen",
702 "TdRiskLevel",
703 ],
704 ),
705 ("Ichimoku & Charts", &["Ichimoku", "HeikinAshi"]),
706 (
707 "Candlestick Patterns",
708 &[
709 "Doji",
710 "Hammer",
711 "InvertedHammer",
712 "HangingMan",
713 "ShootingStar",
714 "Engulfing",
715 "Harami",
716 "MorningEveningStar",
717 "ThreeSoldiersOrCrows",
718 "PiercingDarkCloud",
719 "Marubozu",
720 "Tweezer",
721 "SpinningTop",
722 "ThreeInside",
723 "ThreeOutside",
724 ],
725 ),
726 (
727 "Microstructure",
728 &[
729 "OrderBookImbalanceTop1",
730 "OrderBookImbalanceTopN",
731 "OrderBookImbalanceFull",
732 "Microprice",
733 "QuotedSpread",
734 "SignedVolume",
735 "CumulativeVolumeDelta",
736 "TradeImbalance",
737 ],
738 ),
739 (
740 "Market Profile",
741 &["ValueArea", "InitialBalance", "OpeningRange"],
742 ),
743 (
744 "Risk / Performance",
745 &[
746 "SharpeRatio",
747 "SortinoRatio",
748 "CalmarRatio",
749 "OmegaRatio",
750 "MaxDrawdown",
751 "AverageDrawdown",
752 "DrawdownDuration",
753 "PainIndex",
754 "ValueAtRisk",
755 "ConditionalValueAtRisk",
756 "ProfitFactor",
757 "GainLossRatio",
758 "RecoveryFactor",
759 "KellyCriterion",
760 "TreynorRatio",
761 "InformationRatio",
762 "Alpha",
763 ],
764 ),
765];
766
767#[cfg(test)]
768mod family_tests {
769 use super::FAMILIES;
770
771 #[test]
772 fn no_duplicates_across_families() {
773 let mut names: Vec<&str> = FAMILIES
774 .iter()
775 .flat_map(|(_, ns)| ns.iter().copied())
776 .collect();
777 let len_before = names.len();
778 names.sort_unstable();
779 names.dedup();
780 assert_eq!(
781 names.len(),
782 len_before,
783 "duplicate indicator across families"
784 );
785 }
786
787 #[test]
788 fn total_count_matches_expected() {
789 let total: usize = FAMILIES.iter().map(|(_, ns)| ns.len()).sum();
793 assert_eq!(total, 222, "FAMILIES total drifted from indicator count");
794 }
795}