feat(patterns): add the Harmonic Patterns family (8 XABCD detectors) (#169)
## Summary Adds a new **Harmonic Patterns** indicator family (counter 359 → 367, families 22 → 23) — the second half of the A4 roadmap item, following the Chart Patterns family in #166. Eight Fibonacci-ratio detectors built on the shared swing-pivot tracker (`indicators::pattern_swing`) plus two new helpers there — `xabcd` (reads the last five pivots as X-A-B-C-D) and `ratios_in` (checks a list of `(value, low, high)` Fibonacci windows in one expression, no multi-line `&&` coverage gaps). Each consumes candles and emits the uniform pattern sign convention — `+1.0` bullish (terminal point D a swing low), `-1.0` bearish (D a swing high), `0.0` otherwise, never `None`. Parameter-free, with the Fibonacci windows documented as constants per detector. ## Detectors | Indicator | Defining ratio | |-----------|----------------| | `Abcd` | four-point AB=CD (BC retraces AB, CD ≈ AB) | | `Gartley` | AD/XA ≈ 0.786 | | `Butterfly` | AD/XA ∈ 1.27–1.618 (extended D) | | `Bat` | AD/XA ≈ 0.886, shallow B | | `Crab` | AD/XA ≈ 1.618 (deepest D) | | `Shark` | expansion AB, AD/XA 0.886–1.13 | | `Cypher` | BC on XA, CD/XC ≈ 0.786 | | `ThreeDrives` | two symmetric extension drives | ## Touchpoints Core modules + `FAMILIES` group/assert, crate root re-exports, Python/Node/WASM bindings via the candle-pattern macros (Node `index.d.ts`/`index.js` regenerated), the candle fuzz target (`// --- Harmonic Patterns ---` section), Python reference + `CANDLE_SCALAR` registry tests and the Node candle-scalar factory, README catalogue counter + banner cache-buster + family table row + family-count word, `docs/README.md` counter, and the changelog. ## Verification - `cargo test -p wickra-core --lib` — 2966 passed - `cargo test -p wickra-core --doc` — 335 passed - `cargo clippy --workspace --all-targets --all-features -- -D warnings` — clean - Node `npm run build && npm test` — 444 passed - Python `maturin develop --release` + `pytest` — 748 passed Every detector branch is unit-tested, including a bullish and a bearish match per pattern to cover both output arms, plus an out-of-ratio non-match. Fibonacci windows use standard harmonic-trading ranges with documented tolerance bands.
This commit is contained in:
@@ -10,6 +10,7 @@
|
||||
pub(crate) mod pattern_swing;
|
||||
|
||||
mod abandoned_baby;
|
||||
mod abcd;
|
||||
mod absolute_breadth_index;
|
||||
mod acceleration_bands;
|
||||
mod accelerator_oscillator;
|
||||
@@ -40,6 +41,7 @@ mod avg_price;
|
||||
mod awesome_oscillator;
|
||||
mod awesome_oscillator_histogram;
|
||||
mod balance_of_power;
|
||||
mod bat;
|
||||
mod belt_hold;
|
||||
mod beta;
|
||||
mod beta_neutral_spread;
|
||||
@@ -48,6 +50,7 @@ mod bollinger_bandwidth;
|
||||
mod breadth_thrust;
|
||||
mod breakaway;
|
||||
mod bullish_percent_index;
|
||||
mod butterfly;
|
||||
mod calendar_spread;
|
||||
mod calmar_ratio;
|
||||
mod camarilla_pivots;
|
||||
@@ -70,10 +73,12 @@ mod conditional_value_at_risk;
|
||||
mod connors_rsi;
|
||||
mod coppock;
|
||||
mod counterattack;
|
||||
mod crab;
|
||||
mod cumulative_volume_index;
|
||||
mod cup_and_handle;
|
||||
mod cvd;
|
||||
mod cybernetic_cycle;
|
||||
mod cypher;
|
||||
mod day_of_week_profile;
|
||||
mod decycler;
|
||||
mod decycler_oscillator;
|
||||
@@ -119,6 +124,7 @@ mod funding_rate_zscore;
|
||||
mod gain_loss_ratio;
|
||||
mod gap_side_by_side_white;
|
||||
mod garman_klass;
|
||||
mod gartley;
|
||||
mod granger_causality;
|
||||
mod gravestone_doji;
|
||||
mod hammer;
|
||||
@@ -262,6 +268,7 @@ mod separating_lines;
|
||||
mod session_high_low;
|
||||
mod session_range;
|
||||
mod session_vwap;
|
||||
mod shark;
|
||||
mod sharpe_ratio;
|
||||
mod shooting_star;
|
||||
mod short_line;
|
||||
@@ -306,6 +313,7 @@ mod td_sequential;
|
||||
mod td_setup;
|
||||
mod tema;
|
||||
mod term_structure_basis;
|
||||
mod three_drives;
|
||||
mod three_inside;
|
||||
mod three_line_strike;
|
||||
mod three_outside;
|
||||
@@ -369,6 +377,7 @@ mod zig_zag;
|
||||
mod zlema;
|
||||
|
||||
pub use abandoned_baby::AbandonedBaby;
|
||||
pub use abcd::Abcd;
|
||||
pub use absolute_breadth_index::AbsoluteBreadthIndex;
|
||||
pub use acceleration_bands::{AccelerationBands, AccelerationBandsOutput};
|
||||
pub use accelerator_oscillator::AcceleratorOscillator;
|
||||
@@ -399,6 +408,7 @@ pub use avg_price::AvgPrice;
|
||||
pub use awesome_oscillator::AwesomeOscillator;
|
||||
pub use awesome_oscillator_histogram::AwesomeOscillatorHistogram;
|
||||
pub use balance_of_power::BalanceOfPower;
|
||||
pub use bat::Bat;
|
||||
pub use belt_hold::BeltHold;
|
||||
pub use beta::Beta;
|
||||
pub use beta_neutral_spread::BetaNeutralSpread;
|
||||
@@ -407,6 +417,7 @@ pub use bollinger_bandwidth::BollingerBandwidth;
|
||||
pub use breadth_thrust::BreadthThrust;
|
||||
pub use breakaway::Breakaway;
|
||||
pub use bullish_percent_index::BullishPercentIndex;
|
||||
pub use butterfly::Butterfly;
|
||||
pub use calendar_spread::CalendarSpread;
|
||||
pub use calmar_ratio::CalmarRatio;
|
||||
pub use camarilla_pivots::{Camarilla, CamarillaPivotsOutput};
|
||||
@@ -429,10 +440,12 @@ pub use conditional_value_at_risk::ConditionalValueAtRisk;
|
||||
pub use connors_rsi::ConnorsRsi;
|
||||
pub use coppock::Coppock;
|
||||
pub use counterattack::Counterattack;
|
||||
pub use crab::Crab;
|
||||
pub use cumulative_volume_index::CumulativeVolumeIndex;
|
||||
pub use cup_and_handle::CupAndHandle;
|
||||
pub use cvd::CumulativeVolumeDelta;
|
||||
pub use cybernetic_cycle::CyberneticCycle;
|
||||
pub use cypher::Cypher;
|
||||
pub use day_of_week_profile::{DayOfWeekProfile, DayOfWeekProfileOutput};
|
||||
pub use decycler::Decycler;
|
||||
pub use decycler_oscillator::DecyclerOscillator;
|
||||
@@ -478,6 +491,7 @@ pub use funding_rate_zscore::FundingRateZScore;
|
||||
pub use gain_loss_ratio::GainLossRatio;
|
||||
pub use gap_side_by_side_white::GapSideBySideWhite;
|
||||
pub use garman_klass::GarmanKlassVolatility;
|
||||
pub use gartley::Gartley;
|
||||
pub use granger_causality::GrangerCausality;
|
||||
pub use gravestone_doji::GravestoneDoji;
|
||||
pub use hammer::Hammer;
|
||||
@@ -621,6 +635,7 @@ pub use separating_lines::SeparatingLines;
|
||||
pub use session_high_low::{SessionHighLow, SessionHighLowOutput};
|
||||
pub use session_range::{SessionRange, SessionRangeOutput};
|
||||
pub use session_vwap::SessionVwap;
|
||||
pub use shark::Shark;
|
||||
pub use sharpe_ratio::SharpeRatio;
|
||||
pub use shooting_star::ShootingStar;
|
||||
pub use short_line::ShortLine;
|
||||
@@ -665,6 +680,7 @@ pub use td_sequential::{TdSequential, TdSequentialOutput};
|
||||
pub use td_setup::TdSetup;
|
||||
pub use tema::Tema;
|
||||
pub use term_structure_basis::TermStructureBasis;
|
||||
pub use three_drives::ThreeDrives;
|
||||
pub use three_inside::ThreeInside;
|
||||
pub use three_line_strike::ThreeLineStrike;
|
||||
pub use three_outside::ThreeOutside;
|
||||
@@ -1193,6 +1209,19 @@ pub const FAMILIES: &[(&str, &[&str])] = &[
|
||||
"CupAndHandle",
|
||||
],
|
||||
),
|
||||
(
|
||||
"Harmonic Patterns",
|
||||
&[
|
||||
"Abcd",
|
||||
"Gartley",
|
||||
"Butterfly",
|
||||
"Bat",
|
||||
"Crab",
|
||||
"Shark",
|
||||
"Cypher",
|
||||
"ThreeDrives",
|
||||
],
|
||||
),
|
||||
];
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -1221,6 +1250,6 @@ mod family_tests {
|
||||
// the actual indicator count is the early-warning signal that an
|
||||
// indicator was added without being assigned a family.
|
||||
let total: usize = FAMILIES.iter().map(|(_, ns)| ns.len()).sum();
|
||||
assert_eq!(total, 359, "FAMILIES total drifted from indicator count");
|
||||
assert_eq!(total, 367, "FAMILIES total drifted from indicator count");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user