The system behind the trades

How Wave Works

Wave is an AI-driven paper-trading system on a single $100K bankroll. Every number below is sourced from the live database at render time — no marketing copy, no hand-waving.

Last updated: 2026-05-17 18:30 PT
01

What Wave Is

An AI bot paper-trading crypto on one $100K bankroll. Public, observable, killswitched end-to-end.

Wave is a 24/7 scoring engine that watches the top ~50 crypto perp pairs by volume, scores each candidate across ~8 components, then opens paper trades when the score clears both a regime gate and an execution gate. The trades are real-time against real Binance prices, but the money is paper — no capital deployed until the system proves a 90-day positive edge over BTC buy-and-hold.

Single bankroll, not two. Longs and shorts share one $100K pool (Spec 2589 architecture). Anything that talks about "$200K combined" is a bug — the integrity audit catches that string in Telegram and report files automatically.

Right now (live from lib/crypto/equity.js):

  • Equity: $101108.27 (1.11% MTM / 1.16% realized)
  • Closed trades all-time: 14266 in the v3 cohort (post-rebuild)
  • Open positions: 0 longs · 1+ shorts (see /wave for live counts)
  • Cash available: $74461 · Invested: $26704 (27% deployed)
02

Scoring Engine

8 components feed total_score. Each has a status — live, degraded, partial, or disabled. The badges below pull from the same DB keys the /wave dashboard reads.

Pillar status — live from <pillar>_pillar_status settings keys, written by the integrity audit every 30 min:

LIVE
Chart
Multi-TF technicals, patterns, bearish setups
LIVE
News
RSS sentiment per symbol
LIVE
Narrative
Sector rotation tailwind
DEGRADED
On-Chain
DefiLlama TVL momentum (DeFi tokens only)
DEGRADED
Smart Money
Creators + whale signals — currently disabled
DEGRADED
Narrative Alert
Scout v2 alerts — currently disabled
LIVE
Derivatives
Funding, OI, perpetual flows

Per-component breakdown:

L1live
Chart score (0-3)
Multi-TF TA: RSI, MACD, EMA stack, BBs, ADX, ATR, Ichimoku, Keltner, TTM Squeeze on 1h/4h/1d alignment plus pattern detection
L2degraded
News score (0-3)
RSS feeds + sentiment. Coverage gap on Binance long-tail perps — symbols not in mainstream feeds score zero by absence
L3live
Narrative score (0-2)
Sector rotation tailwind — AI, DeFi, RWA, DePIN, gaming, L1s, modular
L4partial
On-chain score (0-1.5)
DefiLlama TVL momentum. N/A (null) for non-DeFi symbols — TVL coverage is ~57 protocol slugs; recent signals overlap only ~6
L5live
Derivatives score (0-2)
Binance funding rate APR + OI delta. Calibrated for bear-trend setups (funding ≥50% APR only 0.4% of universe in flat markets — fires when it matters)
L6live
Bearish patterns (0-3)
NEW (Spec 2599 Phase 2): double top, head & shoulders, bear flag, rising wedge, bearish structure, descending triangle, Wyckoff upthrust
D1disabled
Smart Money score (0-2)
Disabled May 17 — variance 0.07 over 14 days (creators-x + creators-youtube data feeds starved). Re-enable via smart_money_enabled=1; under review
D2disabled
Narrative Alert (0-2)
Disabled May 17 — variance 0.07 over 14 days. Scout v2 alerts pipeline not firing. Re-enable via narrative_alert_enabled=1; under review

Strip-dead-features setting. When score_strip_dead_features=1 (current state), the Smart Money and Narrative Alert contributions are forced to zero in total_score regardless of what the per-symbol scorer returned. Re-enable cleanly by flipping their individual *_enabled flags AND the strip-dead setting back to 0.

onchain_score is null for non-DeFi tokens as of Spec 2599 Phase 1#3 — distinguishes "no DefiLlama mapping" (N/A) from "mapped but scored 0" (real signal). Eliminates phantom-zero dilution in total_score.

03

Two Execution Gates

Score-emit threshold + regime-execution floor. Decoupled per side (Spec 2598).

Every candidate passes through two independent gates. A signal can be EMITTED (score ≥ threshold) but still BLOCKED from execution by the regime floor. The two were coupled until Spec 2598 — shorts now have their own execution floor so a chart-only short setup can fire in flat tape without lowering the long-side defensive floor.

risk_on
Sizing0.85×
Score floor4
BTC > 50d EMA AND 14d return > +5%. Sizing dampened from 1.0× pending n≥30 v3 data
neutral
Sizing0.7×
Score floor5 longs · 4 shorts
Default. Long-side keeps 5-floor; short-side decoupled to 4 (Spec 2598 — chart-only shorts can fire in sideways tape)
caution
Sizing0.5×
Score floor6
BTC ≤ 50d EMA OR 14d ≤ -5%
risk_off
Sizing0× longs · short-only
Score floor7
14d return ≤ -10%. New longs blocked; shorts continue

