Open Net Worth
Open Net Worth is an open-source personal AI wealth assistant you run yourself: one ledger for your whole financial life, worked by an AI agent you control.
翻譯準備中
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證VWAP Blue — dual VWAP desk (blue day + orange anchor) · KER regime · grade A · free multi-provider
翻譯準備中
正在載入完整 README。 以下為已儲存的摘錄。
Best-of Blueline + VWAP One in the VWAP desk layout, with Modern-VWAP-style
adaptive bands and Kaufman Efficiency Ratio regime gates (v1.5.0).
Research scanner, no demonstrated edge: replayed on sessions no rule was tuned on, its grade-A
triggers lost money after costs on US equities and showed no edge on crypto
(honest results).檢視完整 README ↗Best-of Blueline + VWAP One in the VWAP desk layout, with Modern-VWAP-style adaptive bands and Kaufman Efficiency Ratio regime gates (v1.7.0).
Research scanner, no demonstrated edge: replayed on sessions no rule was tuned on, its grade-A triggers lost money after costs on US equities and showed no edge on crypto (honest results).
| Web demo (GitHub Pages) | https://21e8-miner.github.io/vwap-blue/ |
| Source | https://github.com/21e8-miner/vwap-blue |
| Related desk | https://21e8-miner.github.io/blueline-orangeline/ |
The Pages demo runs the desk's own engine in the browser: engine.js is a line-by-line port of
engine.py, and CI runs both on hundreds of synthetic sessions (gap fades, trend days, reclaims,
DST weeks, crypto, broken feeds) and compares every output field (tests/test_engine_parity.py).
It pulls 14 days of free 5m Yahoo bars per name through a CORS proxy and applies the desk's scan
pipeline: session $ volume floor → engine → stale-bar guard → grade floor → rotation rank. Unlike
the local desk it scans a smaller pool (≥160 names vs ~480), grades crypto on Yahoo's bars rather
than exchange candles, has no VWAP One cross-check, uses the last bar's close rather than a live
quote, and keeps no forward ledger. cf-pages/ is an identical copy for Cloudflare Pages (a test
keeps it so). With your own Moontower key (kept in the browser, sent only
to api.moontower.ai) the Moontower lens selector adds the options market's prior-close reading of
each row and filters on it (what it found), and the chart pane can
quote a clicked row's bracket as a vertical (contract.js: the call or put struck nearest the entry
against the first strike at or beyond the target, on the first expiry after today) from Moontower's
end-of-day chain, 2 credits a name. The chain is last night's: Moontower's derived readings (IV
surface, rank, skew, VRP) update intraday with a 15-minute delay, but contract quotes land after the
close, so a premarket plan is priced off the prior close and a live fill still needs your broker.
The contract stat also says whether the spread is fillable (long leg's market wider than a third of
the cost, or no open interest and no volume, is flagged) and can size an index hedge for the stock
position (/v1/hedge-ratios: beta-weighted vs SPY, as SPY shares). With a lens on, the MTW cell
leads with the bracket in implied daily moves (s0.4 t0.9: stop and target as fractions of
IV30/√252) and the meta line counts the board's tight stops and priced events. The page itself is
pared to what an intraday desk uses: the header is the ticker list, the grade floor, the Moontower
lens, the actionable toggle and Scan / Live; everything set once (show-N, the $vol floor, the
Moontower key and cap, feed mode, live interval, proxy) sits behind the ⚙. The table carries the
plan columns only: the VWAP levels, σ distance and regime live in the Price and State tooltips. The
meta line reads shown · actionable · live · grade A · session · Moontower · time, with the scan
details (pool, floor, regimes, feeds, seconds) in its tooltips. The results banner folds to one line.
Moontower is paid for in three layers, each at its own rate, so a day on the page costs a handful
of credits (2 a call; a cap per ET day sits in the ⚙, default 60, with the spend shown beside it).
The daily layer (directory, prior-close cockpit, earnings, a month of skew, the idea lists) is pulled
once per day for the board's candidates. The intraday layer is one cockpit call for those candidates
(up to 100 names) during regular hours, only when the 15-minute slot turns or a new name enters the
board (new names coalesce for a minute): Moontower's rows are 15-minute delayed, so polling faster
returns the same row. Live IV30 shows as IV28 →33 in the cell and feeds the sizing (stop and target
in implied moves) and the IV lenses; everything else stays the prior close the replay graded. Chains
are end of day: after 16:20 ET the page pulls today's chain once for the grade-A names on the board
(within the cap), keeps every chain for five days, and intraday re-marks last night's vertical at the
live price with Black–Scholes (contract.js remarkContract, each leg's end-of-day IV held fixed) so
the contract stat updates all session without a call.
The full live desk (5m hybrid feeds, live loop, chart pane, forward ledger) runs locally on :8791.
| From | What |
|---|---|
| VWAP One | Scanner left · chart right, free multi-provider rotate, live loop, edge rank |
| Blueline | Blue day VWAP ± volume-weighted σ · orange prior-day anchor · gap MR · grades |
| v1.2 | KER regime gate · adaptive σ mult · grade A desk default · universe rotation · One conflict demotion · partial/time-stop backtest · walk-forward grid |
| v1.3 | 10× scan pool (~480 names) · session $ volume filter ($2M equity / $0.5M crypto) · rank by gap×RVOL×edge×$vol |
| v1.3.1 | Prefix-honest session replay · mdrev-in-chop demoted off A desk |
| v1.4 | Honest replay: next-bar-open fills, R net of costs, session-clustered CIs · stale-bar guard · forward signal ledger |
| v1.4.1 | Prior-close fix: gaps were measured from the prior session's 09:30 close instead of its last RTH bar · Pages demo runs the desk engine (engine.js, parity-tested) · round-trip cost in R on every plan · blocked fades badge WATCH, not TRIGGER |
| v1.5.0 | Crypto gets a 24h session: blue, orange, RVOL and signals use the whole ET day, the prior close is the prior day's last bar, and there is no gap fade (a 24/7 market has no opening gap) · first crypto replay (replay_crypto.py) · the session replay grades every bar as the desk saw it and closes equity trades by 16:00 (causal_check.py re-runs its old end-of-day trigger search) |
| v1.6.0 | mdrev gets a real target: the first level beyond entry among today's VWAP, today's extreme before the reclaim, the prior session's regular-hours extreme and close (engine._md_target); with none, the plan has no target and cannot grade A. v1.5.x stretched a fixed max(1.5 × risk, 0.4%), so every such R:R read 1.50 and the R:R gate never applied · the rule and a missing-RVOL gate are engine options (md_target, rvol_missing), compared in md_target_check.py · parity now covers every option |
| v1.7.0 | Grade A means a multi-day reclaim. On 59 replayed sessions the gap fade's direction call did worse than its mirror (−0.21R vs −0.09R) while the reclaim's was the only one with a hint (+0.33R ± 0.19), so a fade, alone or with a reclaim, is capped at grade B (); the desk's default floor moves to B, so the board still shows the fades · the column shows every row's class as it replayed (; the capped fades' record is the paired v1.6.0 replay's on the same bars, marked A→B, since no grade-A replay takes them any more) · the forward ledger records the capped fades too, reported beside grade A · two refinements from the Oct 26 tape were replayed paired and (, ): a floor on the reclaim's target distance (; the nearest level was cents from entry on 180 of 1,554 holdout reclaims) left the mean where it was (+0.02R → +0.05R ± 0.08 at 1R, with 754 fewer trades) and re-arming a stopped fade on a fresh break (, replay ) gave second trades of −0.21R ± 0.11 in sample and +0.02R ± 0.11 on the holdout · a stopped fade now stays STOPPED instead of flapping to TREND BLOCK on later bars · every row carries the OU of its close − blue deviation (, 60 bars, AR(1); ): the fastest-reverting third (t½ ≤ 4.6 min on 5m bars, β ≤ 0.5 — bar-to-bar noise around blue) lost on every sample (equities −0.12R ± 0.05 vs ≈ 0 for the rest, both halves of the window; crypto reclaims −0.19R ± 0.09, longs −0.42R), the opposite of the source idea's claim that fast reversion is conviction; a reading in the Reg tooltip, not yet a gate · two more negative results (, ): on the crypto year 95% of reclaims move with the basket (628 of 661), |
git clone https://github.com/21e8-miner/vwap-blue.git
cd vwap-blue
python3 -m pip install -r requirements.txt
python3 app.py
# → http://127.0.0.1:8791/
Env:
VWAP_BLUE_LIVE=0 — disable auto liveVWAP_BLUE_LIVE_SEC=45 — scan intervalVWAP_BLUE_PORT=8791VWAP_BLUE_GRADE_MIN=B — desk grade floor (default B since v1.7.0: gap fades show at B, reclaims at A)VWAP_BLUE_POOL_MULT=10 — universe pool multiplier (was effectively ~3× / 48 names)VWAP_BLUE_MIN_DVOL=2000000 — equity $ volume floor (0 = off), on the larger of a stock's ET day
so far and its prior session. Crypto gets a quarter of it ($0.5M at the default) on its last 24
hours of volume. A day so far is minutes old early on, after midnight ET for crypto and in premarket
for a stock once it first trades: on the day so far alone, 9.5% of the desk's stocks cleared $2M at
09:00 ET and 9% of its crypto names at 00:55. The desk's $M box and min_dvol work the same wayVWAP_BLUE_YF_RPS=20 — pace of the yfinance bulk download, in requests a second (0 = unpaced; yfinance
alone sends ~45 a second). A chunk Yahoo rate-limits (HTTP 429) pauses it 15 s and its names are asked
for again at half the paceVWAP_BLUE_MAX_BAR_AGE_MIN=15 — while the market is open, a TRIGGER on bars older than this is demoted to WATCH (STALE)VWAP_BLUE_LEDGER=0 — stop recording live grade-A triggers to data/signals/Gap extends away from blue (session VWAP, hlc3×volume). After K consecutive bars beyond blue by adaptive volume-weighted σ → confirm. Target orange (prior-day-anchored VWAP). Stop = blue ± ATR/σ × adaptive mult.
rvol_n# Prefix-honest multi-session replay (matches live 5m desk, ~1mo): every bar graded as the desk saw it,
# fills on the bar after the trigger (+2 bps), equities out by the 16:00 close; prints net-of-cost R
# with session-clustered CIs.
python3 replay_sessions.py --max-tickers 96 --grade-min A
python3 alpaca_bars.py --tickers-from desk --start 2024-11-01 --out data/backtests/alpaca_5m_2y.pkl # years of 5m SIP bars (free Alpaca keys)
python3 orb_rvol_check.py --bars data/backtests/alpaca_5m_2y.pkl --out research/orb_rvol_check_<date>.json # opening-range continuation by RVOL, fade as mirror
python3 replay_sessions.py --range-60d --save-bars data/backtests/eq_60d.pkl # 60 days of 5m bars (Yahoo chart API), ~59 sessions
python3 replay_sessions.py --save-bars data/backtests/equity_bars.pkl # keep the fetch: Yahoo's window moves
python3 replay_sessions.py --bars data/backtests/equity_bars.pkl # replay those bars again
python3 replay_sessions.py --entry trigger_close # the old, optimistic trigger-close fill
# Honest stats for a saved replay, no fetching
python3 replay_sessions.py --rescore research/replay_2026-08-12.json
# The crypto names (the replay above takes the first N names of universe.txt: all equities)
python3 replay_crypto.py --save-bars data/backtests/crypto_bars.pkl
python3 replay_crypto.py --bars data/backtests/crypto_bars.pkl --utc-days # crypto's day from 00:00 UTC
python3 replay_crypto.py --source coinbase # Coinbase bars instead of Yahoo
python3 replay_crypto.py --source binance-vision --days 365 --jobs 8 --save-bars data/backtests/crypto_bv.pkl
# a year of Binance spot 5m bars from data.binance.vision (no key; checksum-verified; cached in data/binance_vision/)
# bars cached before the Yahoo symbol map hold other tokens under ARB/TON/JUP-USD: add
# --exclude ARB-USD,TON-USD,JUP-USD
# The replay's old end-of-day trigger search on the same bars: what it missed, how it scored
python3 causal_check.py --bars data/backtests/equity_bars.pkl
# What each setup class did on the replays the page cites → research/evidence_v<engine>.json, pasted
# into the page as its Record column (the page test recomputes it from the linked files)
python3 evidence.py --embed index.html cf-pages/index.html
# mdrev target rules and the missing-RVOL gate on the same bars, plus a 60-day holdout
python3 md_target_check.py --fetch-holdout data/backtests/holdout_60d.pkl
python3 md_target_check.py --bars data/backtests/equity_bars.pkl --holdout data/backtests/holdout_60d.pkl
# Breakout vs fade at the engine's own gap states (first band break, fakeout): same events, both
# directions, same exits, net of costs, session-clustered (60 days of 5m bars, first 96 equities)
python3 direction_check.py
# The Moontower lens: the options market's reading of each name at the prior close (api.moontower.ai:
# earnings distance, IV30 and its weekly change, monthly VRP, monthly return z, Buy/Sell Vol idea
# lists) as yes/no lenses on a replayed trade, pass vs fail, session-clustered. Needs a key
# (MOONTOWER_API_KEY or ~/.config/active_projects_secrets/moontower_api_key); 2 credits a call; the
# raw pulls stay in the git-ignored data/moontower/ cache, only the per-lens table is written.
python3 moontower_check.py --replay research/replay_2026-10-29_v1.7.0.json --pull --embed index.html cf-pages/index.html
# Moontower's own nightly idea lists (Buy/Sell Vol, Long/Short Calendar) scored on the next five sessions,
# every filter the scanner offers, picked vs the rest; reads the same cache, fetches nothing
python3 moontower_ideas_check.py
# Four follow-ups on the same trades: the bracket re-cut in implied moves (paired re-simulation), a
# universe regime gate, the post-earnings gap both ways, index-hedged R, and the grade-A vertical replayed
# (prior-close chains in data/moontower/chains/); needs the replay's saved bars and SPY's 60-day bars
python3 moontower_deeper_check.py --replay research/replay_2026-10-30_v1.7.0.json --bars data/backtests/equity_bars_2026-10-30.pkl
# Forward record of live grade-A triggers (recorded automatically by the desk)
python3 ledger.py resolve # after the close: resolve the session's signals
python3 ledger.py report # net R, session-clustered CI, by setup mode x regime
# Same-day leftover-bar check (thin n — do not use for expectancy)
python3 backtest_today_scans.py --blue-only --grade-min A --model classic
# Parameter grid on current free bars (in-sample: picks and scores on the same bars)
python3 walkforward.py --quick
python3 walkforward.py --max-tickers 20
Grade ≥ A at the trigger bar · 5m bars · R net of round-trip costs (0.08% equity, 0.15% crypto,
converted per trade: cost ÷ risk) · ± session-clustered standard error (honest.py: setups on
the same day share the tape, so ~400 trades from 22 sessions are ~22 independent draws). Verdicts
need ≥ 10 sessions and |t| past Student's t with (sessions − 1) degrees of freedom at two-sided 5%,
never less than 2: 2.26 at 10 sessions, 2.09 at 21, 2.00 at 61 (before Oct 23 the bar was a flat 2;
no verdict in these tables changes). Every replay also scores a mirror: the same bracket the
other way from the same bar, so trade − mirror shows what the trigger's direction adds after the
stop, target and costs, which the mirror shares.
Since Oct 4 the replay grades each bar as the desk showed it then, on the bars up to that one, and trades the first tradeable trigger (bar by bar); before, it took each session's trigger from the end-of-day row (end of day). Equities now exit by the 16:00 close (16:00), not at the last after-hours bar, ~19:55 ET (after hours). Crypto holds to its ET day's last bar either way.
universe.txt)| sessions | role | engine | triggers · exit | fill | n | gross R | net R ± SE | verdict |
|---|---|---|---|---|---|---|---|---|
| Jul 14 – Aug 12 | in-sample (rules tuned here), all A | v1.3 ¹ | end of day · after hours | trigger close | 419 | +0.22 | +0.13 ± 0.16 | inconclusive |
| Jul 14 – Aug 12 | in-sample, mdrev-in-chop removed | v1.3.1 ¹ | end of day · after hours | trigger close | 312 | +0.33 | +0.23 ± 0.18 | inconclusive |
| Sep 3 – Oct 2 | out of sample | v1.3.1 ¹ | end of day · after hours | next bar open +2 bps | 265 | −0.15 | −0.27 ± 0.13 | negative (t −2.1) |
| Sep 3 – Oct 2 | out of sample | v1.3.1 ¹ | end of day · after hours | trigger close | 266 | −0.13 | −0.25 ± 0.13 | inconclusive (t −1.9) |
| Sep 3 – Oct 2 | out of sample, prior close fixed | v1.4.1 | end of day · after hours | next bar open +2 bps | 295 | −0.11 | −0.23 ± 0.12 | inconclusive (t −1.9) |
| Sep 3 – Oct 2 | the same refetched bars, old prior close | v1.4.0 ¹ | end of day · after hours | next bar open +2 bps | 280 | −0.16 | −0.28 ± 0.12 | negative (t −2.4) |
| Sep 3 – Oct 2 | out of sample, refetched | v1.5.0 ² | end of day · after hours | next bar open +2 bps | 292 | −0.10 | −0.22 ± 0.12 | inconclusive (t −1.9) |
| Sep 3 – Oct 2 |
¹ Measured every gap from the prior session's 09:30 close (fixed in v1.4.1). August's 5m bars
are past the free data window, so its rows cannot be re-run. The v1.4.1 and v1.4.0 rows share one
fetch; it reached slightly further back than the morning fetch behind the 265-trade row (19 more
trades on Sep 3–4, 261 of the 265 in common).
² v1.5.0 changed only crypto: on one fetch v1.4.1 and v1.5.0 produce the same 292 equity trades,
field for field. That fetch starts later on Sep 2 than the v1.4.1 row's (Sep 2 is the first
replayed day's prior session and part of the early RVOL baselines), so 285 of the 295 recur.
³ The fetch replay_sessions.py --max-tickers 96 makes, taken Oct 4 at 15:07 ET and replayed from
that cache (--bars): Yahoo's 5m window is the last 32 days, so later that day a fetch had no
regular-session bars from Sep 2, the first replayed day's prior session (and after 20:00 ET none
from Sep 2 at all). Same window as the rows above, with two differences. All 96 names: the Oct 4 files
above replay only the 92 that traded in the morning v1.4.0 run, never PINS, DUOL, HIMS or ACHR (5
trades here). And this fetch starts Sep 2 at 15:05 ET instead of 12:45, which moves orange's seed on
Sep 3 and an RVOL baseline on Sep 4: on the 92 names, bar by bar and after hours, it gives 423 trades
at −0.21R against 431 at −0.23R, the same trades from Sep 5 on. The old replay (end of day · after
hours) on these bars: 289 trades, −0.18R ± 0.12 (t −1.5).
⁴ Yahoo's chart API serves 60 days of 5m bars (range=60d); the desk's own fetch asks for 32.
Fetched Oct 19 in the evening (md_target_check.py --fetch-holdout), so it overlaps the September
rows above and adds Jul 28 – Aug 29 and Oct 5 – 19. Paired on these bars, v1.6.0 keeps 627 of
v1.5.0's trades, drops 467 (multi-day reclaims with no real level beyond entry) and adds 27; the
per-session difference is −0.03R ± 0.05 (t −0.6).
⁵ The 480 v1.6.0 grade-A trades that v1.7.0 grades B: the gap fades alone and with a reclaim. Their
direction call did worse than their mirror, −0.11R ± 0.17; the 174 reclaims' did better, +0.33R ± 0.19
(method.paired_v1_6_0_same_bars in the v1.7.0 file).
What this says:
md_target_check.py
replays five real-level rules on the September bars and on 38 other sessions: none is better
than the stretch in both, and the stretch itself is flat (−0.13R in September, +0.02R
elsewhere). v1.6.0 takes the nearest level on principle, so that R:R and its gate mean
something, not because it scored best. Making a missing RVOL count as thin halved the trades
without helping, so it stays an option, off.causal_check.py re-runs the old search on a
cached fetch.universe.txt; this fetch had the right Yahoo 5m bars for 36)No replay before v1.5.0 included crypto, yet the page graded it. replay_crypto.py runs the same
replay on Yahoo's 5m bars (the page's feed; about half its 5m crypto bars report zero volume),
complete ET days only, on sessions no rule was ever tuned on. Under ARB-USD, TON-USD and JUP-USD
Yahoo lists other tokens (ARbit, TON Token, a second Jupiter), so those are left out; a first
version of these results included them (4 v1.5.0 trades: 149 instead of 145, ± 0.12 instead of 0.13).
| sessions | engine · crypto session | bars | n | gross R | net R ± SE | verdict |
|---|---|---|---|---|---|---|
| Sep 5 – Oct 3 | v1.4.1 · equity clock: 00:00–16:00 ET, gap from the prior 15:55 close · end-of-day trigger search | Yahoo | 196 | −0.40 | −0.91 ± 0.17 | negative (t −5.3) |
| Sep 5 – Oct 3 | v1.4.1, graded bar by bar (the replay's search since Oct 4) | Yahoo | 245 | −0.24 | −0.75 ± 0.16 | negative (t −4.8) |
| Sep 5 – Oct 3 | v1.5.0 · the whole ET day, no gap fade | Yahoo | 145 | +0.08 | +0.01 ± 0.13 | inconclusive (t 0.0) |
| Sep 5 – Oct 3 | v1.5.0 rules with the day starting 00:00 UTC | Yahoo | 150 | −0.28 | −0.35 ± 0.10 | negative (t −3.4) |
| Sep 5 – Oct 3 | v1.4.1 with only its gap fade switched off | Yahoo | 137 | +0.09 | +0.01 ± 0.11 | inconclusive (t 0.1) |
| Sep 5 – Oct 3 | v1.4.1 · end-of-day trigger search | Coinbase, 43 names | 257 | −0.53 | −0.98 ± 0.12 | negative (t −8.3) |
| Sep 5 – Oct 3 | v1.5.0 | Coinbase, 43 names | 128 | +0.18 | +0.13 ± 0.17 | inconclusive (t 0.7) |
| Sep 20 – Oct 18 | v1.6.0 · mdrev to the nearest real level | Yahoo, refetched Oct 19 | 76 | +0.38 | +0.31 ± 0.22 | inconclusive (t 1.4) |
| Sep 20 – Oct 18 | v1.5.0 on the same bars | Yahoo | 180 |
⁵ replay_crypto.py --source binance-vision --days 365: Binance spot 5m klines from data.binance.vision
(checksum-verified archive files, the venue's own volume; Yahoo prints zero on about half its 5m crypto
bars). All 48 crypto names except MKR-USD, which has no USDT pair there. 365 complete UTC days ending
Oct 22, 2026, replayed on the engine's ET calendar day; 244 of the 365 sessions had a grade-A trade.
All Yahoo rows replay one fetch of 36 names; the two Coinbase rows share another (on Coinbase, ARB-USD and TON-USD are Arbitrum and Toncoin). Without a gap fade no crypto trigger depends on later bars, so the v1.5.0 rows (and v1.4.1 without its fade) come out the same under either trigger search; the two v1.4.1 rows marked end-of-day can differ (the Yahoo one, graded bar by bar, is the row below it).
What this says:
providers.YAHOO_CRYPTO_SYMBOLS). The local
desk grades crypto on exchange candles instead (see History / RVOL).Treat the desk as a research scanner. The forward ledger (ledger.py) records every live
grade-A trigger as it is shown and scores it after the close; trust a grade, gate or learned
filter only once months of that record agree.
Re-score any saved replay without refetching: python3 replay_sessions.py --rescore <file>.
Raw JSON: research/replay_2026-08-12.json (August,
trigger-close fills) · research/replay_2026-10-04.json
(September, next-bar fills) · research/replay_2026-10-04_v1.4.1.json
(September, fixed engine; method.paired_v1_4_0_same_bars holds the old engine on the same bars) ·
research/replay_2026-10-04_v1.5.0.json (September
refetched; method.paired_v1_4_1_same_bars, method.causal_check) ·
research/replay_2026-10-04_v1.5.0_causal.json
(September, bar by bar with the 16:00 exit, all 96 names; method.causal_check: the old end-of-day
search on the same bars) · crypto:
research/replay_crypto_2026-10-04_v1.4.1.json
and research/replay_crypto_2026-10-04_v1.5.0.json
(method.paired_v1_4_1_same_bars, method.causal_check, method.sensitivity: UTC day, no gap
fade, Coinbase bars) · v1.6.0: research/replay_2026-10-19_v1.6.0.json
and research/replay_crypto_2026-10-19_v1.6.0.json
(method.paired_v1_5_0_same_bars) · v1.7.0:
(reclaims only on the 60-day bars, with the capped fades) and
(the same crypto trades as v1.6.0: crypto has no gap fade) · the target rules:
. A replay
never overwrites an existing snapshot for the same day.
direction_check.py, Jul 28 – Oct 19, 59 sessions)At the engine's first band break (2,782 events) and its first fakeout (903), the same event was
traded both ways: with the gap's extension (breakout) and against it (fade), next-bar fill, exits
at 30 / 60 min, the close, or a 1 ATR stop / 1.5 ATR target. Neither direction wins. The paired
breakout-minus-fade difference is inside the noise in 31 of 32 comparisons (|t| ≤ 1.8), and both
sides lose after costs: a round trip at a one-ATR 5m stop costs about 0.16R. The one exception,
holding a breakout to the close after a fakeout in a trend or mixed regime (+1.38R vs the fade,
t 2.1, 232 events), is what one test in 32 shows by chance. It is recorded here as a hypothesis
for the forward ledger, not a rule. Raw numbers:
research/direction_check_2026-10-19.json.
Same-day leftover-bar scans (backtest_today_scans.py) print results on a handful of trades
from one session; they are not expectancy.
band_scaling_check.py, Jul 28 – Oct 19 equities, a year of Binance crypto)The confirm band is 0.15 × σ × adapt(KER) and the stop buffer 0.35 × σ × adapt, with σ the running volume-weighted spread of the typical price about blue since 04:00. How far price actually sits from blue by time since the open, against two shuffles of the same bars: each day's returns permuted in time (which also flattens the open's volatility), and each slot's returns permuted across days (which keeps the day's volatility curve and removes only the order within the day, the fair random-walk twin).
Nothing changes in the engine. Two readings for later: a stop buffer from the slot's own deviation
profile instead of the running σ is a fair experiment for the bracket-geometry queue, and the
fade's tailwind toward blue is a few percent of the distance on crypto and about zero on equities,
under the round trip's cost. Raw numbers:
research/band_scaling_equity_2026-10-28.json,
research/band_scaling_crypto_2026-10-28.json.
VWAP Blue reads the price consensus: where the volume traded (the anchors) and whether price is
reclaiming or fading them. Moontower reads the options consensus on the
same names: how wide a range the market is paying for (IV30), whether that range is being repriced
(its weekly change), whether an information event just reset the anchor (earnings), whether the
options are cheap or rich against what the stock does (monthly VRP, ln IV/RV), how stretched the name
is on the quarter-scale anchor (monthly return z), and its own Buy Vol / Sell Vol idea lists. The page
offers each as a selectable lens (a yes/no on every row, from the prior close, with your own key;
off by default, so no calls), and moontower_check.py replays the same lenses on the engine's trades
(research/moontower_check_2026-10-30.json, embedded in the page as each lens's tooltip).
Replayed on Sep 29 – Oct 29 (23 sessions; 1,398 of the 1,556 classic trades fell on the 85 names Moontower covers), no lens reached a verdict:
| lens (grade A+B, decision-time reading) | pass | fail | pass − fail |
|---|---|---|---|
| IV30 ≥ 50% | −0.05R ± 0.05 (882) | −0.20R ± 0.07 (461) | +0.15R, t 1.7 |
| IV30 up ≥ 3 pts on the week | +0.01R ± 0.10 (436) | −0.16R ± 0.05 (907) | +0.16R, t 1.4 |
| did not report earnings today or yesterday | −0.09R ± 0.05 (1,277) | −0.38R ± 0.15 (32) | +0.29R, t 1.9 |
| stretched, |monthly z| ≥ 1.5 | −0.03R ± 0.10 (135) | −0.11R ± 0.06 (1,204) | +0.08R, t 0.7 |
| options cheap (VRP < 0) | −0.10R ± 0.08 (188) | −0.10R ± 0.06 (1,155) | 0.00R |
| options rich (VRP ≥ 0.10) | −0.11R ± 0.06 (979) | −0.08R ± 0.07 (364) | −0.03R |
| on Moontower's Buy Vol list | −0.12R ± 0.07 (558) | −0.10R ± 0.05 (694) | −0.02R |
| on Moontower's Sell Vol list | −0.07R ± 0.06 (474) | −0.13R ± 0.06 (778) | +0.06R, t 0.7 |
A second pass (same day, same replay) sized the bracket in the options market's units, the implied daily move IV30/√252 at the prior close, and added the event and skew readings:
| lens or bucket (grade A+B) | pass | fail | pass − fail |
|---|---|---|---|
| stop ≥ ½ implied daily move | +0.01R ± 0.07 (367) | −0.15R ± 0.06 (976) | +0.16R, t 1.7 |
| target within 1 implied move | −0.09R ± 0.05 (1,284) | −0.40R ± 0.20 (59) | +0.31R, t 1.5 |
| gap ≥ the implied move priced by IV10 (gap trades) | −0.29R ± 0.22 (78) | −0.21R ± 0.10 (523) | −0.08R |
| IV10 above IV30 by ≥ 5 pts (event inside the week) | −0.15R ± 0.06 (343) | −0.09R ± 0.06 (1,000) | −0.06R |
| 25Δ put skew in its top quarter (≥ 10 prior days) | −0.11R ± 0.13 (346) | −0.05R ± 0.08 (333) | −0.07R |
| 25Δ call skew in its top quarter | −0.08R ± 0.13 (78) | −0.08R ± 0.10 (605) | 0.00R |
The stop in implied-move units is the one monotone reading in the whole study: stops narrower than a quarter of the implied daily move lost −0.20R ± 0.08 (496 trades, 40% wins); a quarter to a half, −0.09R; half to one, 0.00R (58% wins); a full move or more, +0.09R ± 0.10 (47 trades, 70% wins). The engine sets stops by the day's own σ bands, and the options market says the narrow ones are inside the noise it is pricing. That is still t ≈ 1.7 on one month, a reading to carry, not a gate. Targets beyond one implied move (59 trades) lost −0.40R: the day rarely delivers them. Skew, term structure and a gap's size against the priced move carried nothing.
Moontower's own scanner, scored (moontower_ideas_check.py, research/moontower_ideas_check_2026-11-02.json):
the 23 nightly idea lists (Sep 28 – Oct 28) against the next five sessions' cockpit rows of the 85
covered names, every filter the scanner offers (score floors, top 10, no earnings within two weeks),
picked vs the names it left out, SEs clustered by snapshot:
| idea, filter score > 20 | picked | the rest | picked − rest |
|---|---|---|---|
| Buy Vol: realized (5 sessions) − IV30, vol pts | −6.7 ± 2.7 (638) | −16.6 ± 1.2 (802) | +9.9, t 3.4 |
| Sell Vol: IV30 − realized, vol pts | +17.2 ± 1.3 (540) | +9.3 ± 2.4 (900) | +7.9, t 2.9 |
| Long Calendar: 5-session change in IV90 − IV30, pts | −0.1 ± 0.6 (385) | −2.6 ± 0.5 (1,055) | +2.5, t 3.2 |
| Short Calendar: the negative of that | +2.7 ± 0.4 (354) | +1.7 ± 0.7 (1,086) | +1.0, t 1.3 |
| Buy Vol: next-day |move| ÷ implied daily move | 0.71× ± 0.07 | 0.58× ± 0.04 | +0.14, t 1.6 |
| Sell Vol: the same | 0.58× ± 0.04 | 0.67× ± 0.06 | −0.09, t 1.2 |
The ranking works relatively: every filter separates the names that went on to realize more (Buy Vol) or less (Sell Vol) than the rest, by 7–10 vol points, at every score floor and in the top 10, with or without the earnings exclusion. It does not fix the absolute sign: October realized far below implied across the board (the rest of the Buy Vol list lost 17 points; even its picks lost 7), so a Buy Vol pick was a smaller loss, and a Sell Vol pick a bigger gain, than its peers. For an intraday desk the useful line is the last two: every name moved about 0.6 of its implied daily move the next day in this quiet month, and Buy Vol picks moved a little more (0.71×, t 1.6). Caveats: the five-session windows overlap night to night, so the clustered t's are generous; "the rest" is the rest of the same list, not a market benchmark; and vol edge here is the straddle's gross, with no gamma scalping, costs or path.
Four follow-ups, same trades (moontower_deeper_check.py, research/moontower_deeper_check_2026-11-02.json,
on research/replay_2026-10-30_v1.7.0.json: Sep 30 – Oct 30, 1,364 classic trades, 35 grade A):
| study | what was done | result |
|---|---|---|
| Bracket re-cut in implied moves | stop moved to ½, ¾ or 1 implied daily move from the fill (target kept, or pulled inside one move), every trade re-simulated on the same bars, paired | In R, nothing: grade A +0.20R → +0.17R ± 0.08 at ¾ move (stop-outs 16 → 4 of 33, but the survivors just ride to the close). Net % per trade rose +0.32% ± 0.17 (t 1.9) only because the stop is 2.3× further away, so 2.3× more is risked: leverage, not edge. A+B: Δ ≈ 0 everywhere. |
| Regime gate | the prior session's universe-wide |move| ÷ implied move (median over names), sessions cut into terciles | No decision-time gate. Fades lost in every tercile (−0.29, −0.18, −0.30R); reclaims +0.06, −0.08, +0.09R. Only the same session's ratio, which you cannot know in the morning, separates (reclaims +0.27R on lively days, fades −0.43R on mid days). |
| Post-earnings gap, both ways | gap trades on a name that reported today or yesterday, and any gap ≥ the implied move IV10 priced, as the engine's fade and as its mirror | Fresh off earnings: fade −0.49R ± 0.17 (21), mirror −0.06R. Gap ≥ implied move: fade −0.42R ± 0.20 (87), mirror +0.24R ± 0.46, difference +0.66R with t 1.1, the mirror's variance is huge (Friday alone). Gaps smaller than the implied move: fade −0.23R, mirror −0.15R. A hypothesis for a "post-event continuation" mode, not a result. |
| Index-hedged R | beta to SPY from ~60 sessions of closes (median 2.1 for these names), SPY's move from the fill bar's open to the exit bar's close taken out of each trade's net % | Grade A's month was the index. Raw +0.23R ± 0.24 on 30 trades becomes −0.07R ± 0.20 hedged (Δ −0.29, t −2.4): the shorts (+0.59R raw, +0.15R hedged) were short a falling tape. A+B unchanged overall (−0.11R either way); gap fades a little better hedged (−0.26 → −0.21R). The index was a third of each trade's |P&L| at the median. |
| The vertical, replayed | 29 grade-A trades as the call/put vertical the page quotes (prior close's ask/bid; data/moontower/chains/, 2 credits each), marked by Black–Scholes at each leg's mid IV on the stock's exit and on the close | +0.11× ± 0.13 of the debit at the stock's exit, +0.20× ± 0.12 held to the close, against the same trades' +0.27R ± 0.23 in stock. A model mark (no intraday option prints), one month, 29 trades: the spread did not beat the stock and was not worse. |
The Buy Vol universe filter (item 5) is the buy_vol_idea lens above: Δ −0.02R. So of the six, one
is a reading the desk now shows (stops in implied moves), one is a caution (hedged, this month's
grade A had no edge of its own), one is a hypothesis worth a fresh window (continuation after a
gap bigger than the priced move), and three are closed.
What that says: the two sites read different things. Moontower prices the size of the expected move; VWAP Blue calls its direction against the anchor. Whether the options are cheap or rich, and whether a name is on Moontower's lists, carries nothing for these trades. The only lean is through range: a wider priced range (high or rising IV30) makes the anchor targets reachable before the stop, +0.15R with t ≈ 1.5, not a verdict. A name fresh off earnings lost −0.38R (−0.48R ± 0.19 on its 19 gap fades), the alert room's own "don't short a stock down big on earnings"; 32 trades. The lens as first drafted (no report within a day either way) showed nothing (Δ +0.01R), because sessions the day before a report did fine, and this engine is flat by the close and carries no overnight event risk, so the shipped lens is post-report only; both are in the research file. Grade A alone (45 trades) is too few to cut. Buckets were chosen after one look at a month of data: a lens is a reading to carry, not a rule, until a fresh window agrees.
An external scan (research/notes/2026-11-02_external_research.md)
found the one published intraday effect that survives costs: Zarattini–Barbon–Aziz 2024, 7,000 stocks,
the 5-minute opening-range breakout is worth nothing unfiltered and climbs from −0.02R to +0.38R as
opening relative volume rises. That is the same selection as our "gap bigger than the options priced"
lead. orb_rvol_check.py replays their rule on our bars: direction of the 09:30 bar, stop order at its
high/low until 10:30, stop 0.10 × ATR14 (--stop range: the bar's other extreme), flat at 15:25 (ahead
of the end-of-day reversal), the paper's universe (ATR14 ≥ $0.50, price > $5), the fade of the same
level as the mirror control, RVOL = 09:30 volume / its prior-14-session mean. Yahoo's 60 days were not
enough to say anything, so alpaca_bars.py pulled two years of 5-minute SIP bars with pre-market
for the desk's 437 names from Alpaca's free tier (24.5 M bars, 487 sessions, Nov 2024 – Nov 2026).
Net of slippage and the desk's cost model, session-clustered:
| RVOL | n | continuation, 0.10 ATR stop | continuation, range stop | fade (range stop) |
|---|---|---|---|---|
| < 1 | 102,136 | −0.39R ± 0.03 | −0.17R ± 0.02 | −0.23R |
| 1–3 | 45,321 | −0.43R ± 0.04 | −0.15R ± 0.02 | −0.18R |
| 3–10 | 4,887 | −0.37R ± 0.07 | −0.06R ± 0.04 | −0.15R |
| ≥ 10 | 584 | −0.25R ± 0.27 | +0.02R ± 0.07 | −0.21R |
| gap ≥ 0.7 ATR and RVOL ≥ 10 | 261 | +0.08R ± 0.52 | +0.03R ± 0.07 | −0.09R |
The paper's lift does not replicate here. The shape is there (every bucket improves with RVOL, and
continuation beats its own fade by +0.06 to +0.4R everywhere), but nothing is positive with confidence:
the best cell is zero on 584 trades. Two reasons are visible in the data. The 0.10-ATR stop is 26 bps
of price at the median, inside 5-minute bar noise, so it is hit 80% of the time and often gapped through
(median trade −1.4R before the universe filter); the paper works on 1-minute bars. And the desk's
round-trip cost is 0.21R against that stop, where the paper charges commissions only. Widening the stop
to the opening range halves the loss but does not turn it. Our one lead, continuation after a gap the
options did not price, is consistent with this table's direction column and no more than that: the
fade is the worse side of the same trade, not a trade of its own.
Files: research/orb_rvol_check_2026-11-02_alpaca_2y.json, …_rangestop.json (per-trade lists kept
locally in data/backtests/), research/orb_rvol_check_2026-10-19_60d.json (the 60-day first pass).
10d rejects). Default fetch is 8d (was 5d).5m/15m → 1mo via bars_range_for_interval).rvol_n / session_n so thin samples stay visible.5d.providers.CRYPTO_HISTORY_DAYS), so RVOL has its 7 prior
sessions. Each venue call returns only 200–350 bars, about a day; before, crypto RVOL never had a
baseline. The series is cached per coin and each scan fetches only its tail, from the same venue:
a series is never stitched from two venues' books. If that venue fails, its cache is served
for up to 5 minutes, then the next venue builds a new series. Yahoo, under its own symbols, is the
fallback over the same window. The ledger asks for more days when a pending crypto session is
older, and leaves a session pending until the feed has a bar from the next ET day.index.html # GitHub Pages / shareable demo (runs engine.js in the browser)
engine.js # browser port of engine.py + the desk's scan helpers (parity-tested)
cf-pages/ # identical copy of index.html + engine.js for Cloudflare Pages
static/index.html # full local desk UI (served by app.py)
app.py # FastAPI · live loop · :8791
engine.py # dual VWAP + KER + grades (ENGINE_VERSION)
providers.py / data.py # free feed rotation; crypto history pager + per-coin cache
backtest_today_scans.py · walkforward.py · replay_sessions.py
replay_crypto.py # the same replay on the crypto names (Yahoo, Coinbase or Binance archive bars, paired engines)
binance_vision.py # Binance's public bulk kline archive: monthly/daily zips, checksums, cache
causal_check.py # the replay's old end-of-day trigger search, against its bar-by-bar one
evidence.py # per-class record (n, net R, direction over mirror) from the banner's replays → page + /api/evidence
md_target_check.py # mdrev target rules + missing-RVOL gate, same bars and a 60-day holdout
direction_check.py # breakout vs fade at the gap states (first break, fakeout), paired, net of costs
band_scaling_check.py # |close - blue| and sigma by time since the open vs shuffled twins; variance ratios
honest.py # cost-in-R and session-clustered standard errors (replay + ledger)
ledger.py # forward signal ledger: record → resolve → report (data/signals/, gitignored)
tests/ # python3 -m unittest discover -s tests (engine parity needs node)
research/ # sample backtest / session-replay JSON
Research only. Free feeds delay. Not financial advice.
fade_max_gradeevidence.pysecond_look_check.pyresearch/second_look_check_2026-10-26.jsonmd_target_min_rrearm_after_stopMAX_TRADES_PER_SESSIONhalf_life_minhalf_life_check.pybasket_check.pylatency_check.py| the same bars |
| v1.5.0 |
| bar by bar · after hours |
| next bar open +2 bps |
| 431 |
| −0.14 |
| −0.23 ± 0.07 |
| negative (t −3.4) |
| Sep 3 – Oct 2 | out of sample, refetched, all 96 names ³ | v1.5.0 | bar by bar · 16:00 | next bar open +2 bps | 428 | −0.08 | −0.17 ± 0.06 | negative (t −2.8) |
| Sep 3 – Oct 2 | the same bars | v1.5.0 | bar by bar · after hours | next bar open +2 bps | 428 | −0.11 | −0.20 ± 0.07 | negative (t −3.0) |
| Sep 3 – Oct 2 | the same bars | v1.5.0 | end of day · 16:00 | next bar open +2 bps | 289 | −0.04 | −0.16 ± 0.10 | inconclusive (t −1.5) |
| Jul 28 – Oct 19 | 60 days of 5m bars, all 96 names ⁴ | v1.6.0 | bar by bar · 16:00 | next bar open +2 bps | 654 | −0.05 | −0.16 ± 0.08 | negative (t −2.1) |
| Jul 28 – Oct 19 | the same bars | v1.5.0 | bar by bar · 16:00 | next bar open +2 bps | 1,094 | −0.04 | −0.13 ± 0.05 | negative (t −2.5) |
| Jul 28 – Oct 19 | the same bars; grade A = reclaims only | v1.7.0 | bar by bar · 16:00 | next bar open +2 bps | 174 | +0.12 | +0.05 ± 0.13 | inconclusive (t 0.4) |
| Jul 28 – Oct 19 | the same bars; the fades v1.7.0 grades B | v1.6.0 ⁵ | bar by bar · 16:00 | next bar open +2 bps | 480 | −0.11 | −0.23 ± 0.09 | negative (t −2.5) |
| +0.30 |
| +0.24 ± 0.16 |
| inconclusive (t 1.6) |
| Oct 23 – Oct 22 (a year) | v1.6.0, 47 names ⁵ | Binance archive (real volume) | 661 | −0.07 | −0.14 ± 0.06 | negative (t −2.3) |
method.paired_v1_6_0_same_bars