Obs 200: Fix trailing SL churn — 2,500+ wasted placements/day eliminated
trailingStop.ts now sets pos.triggersRegisteredAt after placing trailing SL. Previously, index.ts SL verification checked getOpenOrders() within 2-10s (before WebSocket cache updated), didn't find new SL, cleared slOrderId, and trailing re-placed identical SL every ~10s. SOL alone had 2,471 SL placements on Mar 28 for a single position. Fix extends the grace period to cover WebSocket cache lag.
Obs 208: Macro EMA slope gate — filter choppy crossover entries
Added MACRO_MIN_EMA_SLOPE_PCT (0.03%/candle) as hard gate in computeMacroSignal(). Requires EMA20 to be actually moving in the signal direction — filters entries where EMA structure technically satisfies (price > ema20 > ema50) but EMA20 is flat. Over 5 candles = 0.15% minimum EMA movement. Expected to eliminate 30-40% of small losing entries while preserving big directional winners.
Obs 207: Echo pressure threshold raised 0.35→0.55 — structural baseline fix
Obs 202's raise to 0.35 was insufficient. Pressure score reads ~0.495 CONTINUOUSLY: funding(0.700)×0.50 + spread(1.000)×0.15 = 0.500 structural baseline. At 0.35, echo fired 21 trades on Mar 28 (4W/17L, -$2.46). At 0.55, OI imbalance must confirm genuine crowding beyond market structure. 4th threshold iteration — if insufficient, next step is architectural (baseline normalization).
Echo's pressure index measures market STRUCTURE not CROWDING on Drift ETH
Funding and spread components on Drift ETH don't mean what they mean on CEX. High positive funding = permanent market microstructure (chronic long bias), not a crowding event that mean-reverts. Real crowding detection needs pressure CHANGES (delta above rolling baseline), not absolute levels. If 0.55 threshold still fires too often, architectural change needed.
Macro on SOL is closest to profitable: +$4.02 gross, -$1.53 net (42% WR)
Big winners (#208: +$1.57, #201: +$1.17) prove directional edge exists. Problem: too many small losing entries between big moves. Next iteration should focus on signal quality filter — possibly raising MACRO_CONSECUTIVE_CLOSES from 3→4 or adding minimum EMA slope threshold to filter choppy crossovers.
Obs 202: Echo pressure threshold raised 0.18→0.35 — stop fee bleeding
ROOT CAUSE: Drift ETH funding is structural (persistent positive, longs-pay-shorts), not dynamic crowding. Pressure index reads ~0.31 constantly, exceeding 0.18 threshold, causing echo to short every hour on a non-varying signal. This is a permanent short bias, not contrarian trading. At 0.35, echo requires genuinely extreme crowding before entering. Saves ~$0.50-$1.20/day in fee drag.
Resolution: ECHO_PRESSURE_THRESHOLD 0.18→0.35 in config.ts
Macro is PROFITABLE pre-fees (+$2.59 gross on 15 genuine entries)
SOL macro has 40% WR with 1.12:1 R:R on genuine entries (excluding adopted conf=0 positions). Gross P&L is positive but $3.86 in fees tips net to -$1.27. The strategy thesis IS working — the bottleneck is position sizing at Scout/Standard tier. Higher confidence → larger positions → better fee absorption.
Echo needs pressure DELTA detection, not just absolute levels
Medium-term fix: track pressure index over 1-4h window, only enter when pressure has INCREASED by >0.1. This captures the 'accelerating crowding' part of the thesis. Current absolute-level approach reads structural constants as signals.
22% drawdown from peak — approaching 25% halt threshold
Equity $103.51 vs $132.68 peak (Mar 4) = 22% drawdown. MAX_DRAWDOWN_PCT is 25%. Another $6.37 in losses triggers automatic halt. All strategy changes must prioritize stopping bleeding over seeking gains.
Obs 201: Echo timeout raised 30min→60min
ALL ETH echo trades exit at exactly 1800s timeout. Raw P&L avg +$0.03 but fees avg $0.09 per trade, EV = -$0.06/trade. Directional accuracy good but ETH moves only 0.1-0.3% in 30min — TP at 0.6% unreachable. Extended to 1hr to give thesis time to play out.
Resolution: ECHO_MAX_HOLD_S 1800→3600 in config.ts
All 3 paper strategies have zero trades since deployment
Cascade (SOL), Phantom (BTC), Range (ETH) all at 0 paper trades. Root causes: Range gate (0.04% << 0.60% minimum), Phantom needs funding divergence (flat market), Cascade needs multi-TF alignment (low vol). Not bugs — strategies correctly gated. No promotion data accumulating.
SOL Macro meets demotion criteria (38.1% WR, 20% recent)
21 trades, 8W/13L (38.1% WR). Last 10: 2W/8L (20%). Meets all 4 demotion thresholds. However, 3 of 10 recent losses are adopted positions (confidence=0, no risk management) inflating loss count. Excluding adopted: ~28.6% WR on genuine entries — still weak but adoption problem may be masking performance.
Obs 197 VALIDATED: ETH adoption loop fully broken
Post-fix monitoring confirms zero phantom trades since Session 69 deploy. ETH trading organically at 0.8 trades/hour (7 trades in 8.7h). Pre-fix: 172 phantom trades in 4.5h → Post-fix: 7 organic trades in 8.7h = 96% reduction.
Echo fee drag: 30min timeout too short for low-vol ETH
7 organic echo trades post-fix: 1W/6L, net -$0.34. All exits via 30min timeout. ETH moves ~0.1-0.2% in 30min but TP is 0.6% away. EV per trade = -$0.13 (structurally negative). Avg fee $0.088 vs avg raw P&L +$0.039. Consider extending timeout to 1hr.
BTC downtrend blind spot: -0.52% EMA deviation, no strategy can short
BTC at -0.52% EMA deviation (clear downtrend), above 0.40% threshold. But TREND_ALLOW_SHORTS=false blocks entry, velocity needs HIGH_VELOCITY, and macro is disabled (macroWeight=0.0). BTC has been idle for 3+ days during sustained downtrend. Consider enabling macro on BTC.
SOL macro trailing stop confirmed working (Trade 207)
First confirmed trailing stop activation on a macro trade. Trade 207 SHORT at $85.04, trailing moved SL to breakeven ($84.85) at 0.50% profit. SL/TP placement also confirmed in logs. Recent macro WR: 55.6% (5W/4L on last 9 trades).
Sentiment updated: F&G 10, all BEAR, BTC -3% to $67,750
BTC dropped to $67,750 (-3.1% from yesterday). SOL $84.90. ETH $2,043. PCE inflation tomorrow. FTX $2.2B distribution Mar 31.
ETH adoption loop catastrophe — 511 trades/day
Obs 196 force-timeout approach failed. Rejected positions still received protective SL/TP (index.ts runs before timeout in same tick), creating new stale triggers. Additionally cancelAllOrders() ran AFTER market close, allowing triggers to fire during gap. Mar 26: 511 trades, -$55.45 DB. Mar 27: 172 trades in 4.5h.
Resolution: Skip protective SL/TP for openedAt===0 positions. Move cancelAllOrders() before market close.
Sentiment updated: F&G 10, all BEAR, macro HIGH
Fear & Greed deepened to 10 (47th consecutive extreme fear day). BTC $68.8K testing 200-day MA. SOL $86.35. ETH $2,050 weakest major. Key catalysts: BTC $14B options expiry today, PCE inflation tomorrow.
Echo adoption fee bleed from stale triggers
Mar 26: 11 of 16 ETH trades were adopted (no matching DB trade). Adopted positions 2-6x organic size, causing $1.82 in fees vs $0.36 for organic entries. Adopted trades lost -$1.58 while organic lost only -$0.10. Stale trigger orders from previous cycles create untracked positions.
Resolution: When adoptedStrategy='echo' and no matching DB trade, force immediate timeout (openedAt=0). Preserves legitimate adoption on restart while rejecting stale-trigger artifacts.
Obs 195 orphan cleanup fix validated
Orphan cleanup grace period confirmed working. Recent ETH echo entries show SL/TP properly placed and surviving (SL=13612, TP=13613). Trade count reduced from 39/day to 16/day (59% reduction). Net loss improved from -$8.06 to -$1.68 (79% improvement).
Sentiment update: all markets BEAR, F&G 11
All 3 markets downgraded to BEAR. F&G 11 (46th consecutive extreme fear day). Significant sell-off: SOL -3.7%, BTC -1.8%, ETH -2.5%. Macro risk HIGH. Catalysts: Mar 27 options expiry ($14B), Mar 28 PCE inflation.
Echo same-direction repeat entries
Even with 600s cooldown, echo enters the same direction 20x/day when funding pressure persists. 20 ETH echo trades (all LONG) in 9 hours. Net -$3.20/day ($0.36 raw P&L, $3.56 fees).
Resolution: Module-level lastEchoEntryDirection tracking. Same-direction re-entries require 3600s (1h). Direction flips use normal 600s cooldown.
Macro strategy deployed for SOL-PERP
New hourly-candle trend strategy. Uses 20/50-period hourly EMAs with 4H and daily trend confirmation. 5-minute evaluation cadence. 2.5% SL, 5% TP, 12h max hold. Both longs and shorts.
Strict per-pair strategy assignment
SOL: Macro only. BTC: Velocity + Trend. ETH: Echo only. All other strategies disabled per market (weight=0.0). Clean signal isolation.
Cloud deployment to Fly.io
All 3 bots + dashboard deployed to Fly.io. Persistent volumes for SQLite. Entrypoint symlink fix (Obs 188). Historical databases migrated.
Resolution: drift-sol.fly.dev, drift-btc.fly.dev, drift-eth.fly.dev, drift-dashboard.fly.dev
Echo adoption + overtrading (7-fix bundle)
Multiple issues: (1) Protective SL/TP not registered. (2) ECHO_COOLDOWN_S 120→600. (3) Wrong stop_pct (velocity 1.5% instead of echo 0.4%). (4) Adoption maxHoldS hardcoded to trend. (5) Adoption defaulted to 'trend' strategy. (6) DB strategy restore bypassed isStrategyEnabled. (7) echo.ts missing confidence+leverage in registerPosition.
Resolution: 7-fix bundle deployed. All issues verified fixed: ETH adoption shows strategy:'echo', stopPct:'0.4%'.
Echo full unblocker — 4 remaining blockers after Obs 191
After Obs 191 level-based fix, 4 more blockers: (1) Price normalization divided rate by oracle price. (2) 2/3 component agreement gate impossible with OI~0. (3) Spread weight (0.25) cancelled extreme funding. (4) Threshold 0.4 too high, shorts disabled.
Resolution: Removed price normalization, removed agreement gate, rebalanced weights (funding=0.50), threshold 0.4→0.18, ALLOW_SHORTS=true.
Echo pressure index dead weight — trajectory-only approach
Drift funding updates hourly, OI ratio barely moves minute-to-minute. Both components = 0 for 90%+ of readings. Echo structurally unable to enter trades.
Resolution: Hybrid 70% level + 30% trajectory. Direction threshold 0.3→0.15.
isStrategyEnabled() weight=0 gate missing
ETH was running trend trades despite trendWeight=0.0. isStrategyEnabled() fell through to global CONFIG.TREND_ENABLED=true.
Resolution: Function returns false when weight===0. ETH confirmed: adopts as echo:long post-fix.
Position sizing recalibration
MAX_POSITION_PCT 15%→25%, MAX_EQUITY_RISK_PCT 3%→5%. At $110 equity with ~1 trade/3h, prior sizing produced $2-3 positions. New sizing targets $10-15 notional.
Echo strategy deployed for ETH-PERP
Claude's on-chain pressure contrarian strategy. Reads funding rate trajectory, OI imbalance, and mark-oracle spread. Enters AGAINST the crowd for mean-reversion. 0.4% SL, 0.6% TP, 30min max hold.
BTC SHORT adoption from stale trigger orders
Timeout close left stale trigger orders. Next restart adopted SHORT position from fired stale trigger, despite TREND_ALLOW_SHORTS=false. Lost -$3.70 across 3 SHORT adoptions.
Resolution: Timeout close cancels ALL trigger orders. Adoption rejects forbidden shorts with immediate timeout.
Oracle feed gap during crash — 15-min blind spot
15-min blind spot across all markets at 23:56 UTC Mar 21. BTC position untracked for 15min. Backup RPC endpoint is #1 infrastructure priority.
Post-loss whipsaw — 180s cooldown
SL hits create large EMA deviations that look like strong trend signals, causing immediate re-entry into the same losing pattern.
Resolution: 180s cooldown after losses prevents whipsaw re-entries. Validated working (Session 52).
Trend strategy enters range oscillations
Trend strategy lacks a mechanism to distinguish sustained trends from range oscillations. SOL and BTC entered 7 times each in range-bound markets on Mar 17. Combined loss -$5.66.
Structural negative EV across all strategies
54 trades over 5 days: -$91.55. Avg win:loss ratio ~1:3.3. Fee drag + tight stops + wide losses. Macro strategy is the response to this observation.
Resolution: Macro strategy deployed Session 67 to address root cause.
Add backup RPC endpoint
Obs 184: 15-min oracle blind spot during crash. Need RPC_FALLBACK_URL in client.ts with automatic failover on WebSocket disconnect.
Orphan trigger order cleanup
Stale trigger orders consuming ~$2 margin. Need mechanism to identify and cancel orders not associated with any tracked position.
Wire shouldPauseForCatalyst() into strategy evaluation
Method exists in sentimentService but not called. Could block entries when macro risk HIGH + catalysts present.
Obs 195: Orphan cleanup strips echo SL/TP — false 'SL filled' detection
SDK cache lags 2-10s after trigger placement. orphanCleanup() runs every 1s, doesn't see newly placed SL in getOpenOrders(), interprets as 'SL filled', cancels TP. Echo loses ALL protection within 1s. Result: 39 ETH trades/day (100% timeout exits), -$8.06 net ($7.25 fees).
Resolution: Added triggersRegisteredAt timestamp to StrategyPosition. orphanCleanup() skips positions with triggers registered <30s ago. Post-timeout adoption deferral increased 5s→30s.
Deploy Obs 195 fix: 30s orphan cleanup grace period + adoption deferral increase
Two-part fix in risk.ts: (1) triggersRegisteredAt field + 30s grace in orphanCleanup prevents false SL/TP stripping. (2) Post-timeout adoption deferral 5s→30s reduces stale-trigger adoptions.
Obs 196: Macro blind to downtrends — keeps entering longs during lower highs
Hourly lower highs ($93.42→$92.89→$91.97) but macro enters long because price is still above 20h/50h EMAs. No concept of rally exhaustion. User correctly identifies $89 as 50% retrace target.
Resolution: Three-part fix: (1) Swing high/low analysis — 3+ descending swing highs suppress longs. (2) EMA20 slope detection — flat/declining slope penalizes confidence. (3) Overextension hard gate — blocks entries >3% from EMA20.
Obs 197: Winning positions give back all gains — trailing too wide
Trade at $92.57 went up to $92.93 then reversed to -$0.59. Macro trailing requires 2% profit to activate. Most SOL hourly moves are 0.5-1.5% — trailing never fires. Winners become losers.
Resolution: Three-part fix: (1) Trailing activation 2.0%→1.0%. (2) Time-progressive: after 1h→0.5%, after 2h→0.10%. (3) Breakeven stop: once up 0.5%, SL floor = entry + fees.
Level Sniper strategy deployed for SOL-PERP
Patience-based strategy at daily/weekly/monthly extremes. Waits for price to reach and hold at significant S/R levels for 15+ minutes. Liquidation safety check. SL structural (beyond level zone), TP targets opposing level. 72h max hold, 24h cooldown. Longs only initially.
SOL runs both Macro + Sniper, sharing 1 position slot
Macro handles intraday hourly trends (hours). Sniper handles multi-day level bounces (days). They share MAX_CONCURRENT_POSITIONS=1. When sniper holds, macro can't trade — acceptable for high-conviction multi-day positions.