Gate 1 — score-emit threshold: shorts_min_score_after_3_trades=3 (default 4 pre-shorts-pilot). Anything below this never even enters as a signal candidate.

Gate 2 — regime execution floor: long-side reads min_score_neutral=5, short-side reads shorts_min_execution_score=4 (Spec 2598 decoupling). Both havestrict_floor_enforcement kill-switch.

Plus per-trade vetoes: cluster cap, day-of-week filter, funding-APR veto, onchain-zero veto, gap-through guard. Any one of these short-circuits an otherwise-qualifying signal.

04

Risk Management

Killswitched at every level. Deployment cap, sizing tiers, stops, ratchets.

Every rule below has a settings-key killswitch. Flipping it to 0 takes effect on the next scan tick — no redeploy.

Position sizingshorts_position_size_pct / tier × conviction × regime
Per-trade ≤5% of the unified $100K bankroll. Conviction multiplier ×0.5 for score-4 fallback entries (Spec 2585).
Deployment capmax_deployed_capital_pct=0.80
Total invested ≤ 80% of $100K — applies to combined longs + shorts (Spec 2589 unified pool). NOT 200K.
Slot capsmax_open_trades_hard_ceiling / shorts_max_open_trades_hard_ceiling
Long ceiling 40, short ceiling 25. Slot-count, not dollar-based.
ATR stopsatr_stops_enabled / atr_tp1_mult / atr_tp2_mult
TP1 at 1× ATR, TP2 at 2× ATR. Hard stop at entry × (1 - atr_stop_pct). Gap-through guard closes if breach >0.5× stop distance.
Break-even ratchetalways-on (Spec 2550)
Once TP2 hits, stop ratchets to entry — never gives back a winning trade.
Near-stop alertsnear_stop_alerts_enabled
Every 15min walks open positions; posts to the Silas Crypto group when any trade is within 1% of stop with 4h dedup.
Funding APR veto (longs)long_funding_veto_enabled, range -50% to 0%
Blocks longs when funding ∈ [-50%, 0%] — consensus shorts already positioned (Spec 2571). Score ≥8 overrides.
Onchain=0 veto (longs)long_onchain_zero_veto_enabled
Blocks longs when symbol IS in DefiLlama mapping AND TVL momentum is zero (Spec 2572). Now skipped for non-DeFi symbols (null, not 0).
Day-of-week filterday_of_week_filter_enabled
Blocks Sun all day + Sat afternoon entries. Spec 2573 audit: weekday 48% WR / +$818 vs weekend 20% WR / -$1,084 over 48 trades.
Cluster capcorrelation_cap_enabled, max_per_cluster=3
Max 3 trades per correlation cluster (AI, L1, etc) to prevent pile-on.
05

Audit Visibility

37 checks every 30 min. equity.js locked as the only P&L source. Pre-commit hook enforces it.

The system catches its own bugs before David eyeballs them. Each audit run cross-checks every live API endpoint, every snapshot table, every score-feature variance against lib/crypto/equity.js(the canonical truth). Dedup state machine prevents repeat alerts inside a 4-hour cooldown.

1. Number consistency
7 checks
Cross-checks /api/wave/stats, /shorts/stats, /winning-pulse, /combined/stats against equity.js — drift > $1 or > 0.05pp = FAIL
2. Architectural premise
4 checks
No "$200K" / "200K combined" in Telegram + audit files; no settings.*bankroll_usd other than the canonical bankroll_usd; unified_bankroll_v2 readable
3. Data plausibility
7 checks
Benchmark drift vs equity.js; day-over-day equity moves; deployment cap; position concentration; signal freshness
4. Data correctness
8 checks
6 score-feature variance checks (DEAD/DEGRADED/LIVE pillar status writeback); display-pair guard (realized + mtm both present)
5. Cron liveness
2 checks
consecutive_failures ≥ 3; stale crons past 2× expected interval (Tier-1 auto-fix: pm2 restart with 3/24h cooldown)
6. Entry cadence
6 checks
Per-side daily entries vs 7d avg (long + short); math identities to the cent (STARTING + closed + open == mtmEquity)
7. Scanner output yield
2 checks
wave-scan + wave-shorts-scan signal-to-candidate ratio; < 0.05% threshold flags starvation

Run-history table: every wave/crypto cron writes a row to crypto_cron_runs via the shared tripwire helper. Status, duration, output_summary_json, error_message. 30-day retention. Replaces pm2-log-grepping with a queryable history.

