feat(indicators): A5b Fibonacci tools (geometric) (#172)

Completes the **Fibonacci** family with the four geometric/time tools (catalogue 373 -> 377). All extend the internal `pattern_swing` ZigZag tracker with a per-pivot bar index and a current-bar counter (additive — the chart/harmonic detectors are unaffected), and emit `Candle -> struct` outputs via custom Python/Node/WASM bindings.

| Tool | Output |
|------|--------|
| `FibFan` | three trendlines fanning from a swing start through its 38.2/50/61.8% retracement levels, extended to the current bar |
| `FibArcs` | semicircular retracement levels centred on the swing end, normalised by the leg's bar-width (chart-scale-free) |
| `FibChannel` | a sloped base trendline plus parallel lines at Fibonacci multiples of the channel width |
| `FibTimeZones` | markers at Fibonacci bar-distances (1/2/3/5/8/...) from the latest swing pivot |

The geometric tools are novel as streaming indicators; each normalises its geometry to the swing leg's bar-width so the output is chart-scale-free. Formulas are documented in each module and deep-dive.

Fully wired: core (100% unit-tested branches incl. the new `pattern_swing` bar tracking), Python/Node/WASM struct bindings, fuzz, reference + streaming-vs-batch tests.

Verification: `cargo test --workspace` green, clippy `-D warnings` clean, node 454 tests, python 768 tests.
This commit is contained in:
kingchenc
2026-06-04 01:12:09 +02:00
committed by GitHub
parent ea9da12d86
commit 5a1d607807
19 changed files with 1757 additions and 13 deletions
@@ -391,6 +391,10 @@ const multi = {
AutoFib: { make: () => new wickra.AutoFib(), fields: ['level0', 'level236', 'level382', 'level500', 'level618', 'level786', 'level1000'], step: (ind, i) => ind.update(high[i], low[i]), batch: (ind) => ind.batch(high, low) },
GoldenPocket: { make: () => new wickra.GoldenPocket(), fields: ['low', 'mid', 'high'], step: (ind, i) => ind.update(high[i], low[i]), batch: (ind) => ind.batch(high, low) },
FibConfluence: { make: () => new wickra.FibConfluence(), fields: ['price', 'strength'], step: (ind, i) => ind.update(high[i], low[i]), batch: (ind) => ind.batch(high, low) },
FibFan: { make: () => new wickra.FibFan(), fields: ['fan382', 'fan500', 'fan618'], step: (ind, i) => ind.update(high[i], low[i]), batch: (ind) => ind.batch(high, low) },
FibArcs: { make: () => new wickra.FibArcs(), fields: ['arc382', 'arc500', 'arc618'], step: (ind, i) => ind.update(high[i], low[i]), batch: (ind) => ind.batch(high, low) },
FibChannel: { make: () => new wickra.FibChannel(), fields: ['base', 'level618', 'level1000', 'level1618'], step: (ind, i) => ind.update(high[i], low[i]), batch: (ind) => ind.batch(high, low) },
FibTimeZones: { make: () => new wickra.FibTimeZones(), fields: ['onZone', 'barsToNext'], step: (ind, i) => ind.update(high[i], low[i]), batch: (ind) => ind.batch(high, low) },
};
for (const [name, d] of Object.entries(multi)) {