Pipeline overview
For each request, we fetch OHLCV bars at three intervals (weekly, daily, 4-hour), run the same enumeration on each, score the resulting wave counts for multi-timeframe agreement, optionally rerank with an LLM, and derive a trade signal from the top count. Every step is deterministic given the same inputs and as-of date.
src/wave_alpha/pipeline.py:run_analysis · Spec: §5 of 2026-05-03-wave-alpha-design.mdPivots & degrees
A zigzag detector finds turning points in price scaled by Average True Range (ATR), so the same logic works on a $5 stock and a $5,000 one. Pivots are stratified into degrees: degree-0 captures every micro-turn, higher degrees keep only the more significant ones. The engine counts at degree 2 by default — coarse enough to ignore noise, fine enough to see most actionable patterns.
src/wave_alpha/pivots/ · Spec: §6Wave templates
Patterns are defined in YAML, not code. Each template (impulse, zigzag, flat, expanded
flat, contracting triangle, ending diagonal) lists its waves and constraints, marked
either hard (rejection) or soft (score penalty). Adding a
new pattern means dropping a YAML file in
src/wave_alpha/elliott/templates_data/ — no code change required
unless a new constraint operator is involved.
src/wave_alpha/elliott/templates_data/ · Spec: §7Enumeration & scoring
For each timeframe, the engine slides every template across the recent pivot stream and records every legal fit. Each candidate is scored on three components: template fit (how cleanly the pivots match the wave skeleton), fib quality (how close wave ratios sit to canonical Fibonacci targets), and recency (how fresh the most recent pivot is). Multiple windows of the same template family deduplicate down to the highest-scoring instance before the global top-K cut, so one template can't crowd out alternates.
src/wave_alpha/elliott/enumerator.py · Spec: §8Multi-timeframe coherence
Coherence asks: do the weekly, daily, and 4-hour timeframes tell the same story? The engine compares the top counts pairwise (W↔D, W↔4h, D↔4h) and produces a multiplier that scales the engine score. Strong agreement amplifies confidence; weak agreement (or missing-timeframe data) leaves the multiplier at 1.0 or below. High coherence means the count is consistent across horizons; it does not mean the count is correct.
src/wave_alpha/coherence/score.py · Spec: §9Right-edge confirmation
The most recent pivot is, by definition, the least confirmed. The right-edge model
estimates the probability that this tentative pivot will hold — that future bars
won't push past it and invalidate the count. Three implementations exist: a hand-coded
heuristic, a heuristic plus per-degree Platt calibration, and a full logistic regression
with a feature-order-stable JSON artifact. The active model is selected per
configuration; auto prefers logistic, falls back to calibrated heuristic,
then heuristic.
src/wave_alpha/right_edge/ · Spec: §10LLM rerank & α blend
The LLM is strictly optional. When enabled, it reranks the engine's top candidates
— it never invents counts. The final score blends both signals as
final = α × engine + (1 − α) × llm, then multiplies by
the coherence multiplier. The default α = 0.6 leans on the engine; tune toward 1.0
to trust the engine fully, toward 0.0 to trust the LLM fully. There is no formal
Sharpe sweep yet, so the default is internal preference rather than a fitted optimum.
Three modes: disabled (no API key needed, fully deterministic;
mandatory for backtest comparisons), cached (replays prior responses
from the local SQLite cache, raises on miss), live (real API calls,
writes to cache).
src/wave_alpha/llm/ · Spec: §11Trade plan derivation
For the top candidate that meets a minimum-confidence threshold, the engine derives a
trade plan: entry at the close of the most recent confirming pivot,
stop at the prior wave's structural extreme (with an ATR cushion), and
target from a Fibonacci extension of the active count by default. R:R is
(target − entry) ÷ (entry − stop). Switch the target
source to fixed_R in Settings to use a fixed multiple of the
entry-to-stop distance instead.
src/wave_alpha/trades/derive.py · Spec: §12Lookahead-safety guarantee
Every analysis runs through PointInTimeView, which hard-asserts that no
bar with a timestamp after the as-of date is reachable. The backtest harness, the live
pipeline, and the right-edge feature extractor all flow through it. A synthetic-leak
unit test (tests/backtest/test_lookahead_guard.py) plants a deliberate
violation to verify the assertion fires — if you ever see it pass with a leaked
bar, the safety net has a hole.
src/wave_alpha/data/point_in_time.py:PointInTimeView · Spec: §13Privacy contract
When the LLM is enabled, the only payload sent upstream is: ticker symbol, pivot
timestamps and prices, candidate count structures, and coherence metrics. No raw OHLCV
bars, no API keys (the key is set on the client, never serialised in the payload), no
account information. This contract lives in llm/prompts.py and
llm/candidates.py:serialize_candidate_set. Tampering with either should
require a paired update to this section.
src/wave_alpha/llm/prompts.py, llm/candidates.py · Spec: §14What this is not
- This is not financial advice. The engine produces deterministic candidate counts and signals; whether to act on them is your judgment.
- This is not a real-time backtest of itself. Coherence and right-edge are computed per request, not validated per request.
- The engine can and does miss patterns. The template set in
templates_data/is finite; price action that doesn't fit a template gets no candidates. - High coherence does not mean the count is correct. It means the engine reached the same count across timeframes — more likely to be correct, not certain.
- LLM rerank is heuristic. With α = 0.6 the engine still dominates; setting α = 0.0 makes the LLM responsible for most of the ranking, which is not validated.