P&L canonical source rule (Spec 2599 Phase 8): every $/% number that gets shown or spoken to David comes from lib/crypto/equity.js. scripts/check-pnl-canonical.sh +.git/hooks/pre-commit fail any commit that introduces inline equity math outside the canonical writers.

Tier-1 auto-fix: snapshot drift > $1K vs equity.js auto-repairs the row; stale crons with last_success_at > 2×expected_interval auto-restart via pm2. Cooldown 3/24h per fix-type, 10/24h global cap. Killswitch integrity_audit_autofix_enabled.

06

Cohorts & Tuning

Pre-rebuild trades stay in the DB but don't feed weight tuning. v3 cohort starts now.

crypto_paper_trades.cohort column added by Spec 2599 Phase 9. All trades before the rebuild ship are tagged pre_rebuild; new trades opened by either scanner now writecohort='v3'. This is NOT data deletion — pre-rebuild trades are still queried for all-time lifetime numbers, but they don't feed Phase 2 weight tuning.

Phase 2 trigger: when cohort='v3' AND status='closed' count reaches n ≥ 30 AND every scoring feature has been alive for the full window, the daily audit auto-proposes re-weights via crypto_audit_proposals (Tier 2 — Silas review, no auto-apply).

Recap audio explicitly distinguishes the two scopes: "Lifetime, all trades: -$1939 over 71 trades" (canonical, equity.js) AND "V3-era cohort: -$X over 66 trades" (subset, labeled). No more pre-rebuild numbers wearing the word "Lifetime."

Current v3 cohort count: 66 closed trades (target n ≥ 30 to unlock Phase 2 tuning).

07

Daily Rhythm

When each cron runs and what it produces.

06:00 PT
wave-daily-audit
Full performance audit + Tier-1 auto-fix layer. Markdown report + MP3 transcript. Telegram digest currently muted per operator flag.
07:00 PT
wave-morning-recap
Friendly check-in audio.
08:00 PT
wave-morning-health
Single one-line DM: equity, pillar status, cron health, audit summary. Replaces noisy state-change spam.
17:00 PT
crypto-daily-recap
Evening recap MP3 + Telegram audio. All numbers sourced from equity.js per Spec 2597.
every 15min
wave-scan
Long-side scoring on top-50 by volume. Output → crypto_signals.
every 15min
wave-shorts-scan
Short-side scoring with bearish patterns. Output → crypto_signals + paper shorts.
every 15min
wave-near-stop-alerts
Walks open positions; posts to the Silas Crypto group when any trade is within 1% of stop.
every 30min
wave-system-integrity-audit
37 checks across 7 categories. Auto-fix benchmark drift + stale-cron restart. Pillar status writeback.
every 4h
wave-defillama-ingest
DefiLlama TVL ingestion across ~57 mapped protocol slugs.

Telegram cadence: morning health DM at 08:00 PT is the canonical "is Wave OK?" digest. Integrity audit Telegram currently muted per operator flag (integrity_audit_telegram_enabled=0) — runs silently, writes reports, alerts when flipped back on. Audit MP3s land at /recaps/<date>-audit.mp3 regardless.

08

Safety Rails

Killswitched rails layered on top of the scoring engine. Each is independent; flipping its DB key reverts to pre-rail behavior.

The original rebuild on 2026-05-17 added 13 rails over one day. Specs #2826 and #2827 layered another ten on top through May 21 / May 22 — portfolio drawdown breaker, BTC flash breaker, counterfactual shadow replay, wiring drift audit, BTC tape filter, counter-trend guard, daily loss cap, funding entry-gate, news weight set to zero, and the inverse-side shadow loop. Each row shows what it does, why it exists (with backing data where the case was empirical), and the exact DB key to flip if a rail needs to be disabled. Cohort marking is active throughout — pre-rebuild and v3 trades are tagged separately so post-rebuild metrics don't get muddied by legacy data.

