Local-first Elliott Wave analysis for swing traders
Project description
Local-first Elliott Wave analysis for swing traders. Deterministic rule engine · multi-timeframe coherence · optional LLM reranking · leak-free backtests.
Why wave-alpha
Existing "auto Elliott" tools are either dressed-up ZigZag indicators, institutional-priced terminals, or cloud-only SaaS. None of them give swing traders all of:
- Rule-validated counts with calibrated alternates — not a single confident-but-fragile answer.
- Multi-timeframe coherence (weekly + daily + 4h) as a first-class scoring input.
- A trade-signal contract — entry, stop, target, R-multiple — derived directly from the count.
- Honest backtests that enforce lookahead at every fetch site.
- Local-first, BYO-key, no telemetry. Your watchlist and bars stay on your disk.
[!NOTE] The LLM is a strictly optional reranker and narrator — it never counts waves on its own. The deterministic engine is always the source of truth.
Contents
- What it does
- Prerequisites
- Installation
- Quick start
- CLI at a glance
- Web UI
- Watchlist & scan
- History snapshots
- LLM reranking (optional)
- Backtest harness
- How it works
- Right-edge models
- Persistence
- Development
- Disclaimer
- License
What it does
wave-alpha covers the full swing-trader workflow — from raw bars to a ranked thesis to a backtest receipt — organized around six capabilities:
| Capability | Summary | Learn more |
|---|---|---|
| 🌊 Wave detection | Rule-validated Elliott counts with calibrated alternates and multi-timeframe coherence. | How it works |
| 🎯 Trade-ready signals | Entry, stop, target, and R-multiple derived directly from the top count. | Quick start |
| 📋 Watchlist & scanning | Persistent watchlist, multi-ticker scans, and a self-refreshing OHLCV cache. | Watchlist & scan |
| 📈 History & stability | Per-ticker snapshots and a stability badge that tracks how a thesis holds up over time. | History snapshots |
| ✅ Honest backtests | Three-layer harness with hard-enforced lookahead safety. | Backtest harness |
| 🤖 Optional LLM rerank | BYO Anthropic key for reranking and narration; engine never depends on it. | LLM reranking |
Wave detection
- Pattern library as data — six templates (
impulse,zigzag,flat,expanded_flat,contracting_triangle,ending_diagonal) defined in YAML withhard/softconstraints. Add a pattern by dropping a file — no code change. - Multi-degree ATR-scaled pivots with deduplicated top-K candidates per timeframe.
- Multi-timeframe coherence — weekly + daily + 4h read against each other; the coherence multiplier folds into final ranking.
- Calibrated alternates ranked by
final = coh × (α · engine + (1−α) · llm_prob), never a single confident answer.
Trade-ready signals
- Entry / stop / target / R-multiple derived from the count's structural pivots.
- Right-edge confirmation models —
heuristic,calibrated_heuristic, or trainedlogistic— with paired-bootstrap promotion gating. - Configurable target source —
fib_extension(default) orfixed_R.
Watchlist & multi-ticker scanning
- Watchlist with imports from CSV or TradingView text format.
- Scan any list of tickers with one command; reports persist to
~/.wave_alpha/scans/for instant dashboard reload. - OHLCV cache auto-refetches a stale tail, so daily cron runs always pull fresh bars without re-downloading history.
History & stability tracking
- Snapshot per analysis — every
analyzecall records the top counts, signals, and coherence to~/.wave_alpha/history.sqlite. - Stability badge highlights when the top count's identity persists across runs — separates transient signals from a maturing thesis.
- Best-effort writes that never raise, so corrupted state can't interrupt analysis output.
Honest backtest harness
- Three layers — count direction hit-rate, per-degree pivot Brier score, and full trade simulation (hit rate, expectancy, profit factor, max drawdown in R-units).
- Lookahead is hard-enforced by
PointInTimeViewat every fetch site, with a synthetic-leak unit test that plants a violation and verifies the assertion fires. - Grid search to sweep rule parameters across the curated universe.
Interfaces
- CLI —
analyze,scan,watchlist,backtest,train,ui,config(command reference). - Local web UI with TradingView Lightweight Charts (vendored, MIT) — deep-dive page, scan dashboard, watchlist manager, count-history strip. Zero CDN runtime dependencies.
Optional: LLM reranking
- BYO Anthropic key — the engine is fully usable without one.
- Reranker only — the LLM never counts waves; it adjusts ranking and narrates the top thesis.
- Strict privacy contract — pivots and candidate structures only; no bars, no watchlist, no key in payload.
Prerequisites
| Requirement | Why |
|---|---|
| Python 3.11+ | Pinned in .python-version; required by the engine. |
uv |
Project manager — every command runs as uv run …. |
| Anthropic API key (optional) | Only needed for --llm-mode live; requires the llm extra (wave-alpha[llm]). The engine is fully usable without it. |
[!IMPORTANT] All commands go through
uv— do not activate the venv manually.uv runresolves the right interpreter and extras for you.
Installation
From PyPI (most users)
# Lean install (deterministic engine + CLI)
uv pip install wave-alpha
# With the local web UI
uv pip install "wave-alpha[ui]"
# With the optional LLM reranker (BYO Anthropic key)
uv pip install "wave-alpha[ui,llm]"
The LLM reranker is opt-in — install the llm extra to enable --llm-mode live or cached. Without it, the deterministic engine works exactly the same.
Develop from source
git clone https://github.com/chen-star/wave-alpha.git
cd wave-alpha
# Engine + CLI only (most contributors start here)
uv sync --extra dev
# Add the web UI
uv sync --extra dev --extra ui
# Add the LLM reranker
uv sync --extra dev --extra ui --extra llm
Verify the install:
uv run wave-alpha version
Quick start
Run a one-off analysis on a ticker — no API key, no cloud, no account:
# Today
uv run wave-alpha analyze AAPL
# Or rewind to a specific cutoff (lookahead-safe)
uv run wave-alpha analyze AAPL --as-of 2024-12-31
# JSON output for scripting
uv run wave-alpha analyze AAPL --json | jq .
You'll see the top-3 ranked counts, a coherence score, and any derived trade signals (entry / stop / target / R-multiple). Each run also writes a snapshot to the local history database — see History snapshots.
CLI at a glance
| Command | Purpose |
|---|---|
wave-alpha analyze TICKER |
Run analysis for a single ticker, optionally --as-of YYYY-MM-DD, --json, --llm-mode. |
wave-alpha scan |
Scan watchlist (or --symbols A,B,C) and persist a report. |
wave-alpha ui |
Launch the local web UI (binds to 127.0.0.1, picks a free port in 8765–8775). |
wave-alpha watchlist add|rm|ls|import |
Manage saved tickers. |
wave-alpha config show|set |
View or change config (API key, model, alpha). |
wave-alpha backtest count|pivot|trade|grid |
Walk-forward backtest harness across three layers + grid search. |
wave-alpha train right-edge|calibrated-heuristic |
Train and gate right-edge confirmation models. |
wave-alpha version |
Print the installed version. |
Every command supports --help.
Web UI
uv sync --extra ui
uv run wave-alpha ui # binds to 127.0.0.1 on first free port in 8765–8775
Then open:
| Page | URL |
|---|---|
| Single-ticker deep-dive | http://127.0.0.1:8765/deepdive/SPY |
| Scan dashboard | http://127.0.0.1:8765/scan |
| Watchlist | http://127.0.0.1:8765/watchlist |
| Settings (paste API key here) | http://127.0.0.1:8765/settings |
The deep-dive page composes a chart with pivot overlays, the multi-TF coherence row, the top-3 counts with optional LLM narrative, an auto-derived trade plan, right-edge alternates, and a count-history strip.
Watchlist & scan
uv run wave-alpha watchlist add AAPL
uv run wave-alpha watchlist add MSFT
uv run wave-alpha watchlist import portfolio.csv --format csv
uv run wave-alpha watchlist import tradingview.txt --format tv-txt
# Scan all watchlist tickers (LLM disabled by default — no API cost)
uv run wave-alpha scan
# Ad-hoc list with a specific cutoff
uv run wave-alpha scan --symbols AAPL,MSFT,NVDA --as-of 2026-05-01
Reports persist as JSON to ~/.wave_alpha/scans/<scan_id>.json so the dashboard reloads instantly without re-running.
History snapshots
Every analyze invocation writes a snapshot of the top counts, coherence, and trade signal into ~/.wave_alpha/history.sqlite. The web UI surfaces a per-ticker history strip and a stability badge that highlights when the top count's identity persists across runs — useful for separating transient signals from a maturing thesis.
The write is best-effort and never raises, so a corrupted DB or full disk will not interrupt analysis output.
LLM reranking (optional)
wave-alpha can rerank the engine's candidate counts and narrate them using an Anthropic API key (BYO).
# One-time setup
uv run wave-alpha config set api_key sk-...
# Live API; responses cached to ~/.wave_alpha/llm_cache.sqlite
uv run wave-alpha analyze AAPL --llm-mode live
# Reproducible — raises on cache miss, no key required
uv run wave-alpha analyze AAPL --llm-mode cached
# Engine-only baseline (default; mandatory for backtest comparisons)
uv run wave-alpha analyze AAPL --llm-mode disabled
# Tune the engine/LLM blend
uv run wave-alpha analyze AAPL --llm-mode live --alpha 0.6
Final ranking formula: final = coh_multiplier × (alpha × engine_score + (1 − alpha) × llm_prob).
[!IMPORTANT] Privacy 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 bars. No watchlist. No API key in the payload. Nothing else.
Backtest harness
Honest accuracy starts with a leak-free backtest. Lookahead is hard-enforced by PointInTimeView at every fetch site, with a synthetic-leak unit test that plants a violation and verifies the assertion fires.
# Count layer — top-1 / top-3 forward direction hit rate
uv run wave-alpha backtest count \
--universe data/universe_curated.txt \
--start 2020-01-01 --end 2024-12-31 \
--step 5 --out reports/count.md
# Pivot layer — per-degree confirmation rate + Brier score
uv run wave-alpha backtest pivot \
--universe data/universe_curated.txt \
--start 2020-01-01 --end 2024-12-31 \
--out reports/pivot.md
# Trade layer — hit rate, avg R, expectancy, profit factor, max drawdown
uv run wave-alpha backtest trade \
--universe data/universe_curated.txt \
--start 2020-01-01 --end 2024-12-31 \
--rules my-rules.yaml \
--out reports/trade.md \
--json reports/trade.json \
--trades-csv reports/trades.csv
All three layers run --llm-mode disabled by construction — headline numbers are reproducible without an API key. The bundled data/universe_curated.txt ships 50 tickers across sectors and vol regimes; pass your own with --universe my-list.txt.
[!WARNING] The 4h timeframe is resampled from yfinance's 1h data, capped at ~730 days of history. Backtests reaching back further degrade gracefully to 2-timeframe coherence (weekly + daily) and emit a startup warning. The trade-layer report's
4h coverageline and thetf_countcolumn in the CSV ledger let you slice ablations on this dimension.
How it works
OHLCV bars (weekly / daily / 4h)
→ PointInTimeView(bars, as_of) # lookahead-safety boundary
→ detect_multi_degree (ATR-scaled zigzag) # pivots at degrees 0..N
→ enumerate_counts(pivots) # YAML templates + fib + recency → top-K
→ three_way coherence(W, D, 4h) # multiplier on engine_score
→ [optional] LLM rerank # blended via blend_scores(alpha, …)
→ derive_signal(top counts) # entry / stop / target / RR
Every consumer (CLI, web, scan) tolerates partial results — pipeline.run_analysis always returns an AnalyzeResult, even with empty bar series.
For full design rationale see docs/superpowers/specs/2026-05-03-wave-alpha-design.md.
Right-edge models
Three implementations of the ConfirmationModel protocol — selected via RightEdgeConfig.kind:
| Kind | What it is | Artifact |
|---|---|---|
heuristic |
Hand-coded weighted sum | none |
calibrated_heuristic |
Heuristic + per-degree Platt scalers | JSON |
logistic |
Full logistic regression with stable feature order | JSON |
Train artifacts via wave-alpha train right-edge --end 2024-12-31 [--with-fib-features] [--write]. Promotion is gated by paired bootstrap on Brier score and per-degree ECE; only PROMOTE / PROMOTE_CALIBRATION verdicts write without --force.
Persistence
All user-facing state lives under ~/.wave_alpha/:
| Path | Purpose |
|---|---|
config.yaml |
API key, model, prefs |
cache.sqlite |
OHLCV bar cache |
llm_cache.sqlite |
LLM response cache |
history.sqlite |
Per-ticker snapshot history |
watchlist.json |
Saved tickers |
scans/<scan_id>.json |
Persisted scan reports |
Development
uv sync --extra dev
uv run pytest # full test suite
uv run pytest tests/elliott -k impulse # filter by folder + name
uv run pytest tests/test_pipeline.py::test_x -x # single test, fail fast
uv run ruff check . # lint
uv run ruff format . # format
Pattern definitions live in src/wave_alpha/elliott/templates_data/*.yaml — each lists waves and constraints with severity: hard | soft. Adding a pattern is a YAML drop-in (force-included in the wheel via pyproject.toml); no code change is needed unless new constraint operators are introduced.
Disclaimer
This software is for educational and research use only. It is not financial advice.
See DISCLAIMER.md for the full text. By using wave-alpha you accept that
trading decisions are solely your responsibility.
A short banner is shown on first CLI invocation. To suppress it (e.g. in CI), set
WAVE_ALPHA_NO_DISCLAIMER=1.
License
Released under the MIT License.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file wave_alpha-0.8.0.tar.gz.
File metadata
- Download URL: wave_alpha-0.8.0.tar.gz
- Upload date:
- Size: 996.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
ec913b8756c69f026fbdab2c24f80336e2fda32cfeec7632e32bee92f19c69ca
|
|
| MD5 |
6614539f5d370df3dd63ed72387e6c69
|
|
| BLAKE2b-256 |
705a6efe7655ce66e5eb8dcd4bb628d7cc37e6e21f7272b4c15c74632393a205
|
Provenance
The following attestation bundles were made for wave_alpha-0.8.0.tar.gz:
Publisher:
publish.yml on chen-star/wave-alpha
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wave_alpha-0.8.0.tar.gz -
Subject digest:
ec913b8756c69f026fbdab2c24f80336e2fda32cfeec7632e32bee92f19c69ca - Sigstore transparency entry: 1500362489
- Sigstore integration time:
-
Permalink:
chen-star/wave-alpha@e7b9a37c2785432742e29e57200a21396756ceb0 -
Branch / Tag:
refs/tags/v0.8.0 - Owner: https://github.com/chen-star
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e7b9a37c2785432742e29e57200a21396756ceb0 -
Trigger Event:
push
-
Statement type:
File details
Details for the file wave_alpha-0.8.0-py3-none-any.whl.
File metadata
- Download URL: wave_alpha-0.8.0-py3-none-any.whl
- Upload date:
- Size: 263.0 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? Yes
- Uploaded via: twine/6.1.0 CPython/3.13.12
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
f40b7e3f6b7dc7364ad9d0bcb1c4173adf936f5e915cb646e8bc4e4235eb05e4
|
|
| MD5 |
80a304062236b3a81c4110c8a8733e56
|
|
| BLAKE2b-256 |
7045f5a4c9d832ea2ca6d53c0e38d26beda4b47b387c71dc690442ff2539d34e
|
Provenance
The following attestation bundles were made for wave_alpha-0.8.0-py3-none-any.whl:
Publisher:
publish.yml on chen-star/wave-alpha
-
Statement:
-
Statement type:
https://in-toto.io/Statement/v1 -
Predicate type:
https://docs.pypi.org/attestations/publish/v1 -
Subject name:
wave_alpha-0.8.0-py3-none-any.whl -
Subject digest:
f40b7e3f6b7dc7364ad9d0bcb1c4173adf936f5e915cb646e8bc4e4235eb05e4 - Sigstore transparency entry: 1500362588
- Sigstore integration time:
-
Permalink:
chen-star/wave-alpha@e7b9a37c2785432742e29e57200a21396756ceb0 -
Branch / Tag:
refs/tags/v0.8.0 - Owner: https://github.com/chen-star
-
Access:
private
-
Token Issuer:
https://token.actions.githubusercontent.com -
Runner Environment:
github-hosted -
Publication workflow:
publish.yml@e7b9a37c2785432742e29e57200a21396756ceb0 -
Trigger Event:
push
-
Statement type: