Chart patterns, drawn — not just labelled.
Most libraries tell you a Head & Shoulders exists and hand you a bar index. CryptVault computes the geometry — shoulders, armpits, the sloped neckline, the projected target — and draws it onto the candles, where you can actually judge it.
Geometry is computed in Python. The browser only paints it.
Pattern maths lives next to pattern detection, not in a rendering layer. The chart
receives a flat list of primitives in [timestamp, price] space, so a
diagram stays welded to the candles through any pan or zoom.
Fetch
OHLCV for any Yahoo Finance symbol — crypto, equities, indices.
Detect
Every detector runs and returns pivot indices in an extra payload.
Snap
Pivots move to the true swing high or low within ±2 bars, so lines touch the wicks.
Emit
shapes.build() returns primitives tagged with the pattern they belong to.
Paint
One trading-vue overlay maps time and price to screen and strokes the canvas.
Every family gets its own construction.
These figures are not illustrations. Each one is rendered from the output of
cryptvault.desktop.shapes — the same function the desktop chart calls.
Four primitives, and no JavaScript to add a pattern.
Because the renderer only understands four shapes, teaching CryptVault a new diagram means writing a Python function that returns them. Nothing in the browser changes.
| Primitive | Draws |
|---|---|
| poly | Polyline, optionally dashed and filled |
| dot | Pivot marker |
| text | Boxed label, nudged clear of its neighbours |
| mark | Triangle pointing at a bar |
- Grouped. Every primitive is tagged
name@bar, so two detections of the same pattern stay separate. - Selective. The three strongest draw on load; clicking a pattern isolates it.
- Resilient. A malformed pivot payload is skipped, never raised — a bad pattern cannot blank the chart.
- Forecast, in beta. The same four primitives draw the projection past the last bar: a dashed path to the target inside a volatility envelope. A cone, not a calibrated interval — hence beta.
# cryptvault/desktop/shapes.py def _head_shoulders(f, extra, idx, color, inverse, name): ls, head, rs = extra["ls"], extra["head"], extra["rs"] pick = f.trough if inverse else f.peak between = f.ridge_between if inverse else f.valley_between p_ls, p_h, p_rs = pick(ls), pick(head), pick(rs) n1, n2 = between(ls, head), between(head, rs) # the neckline slopes through both armpits slope = (n2[1] - n1[1]) / (n2[0] - n1[0]) return [ _poly([p_ls, n1, p_h, n2, p_rs], color, 2.2), _poly([n1, [t_end, neck_end]], color, 1.6, DASH), _dot(p_ls, color), _dot(p_h, color, 5.0), _dot(p_rs, color), _text(p_ls, "LS", NEUTRAL), _text(p_rs, "RS", NEUTRAL), ]
A local page, a stdlib server, no build step.
python launch_desktop.py starts an http.server on
127.0.0.1 and opens a native window if pywebview is installed, your
browser otherwise. Charts render with
trading-vue-js; Vue and the
chart bundle are pinned and cached on first launch, so the interface runs offline
afterwards. No Electron, no npm.
Three commands to a chart.
Python 3.9 or newer. Add pip install pywebview for a native window
instead of a browser tab.
git clone https://github.com/MeridianAlgo/Cryptvault.git cd Cryptvault pip install -r requirements.txt # desktop terminal python launch_desktop.py # or the command line python cryptvault_cli.py BTC 90 1d
- Nine timeframes from 1-minute bars to weekly, intraday included.
- 50+ patterns across reversal, continuation, candlestick, harmonic and divergence families.
- ML ensemble at 1.6–2.4% MAPE on major pairs, weighted by rolling out-of-fold validation.
- Python API and CLI for portfolio analysis, comparison and batch runs.