Randomized non-sequential trading simulator.
Trading cycles — random ticker × random window, drawn from ~34k listed and delisted US
equities (daily bars, split-adjusted, survivorship-bias-free) — are played in shuffled order.
Each cycle is anonymized: prices rebased so the first candle opens at 100, dates mapped onto a
fixed reference era, ticker hidden. No memory of prices, dates or tickers can leak into your
decisions. Complete cycles, then analyse state/results.csv. Fake edges will be exposed.
python3 -m venv .venv
.venv/bin/pip install -e .
.venv/bin/python main.pyFirst launch scans the equity store into cache/catalog.parquet (~1 min) and generates the
shuffled cycle book (state/cycles.json). Cycle windows are filtered: no warrants/units/rights
or ETFs, ≥$200k median daily dollar-volume in-window, no sub-$1 prints, no dead tape — knobs in
vertex/config.py. python -m vertex.cycles --reset regenerates the book (losing progress);
python -m vertex.catalog --rebuild rescans the store. Set Config.market = "btc" for the
legacy BTC 15m mode.
Resets (close the app first): full restart = rm -rf state — trades, progress and the
played-window ledger all go; the next launch regenerates a fresh book. Partial: delete
state/results.csv (trades only), state/played.json (allow re-deals again), or run
--reset above (new book, trades/ledger kept). cache/ never needs touching.
| Input | Action |
|---|---|
Space / ▶ |
reveal the next candle — the clock is bar-indexed, weekends/halts don't exist (collapses brackets; a fill pops its play back into focus). Shift+Space fast-forwards 5 bars |
| on-chart feedback | hover data strip (O/H/L/C · Δ% · range), dotted divider at window start, ▲/✕ trade markers, live R on filled brackets, bar N/120 progress, Done recap with net R |
Σ / A |
analysis panel: equity in R, rolling form, R distribution, MAE/MFE map, headline stats with recognized/side/LC filters; refreshes on every commit |
| double-click a candle | draft a play (dashed entry): snaps to the candle's nearest O/H/L/C, SL/TP seeded from ATR; the level's side of the current price decides long vs short |
Enter |
confirm the draft into a live play — a draft that isn't confirmed never counts: double-clicking elsewhere moves it, advancing discards it |
| drag entry line | move the whole bracket (focused play only; locked once filled) |
| drag SL / TP line | adjust exits — snaps to nearby candle OHLC levels |
| click a table row | pop that play into focus; other plays collapse to slim lines |
Esc / Del / right-click / row ✕ |
discard the draft if one exists, else cancel the focused pending play (filled positions only resolve at SL/TP) |
P / PLAYS strip |
collapse or expand the plays drawer — collapsed, the chart takes all the space; it never reopens itself (the strip summary keeps updating) |
| pan / zoom | the ticker's full past history is loaded — scroll back TradingView-style |
| price axis | drag to scale (y goes manual and stays put while you scroll); chart-drag then pans both axes; double-click the axis to restore auto-fit |
1 2 3 |
D / W / M timeframes (weekly/monthly aggregate the dailies; BTC mode keeps 1m–4h) |
| ✓ Done | commit the cycle: results are saved only here (a cycle is atomic) |
| cycle completion | trade the whole 120-bar window; Done rotates whenever you choose. (plays_per_cycle can cap resolved trades per chart if you ever want forced rotation.) Committed windows go into state/played.json — a ledger that survives book resets, so no window range is ever dealt twice |
| recognized | flag the cycle if you recognized the underlying chart (excluded from clean stats) |
Drawing toolbar (left edge; every picked point gets a weak OHLC magnet, TradingView-style):
| Tool | Use |
|---|---|
| ✛ | select / place plays; hovering a drawing reveals its drag handles (click = persistent select, Del removes); drag handles to edit, magnet applies |
| % | two clicks → vertical % between the prices (horizontal span irrelevant) |
| ╱ | ray: anchored at the first click, propagates through the second to the chart edge |
| ─ | horizontal ray, one click |
| ✎ | freehand brush, drag |
| φ | fib retracement, two clicks — personal preset (0 · ⅓ · 0.381 · 0.618 · 0.66 · 0.786 · 0.825 · 0.886 · 1) |
| 🗑 | clear all drawings (they also reset with each new cycle) |
Committing a drawing returns to select mode; Esc aborts one mid-draw. Drawings
survive timeframe switches (anchored to time + price, not bar indices).
Fills replay the underlying 1m data: entries are touch-limits nudged 1bp against you, TP can never trigger on the bar that filled you, SL wins when a bar spans both, and MAE/MFE are recorded per trade. Results are stored de-anonymized (real symbol, dates, prices).
vertex/— headless engine (config,data,session,orders,results,cycles,catalog) +ui/docs/index.html— living codebase & functionality documentation (open in a browser)tests/— engine tests (.venv/bin/pytest)legacy/— the v0.6 single-file app, kept for reference