One $100K bankroll
What: Wave is one bot with one $100K balance. Longs and shorts share the pool.
Why: Spec 2589 eliminated the phantom $200K combined framing; David said "we put both longs and shorts into one 100K, not 200."
bankroll_usd=100000, unified_bankroll_v2=1
Side-specific execution floors
What: Longs require score ≥ 5; shorts require score ≥ 4.
Why: Empirical edge differs by side. Decoupled per Spec 2598.
min_score_neutral=5, shorts_min_execution_score=4 (now 5 post-evening fixes)
Conviction step bands
What: Position size scales with score in steps, not a continuous curve. score ≥ 7 → 1.5×; 5–6 → 1.0×; < 5 → 0.5×.
Why: The old (score/4)^1.5 curve overdosed score-5 entries at 1.4× and was inconsistent across long/short. Step bands match David’s stated risk shape.
conviction_sizing_enabled=1, conviction_mult_hi=1.5, conviction_mult_mid=1.0, conviction_mult_lo=0.5
Vol-adaptive sizing
What: Baseline 4% ATR. Low-vol setups size up to 1.5×, high-vol size down to 0.5×. Clamped [0.5×, 1.5×]. Both scanners.
Why: A 2% ATR and 8% ATR setup at the same conviction carry very different real risk; the base chain previously treated them identically.
vol_adaptive_sizing_enabled=1, vol_adaptive_baseline_atr=0.04
48h symbol cooldown
What: Side-aware. After any close on the same side at worse than -2%, that symbol cannot re-enter on that side for 48 hours.
Why: Blocks revenge re-entries. Backing: ZEC took 3 long losses (-$491), AI took 4 (-$159), both within tight windows.
symbol_cooldown_enabled=1, symbol_cooldown_hours_after_loss=48, symbol_cooldown_min_loss_pct=-2.0
Long tier filter (dolphin + shark only)
What: Longs only enter on dolphin or shark tier coins.
Why: Minnow + whale tiers lost -$635 across 11 trades; dolphin + shark were net positive.
long_tier_filter_enabled=1, long_allowed_tiers=dolphin,shark
Short exposure cap 40%
What: Blocks new short entries when total short side would exceed 40% of bankroll. Warns at 35%. Existing positions grandfathered.
Why: Today’s book is 99% short at entry — one BTC squeeze and the pool is gone. Prevents future concentration.
short_exposure_cap_enabled=1, short_exposure_cap_pct=40, short_exposure_warn_pct=35
Cluster-$ correlation cap 25%
What: Blocks new entries that would push any correlation cluster (BTC-major, ETH-DeFi, SOL-eco, etc.) past 25% of bankroll.
Why: Layers a $-based cap on top of the existing count cap. Catches concentration even when no single cluster has 3 positions.
correlation_cap_enabled=1, correlation_max_cluster_pct=0.25
24h no-progress flush
What: If a trade hasn’t made +1.5% progress toward TP1 within 24 hours, force-exit at current price instead of tightening and bleeding.
Why: The 24–48h hold band was 17.6% WR / -$1,593 across 17 trades — the biggest single bleed on the long book. First production save: TRUMP flushed at -3.3% at 16:45 PT May 17.
early_no_progress_flush_enabled=1, early_no_progress_min_pct=1.5
Late hold tighten
What: One-way ratchet on longs older than 60 hours: tightens stop, never loosens.
Why: Spec 61 #3 evidence: 1–3 day holds had 33% WR and lost -$722 net. The ratchet prevents the late-bleed pattern.
late_hold_tighten_enabled=1, late_hold_tighten_h60_pct=6.0, h72_pct=3.0, h84_pct=2.0
Regime sizing
What: BTC 50d EMA + 14d return classifies risk_on / neutral / caution / risk_off. Sizing multiplies by 0.85× / 0.5× / 0.4× / 0.25×.
Why: Macro context modulates how aggressive position sizing should be. Under review May 24 — risk_on H2 produced 15.4% WR / -$1,031.
regime_enabled=1; per-regime overrides: neutral_size_multiplier=0.5, caution_size_multiplier=0.4, risk_off_size_multiplier=0.25
News-spike escalation
What: Score-(floor-1) signals with news_score=3 AND most-recent matched news ≤ 30 min old can enter at the lowered threshold.
Why: Catches the +7.97% news-driven win bucket (TRUMP, BTC, ETH on news=3). Without timing, the system was treating fresh and stale news identically.
news_spike_escalation_enabled=1, news_spike_window_min=30
Real-money pre-flight guard
What: Settings API physically refuses real_money_enabled=1 until a 10-item checklist passes. Currently paper-only.
Why: Eliminates the failure mode where a stray dashboard flip, cron, or operator could accidentally turn live trading on. The checklist itself is the real-money project.
real_money_pre_flight_passed=0 (must reach 1 before real_money_enabled can flip)
Portfolio drawdown breaker
What: Halts ALL new entries when MTM equity drops more than drawdown_breaker_pct (default 12%) below the rolling 14-day peak. Releases automatically when equity recovers above the threshold.
Why: Caps total damage during a regime shift before per-trade stops can fully express. Inspired by the prop-trading "daily drawdown" rule that pulls the operator off the desk.
drawdown_breaker_enabled=1, drawdown_breaker_pct=0.12
BTC flash breaker
What: Blocks new long entries when BTC drops ≥4% in 4 hours OR ≥8% in 24 hours. Auto-releases when the move cools.
Why: On BTC flash crashes the whole alt complex moves together. Pausing longs for the duration is cheaper than opening into the cascade.
btc_flash_breaker_enabled=1, btc_4h_drop_pct=-0.04, btc_24h_drop_pct=-0.08
Counterfactual shadow replay
What: Every scan window also replays the trade the would-have-been opposite ruleset would have produced. Logged to crypto_shadow_trades for offline comparison; never affects live PnL.
Why: Tells us, with real data, whether our entry edge actually beats the simplest counterfactual (inverse / loose / tight / trail-only / scalp / long-hold variants).
shadow_replay_enabled=1, 6 variants live (live/loose/tight/longhold/trailonly/scalp)
Wiring drift audit (9_settings_hygiene)
What: Audit category 9 walks every key in crypto_wave_settings and FAILs if it has no consumer in code AND no unwired_legacy tag. Forces every new setting to be either wired or explicitly deferred.
Why: Spec 2822 wiring sweep found 8 of 13 supposedly-active killswitches were no-ops. The drift detector prevents that from happening again.
wiring_status column on crypto_wave_settings (consumer | unwired_legacy | NULL)
BTC tape + range filter
What: Blocks long entries when BTC is making a fresh 24h low (entry percentile <20). Blocks short entries when BTC is making a fresh 24h high (>80). Both sides record the entry percentile at fill.
Why: Diagnostic on 116 closed trades showed entries clustered near unfavorable extremes — fading the dominant tape direction. Stopping that bleed alone closes ~30% of the cumulative loss.
tape_filter_enabled=1, range_filter_min_pct=20, range_filter_max_pct=80
Counter-trend guard
What: Refuses long entries while BTC 4h return is < -2% (no catching falling knives). Refuses short entries while BTC 4h return is > +2%.
Why: On the 3-day-hold cohort that lost -$5,169, 62% of entries were against the prevailing BTC 4h direction. This rail explicitly says "do not fight the tape".
counter_trend_guard_enabled=1, counter_trend_btc_4h_threshold=0.02
Daily loss cap
What: Walks the day's realized PnL each scan; if cumulative loss exceeds daily_loss_cap_usd (default $2,000) the scanner stops opening new positions until 00:00 PT.
Why: On three of the worst days in history a single bad regime printed -$1,800 to -$2,400. The cap turns "ride it out" into "stop digging" automatically.
daily_loss_cap_enabled=1, daily_loss_cap_usd=2000
Funding entry-gate
What: Records funding APR at entry on every paper trade. Blocks short entries when funding APR is already below -funding_entry_gate_apr_short (default 15%) — the move has already paid out.
Why: Highest-loss shorts in history were entered AFTER funding had already gone deeply negative. Treats funding as a leading indicator, not just a filter.
funding_entry_gate_enabled=1, funding_entry_gate_apr_short=15
News weight set to zero
What: news_weight forced to 0 in the scoring chain — news no longer contributes to total_score. Pillar still tracked + logged for forensics.
Why: Post-mortem on 24h-hold losses showed news_score=3 entries lost -$1,107 vs +$48 for news_score=0 trades. The signal was correlated with retail FOMO tops.
news_weight=0 (was 1.5)
Inverse-side shadow loop
What: For every live trade the system opens, it also writes a shadow trade in the OPPOSITE direction with the same sizing + rules. Settles independently in crypto_shadow_trades.
Why: If the inverse cohort beats live by a margin > the round-trip costs, that's the strongest possible signal that entry direction (not exit rules) is the leak.
inverse_shadow_enabled=1
Chop killswitch (proactive)
What: Blocks ALL new entries (long + short) when regime is caution/risk_off AND 14d realized P&L < -$500 AND last 10 closed trades WR < 40%. All three must hold.
Why: May 24 forensic: the inverse-shadow cohort lost 96.5% of trades in the recent bleed period. That's empirical proof the market was paying nobody. The right response is to stop trading, not to switch sides. Proactive replacement for the reactive stop-bleed pattern.
chop_killswitch_enabled=1, chop_killswitch_regimes=caution,risk_off, chop_killswitch_drawdown_usd=-500, chop_killswitch_min_wr_pct=40
Per-symbol 7d loss cool-down
What: After any losing exit on (symbol, side), block new (symbol, side) entries for 7 days. Distinct from the 48h cool-down above (this catches single-loss re-fires within a week).
Why: Recent bleed dominated by re-traded losers: ZEC ×3 = -$491, SIREN ×3 = -$542, BNB ×2 = -$423. The 48h cool-down only catches -2%+ losses; this catches everything.
symbol_loss_cooldown_enabled=1, symbol_loss_cooldown_days=7
Drawdown-aware sizing
What: When trailing 14d realized P&L < -$500, multiply final position size by 0.5×. Layered on top of all other sizing modifiers.
Why: P4 bleed period had avg position size $3,639 vs P1 era $2,132. Bot was sizing UP into a -$2,803 bleed - classic human discipline failure that a bot should not replicate.
drawdown_sizing_enabled=1, drawdown_sizing_threshold_usd=-500, drawdown_sizing_mult=0.5
48h chop-zone close
What: Force-close longs that have been held >=48 hours and are still sitting in the +/- 2% P&L band.
Why: The 24-72h hold bucket is historically the killer (5W/26L, -$3,929). Trades that survive past 24h either close fast with momentum or ride the trail past 72h. The middle zone bleeds.
chop_zone_close_enabled=1, chop_zone_close_hours=48, chop_zone_close_band_pct=2
Ladder-add for high-conviction repeats
What: When a fresh signal scores >= 7 on a symbol we already hold AND the existing position is in profit, allow a SECOND tranche. Cap at 2 tranches per symbol.
Why: The 1-position-per-symbol cap blocked 66 entries in 14d. Of 6 high-score (>=6) signals we ignored because we already held that symbol, 4 of 5 (where data exists) would have won. Also positions the bot to pyramid into winners in bull markets.
ladder_add_enabled=1, ladder_add_min_score=7, ladder_add_max_tranches=2, ladder_add_require_profit=1
Regime-adaptive trail
What: Trail stop distance and arming threshold are now per-regime. risk_on: loose (10% trail, 8% arm) so winners can run. neutral: medium (5%/5%, the prior flat default). caution/risk_off: tight (3%/3%) so chop doesn't eat slow trades. Falls back to flat settings if a per-regime key is unset.
Why: Single-config trail was killing trending winners in bull (NEAR went +61% after we exited at +4.8% on May 6) and bleeding slow trades in chop. One trail can't serve both regimes.
trail_stop_pct_<regime>, trail_activate_at_pct_<regime>; e.g. trail_stop_pct_risk_on=0.10
Regime-adaptive leverage (bull-mode multiplier)
What: Position size multiplier driven by regime + recent WR. risk_on + WR >= 50%: 2.0×. risk_on + WR < 50%: 1.5×. neutral/caution/risk_off: 1.0×. Hard safety interlock: leverage stays at 1.0× whenever 14d realized P&L is negative - cannot amplify a losing book, period. Layered ON TOP of drawdown sizing (only activates when drawdown sizing is at 1.0×).
Why: For the bot to 2× buy-and-hold in a real bull, position sizes have to scale up when the tape is clear and we are winning. The interlock prevents the obvious failure mode (leveraging into a drawdown).
regime_leverage_enabled=1, regime_leverage_mult_risk_on=2.0, regime_leverage_mult_risk_on_cautious=1.5, regime_leverage_risk_on_wr_floor=50
Liq fade threshold $100k + 12h hold
What: wave-liquidation-fade now triggers on any (symbol, hour) cluster >= $100,000 in Bybit liquidations and holds shadow positions for up to 12 hours.
Why: May 24 backtest of 14d cascades at $100k threshold: 7 wins / 1 loss (88% WR) at 12h hold, +$362 hypothetical P&L at $1,500 per fade. Old threshold $500k caught only 1 of 8 winning setups; old 4h hold cut before reversion peaked.
liquidation_fade_threshold_usd=100000 (was 500000), liquidation_fade_max_hold_h=12 (was 4)
Shadow zero-hold tp_single_8 guard
What: Shadow trades require a minimum 60-second hold before any TP/stop fires. Without this, edge-case entries where the entry candle already contains the TP price registered as instant +8% wins.
Why: May 24 audit found 27 ghost rows (BANANAS31/ICP/TON) closing in <1 second at the entry candle's TP, inflating scalp/long v2 shadow P&L by +216% - pure noise contaminating promotion analytics.
60-second min hold hardcoded in crons/lib/shadow-trades.js
09

