# qta — Streaming Technical Analysis Indicators
> Parent: [`crates/CLAUDE.md`](../CLAUDE.md) | Root: [`/CLAUDE.md`](../../CLAUDE.md)
## Indicators
| `zigzag` | Streaming ZigZag swing detection (no-repaint, O(1) state) | 31 unit + 7 proptest + 2 doctest |
## Architecture
Follows **ta-rs** (flat re-exports at root) and **yata** (Config/State separation) patterns.
- `lib.rs` — Re-exports only: `pub use zigzag::{BarInput, ZigZagConfig, ZigZagState, ...}`
- `zigzag/config.rs` — Immutable validated params. `ZigZagConfig::new()` → `Result<Self, ZigZagError>`
- `zigzag/state.rs` — Streaming state machine. `process_bar(&bar)` → `ZigZagOutput`
- `zigzag/types.rs` — Domain types: `BarInput`, `Pivot`, `PivotKind`, `Segment`, `BaseClass`, `ZigZagOutput`
- `zigzag/ctrends.rs` — Post-filter: `filter_ctrends(pivots, config) -> Vec<Pivot>`
- `zigzag/direction.rs` — Internal `pub(crate)` direction tracking
- `zigzag/base_class.rs` — Pivot classification and z-score
- `zigzag/segment.rs` — Rolling window `SegmentStats`
## Key Patterns
- **Prices as fixed-point `i64`** (× 1e8) — never `f64` for prices
- **Config/State separation** — config immutable after construction, state holds runtime values
- **No-repaint guarantee** — once `ConfirmationStatus::Confirmed` is set, the pivot never mutates (enforced by proptest)
- **Serde feature-gated** — `#[cfg_attr(feature = "serde", derive(Serialize, Deserialize))]`
- **Threshold formulas:** `δ = price × bar_threshold_dbps / 100_000`, `τ = N × δ`, `ε = E × δ`
## Clippy Config
`deny(all)` + `warn(pedantic)` with specific allows in `Cargo.toml`:
- `doc_markdown` (needed for ZigZag/FixedPoint terms)
- `cast_possible_truncation`, `cast_sign_loss`, `cast_precision_loss` (intentional fixed-point math)
## Adding New Indicators
1. Create `src/<indicator>/mod.rs` with types, config, state
2. Add `pub mod <indicator>;` to `src/lib.rs`
3. Re-export key types at crate root
4. Add property-based tests in `tests/`
## Known Gaps
- `confirmed_pivots: Vec<Pivot>` grows unboundedly (memory concern for long streams)
- `ThresholdMode::DurationWeighted` and `AtrBased` exist but are never consumed
- Only 2 of ~15 public types have doc examples