Pattern Detection

Bullish + bearish chart-pattern detectors. Aggregator fires on the highest-confidence detection per scan; score folds into total_score via the per-side killswitches.

All detectors live in lib/crypto/patterns.js. The aggregators (detectBullishPatterns, detectBearishPatterns) return the top confidence match plus a 0–3 score that scales into total_score. Killswitches: bullish_pattern_enabled=1, bearish_pattern_enabled=1.

Bullish (longs) — 8 detectors
  • Double bottom
  • Inverse head & shoulders
  • Bull flag
  • Cup & handle
  • Descending wedge
  • Ascending triangle
  • Symmetric triangle (bullish)
  • Wyckoff spring
Bearish (shorts) — 7 detectors
  • Double top
  • Head & shoulders
  • Bear flag
  • Rising wedge
  • Bearish structure (LH/LL)
  • Descending triangle
  • Wyckoff upthrust

Cohort marking is active — pre-rebuild and v3 trades are tracked separately so the detectors' post-rebuild contribution can be measured without legacy contamination.

10

Strategy Suite (Spec #2828, May 22)

New data feeds, shadow strategies, and sizing helpers shipped as one batch. Most ship in shadow or default-OFF until 7 days of forward data prove the edge.

The diagnostic on the first 116 trades showed that exits work (trail stop is +$6,985) but the entry direction is the leak. The May 22 batch attacks both sides of that problem: new data feeds (BTC dominance, liquidations, funding extremes, event calendar) give the scanners context they didn't have before; new shadow strategies (liquidation fade, Kelly sizing, bankroll compounding, slippage-modelled backtest, pre-listing watchlist) run alongside the live system without affecting real PnL until the data says they earned the upgrade.

Data feeds (always on)

BTC dominance + total market cap· hourly · live
Pulls BTC.D, ETH.D, and total crypto market cap from CoinGecko /global into crypto_market_metrics. Feeds the regime-aware filters and the morning health DM.
crypto-market-metrics-snapshot cron, btc_dominance_filter_enabled=1
Liquidation feed· realtime · live
Long-running pm2 process subscribed to Bybit v5 allLiquidation WS across 30 perp pairs. One row per real liquidation event into crypto_liquidations. (Binance Futures WS is geo-blocked from this VPS even though their REST works — Bybit is the working alternative.)
crypto-liquidation-ws pm2 app, LIQ_WS_MIN_USD=1000 floor
Funding-carry scout· every 30 min · live (digest only)
Detects symbols with |funding APR| ≥ funding_carry_min_apr (15%) and logs them. Daily Telegram digest at 14:00 UTC lists current carry opportunities.
wave-funding-carry-scout cron, funding_carry_scout_enabled=1, funding_carry_min_apr=15
Event calendar block· live, 18 events seeded · live
crypto_event_calendar seeded with 2026 FOMC meetings (6), CPI releases (9), and BTC/ETH quarterly options expiries through Dec. Every entry checks the upcoming-events window and refuses if within block_window_hours.
event_calendar_filter_enabled=1, 18 events seeded
Focus universe gate· always · off by default
When enabled, restricts entries to the curated crypto_universe_focus list (BTC, ETH, SOL, etc.). Shrinks the universe to where we have real edge.
universe_focus_enabled=0 (opt-in)

Shadow strategies + sizing helpers

Liquidation fade· shadow
Aggregates 1h liquidation $-volume per symbol+side; when it crosses $500K threshold, opens a SHADOW trade in the OPPOSITE direction (the fade). Lives in crypto_shadow_trades with variant_code=liq_fade; never affects real PnL until 7d of forward data proves edge.
wave-liquidation-fade cron, liquidation_fade_enabled=1, liquidation_fade_live_enabled=0
Kelly Criterion sizing· off by default
Per side (now wired on BOTH longs and shorts), computes f = (WR × payoff − 1) / payoff over the last 30 closed trades and clamps to [0, kelly_max_fraction=0.25]. When ON, sizes down trades that exceed the Kelly bet; never sizes UP.
kelly_sizing_enabled=0, kelly_min_lookback_trades=30, kelly_max_fraction=0.25
Bankroll compounding· off by default
Daily at PT midnight (08:00 UTC), rolls bankroll_usd to current MTM equity. Future trade sizes scale with realized + open PnL. Logs to crypto_bankroll_compound_log.
wave-bankroll-compound cron, compound_bankroll_enabled=0
Slippage-modelled backtest· live
replayTrade() in lib/crypto/backtest-engine.js now applies entry-side slippage when ruleset.slippage.enabled. Counterfactual replay cron reads slippage_model_enabled and passes the slippage option through to every variant — replays now produce real-fill-adjusted PnL.
slippage_model_enabled=1, slippage_atr_fraction_entry=0.5, slippage_atr_fraction_exit=0.25
Funding-extreme long trigger· live
When funding APR drops to ≤ -20% (deeply negative — shorts paying longs), wave-scan treats the signal as a squeeze setup: bypasses the funding-veto AND lowers the score floor by 1 point. Symmetric to news-spike escalation.
funding_extreme_long_enabled=1, funding_extreme_long_min_apr=-20
Pre-event positioning· shadow
Hourly cron walks crypto_event_calendar for events 6-24h ahead and opens a SHADOW position per the category bias table: FOMC=short BTC, ETF/options-expiry=short the underlying, listing/hard_fork=long. Live mode killswitched until 7d of positive shadow PnL.
wave-event-positioning cron, event_positioning_enabled=1
Pre-listing front-run· shadow
Two-cron pipeline. crypto-listing-scraper pulls Coinbase RSS + Binance news + KuCoin announcements hourly into crypto_listing_watchlist. wave-listing-front-run opens a SHADOW LONG on any pending symbol it can resolve to a coingecko_id (wider stop -8%, TP +30%, 96h hold).
crypto-listing-scraper + wave-listing-front-run crons, listing_front_run_enabled=1
Funding cash-and-carry pairs· shadow
Two-cron pipeline. wave-carry-entry (every 30 min) opens paired long-spot + short-perp positions when funding APR ≥ +20% and the candidate resolves to a real crypto coingecko_id (filters out stock-tokenized perps). wave-carry-settle (hourly) accrues funding income, MTM both legs, closes when funding flips, time stop hits, or legs diverge >4%. New crypto_carry_positions + crypto_carry_settlements tables. Live mode (real exchange orders) gated until pipeline is built.
wave-carry-entry + wave-carry-settle crons, carry_entry_enabled=1, carry_live_enabled=0
Automated promotion check· live
Daily cron compares every shadow variant (live/loose/tight/longhold/trailonly/scalp/liq_fade/event_pre/listing_front/inverse) to the live cohort baseline over 30d. When sample n≥30 AND winrate-lift ≥5pp AND payoff ≥1.1× live AND ΔPnL ≥$500 AND sharpe ≥0.8, writes a PROMOTE recommendation to crypto_promotion_recommendations and DMs David with the breakdown. Never auto-flips killswitches.
wave-shadow-promotion-check cron, shadow_promotion_check_enabled=1, runs 14:15 UTC daily

The full strategy plan that motivated this batch lives at /root/cc-summaries/2026-05-22-boostio-10x-strategy-plan.md. Promotion criterion across the board: ≥30 closed shadow trades with WR + payoff that beats the live cohort by more than the round-trip cost. Until then, the live book runs on the existing engine and the new strategies record themselves into crypto_shadow_trades + their per-strategy log tables.

11

Intentionally Not Here Yet

The honest list of what's NOT in this version, and why.

Wave ships in phases. Below is everything that someone might reasonably assume is part of a "real trader" stack but is deliberately deferred — with the reason for each, so nothing surprises you later.

Real money (live capital)
Gate: 90 consecutive days beating BTC buy-and-hold on v3 cohort. Currently zero v3 trades; Phase 2 tuning requires n≥30 first.
Pitchforks / trendline drawing
Pivot-point selection needs its own design + backtest. Naive line-fitting overfits noise.
Elliott Wave
Subjective by design. No widely-accepted automated detector. Permanently deferred.
Liquidation cluster maps (websocket)
Live 5-min poll from Binance is now feeding crypto_liquidations (Spec #2828 — see Strategy Suite). Realtime websocket subscription as a long-lived pm2 process is the next upgrade.
Volume Profile usage (L)
POC/VAH/VAL calc lives in patterns.js; entry/exit wiring deferred until backtest validates the bias.
Higher-TF bias (M)
htf_bias column + setting in place. Full weekly+monthly EMA requires 600d candle fetch — its own spec.
CME gap scanner (N)
crypto_cme_gaps table + setting ready. Sunday 22:00 ET Yahoo Finance scanner is a separate ship.
Funding × price-action (O)
Replaces existing funding-veto logic. Killswitch in place; wiring needs backtest before swap.
FVG / order blocks (P)
detectFvg() exported. Scoring wiring deferred.
Wyckoff Spring (Q)
detectWyckoffEvent() exported; upthrust folded into bearish aggregator. Spring wiring for longs deferred.
12

Roadmap

Triggers, not dates. Wave ships when the data says it's ready.

Phase 2
Trigger: n ≥ 30 v3 trades + all features alive
Auto-tune scoring weights from v3-cohort outcomes. crypto_audit_auto_fixes table tracks per-setting changes.
Phase 3
Q3 2026
On-chain mapping expansion — DefiLlama beyond DeFi tokens + Glassnode net-flows.
Phase 4
Phase 11 detectors wired
Volume profile + HTF bias + CME gaps + Wyckoff Spring + FVG into scoring, with backtested weights.
Phase 5
After 90d positive alpha on v3
Live capital via Coinbase API. Same scoring, real money, kill-switch on drawdown.

No fixed dates. The roadmap moves when the data does — n ≥ 30 v3 trades unlocks Phase 2, not a calendar. If a phase needs more time, it gets more time. If it ships earlier, it ships earlier. Either way the morning health DM tells David where we are.

See it live

Every trade, every signal, every regime change — happening right now.

Open the Wave Dashboard →