// Shared mock data for all TAM variations window.TAM_DATA = (() => { const now = new Date('2026-05-07T15:32:00'); // ── Risk metric helpers ───────────────────────────────────────────── function computeReturns(values) { const r = []; for (let i = 1; i < values.length; i++) r.push((values[i] - values[i-1]) / values[i-1]); return r; } function mean(arr) { return arr.length ? arr.reduce((a,b) => a+b, 0) / arr.length : 0; } function std(arr) { if (arr.length < 2) return 0; const m = mean(arr); return Math.sqrt(arr.reduce((s,x) => s + (x-m)**2, 0) / (arr.length - 1)); } function sharpe(returns, rf = 0.0425 / 365) { const excess = returns.map(r => r - rf); const s = std(excess); return s === 0 ? 0 : (mean(excess) / s) * Math.sqrt(365); } function sortino(returns, rf = 0.0425 / 365) { const excess = returns.map(r => r - rf); const downside = excess.filter(r => r < 0); const ds = std(downside); return ds === 0 ? 0 : (mean(excess) / ds) * Math.sqrt(365); } function maxDrawdown(values) { let peak = values[0], peakIdx = 0, maxDD = 0, troughIdx = 0; for (let i = 1; i < values.length; i++) { if (values[i] > peak) { peak = values[i]; peakIdx = i; } const dd = (peak - values[i]) / peak; if (dd > maxDD) { maxDD = dd; troughIdx = i; } } return { value: maxDD, peakIdx, troughIdx }; } function calmar(returns, maxDD) { const annReturn = mean(returns) * 365; return maxDD.value === 0 ? 0 : annReturn / maxDD.value; } function rollingVol(equityCurve, window = 14) { const vals = equityCurve.map(d => d.portfolio); const rets = computeReturns(vals); if (rets.length < window) return std(rets) * Math.sqrt(365) * 100; const recent = rets.slice(-window); return std(recent) * Math.sqrt(365) * 100; } // ── Positions (actual TAM crypto holdings) ────────────────────────── const positions = [ { ticker: 'BTC', coingeckoId: 'bitcoin', qty: 0.124, avgCost: 82400, price: 96420, change24h: 2.14, thesis: 'Digital gold narrative + ETF inflows sustaining bid. Core position. Max size 20%.' }, { ticker: 'ETH', coingeckoId: 'ethereum', qty: 3.2, avgCost: 2900, price: 3280, change24h: 1.82, thesis: 'Dencun upgrade fee burn + restaking narrative. L2 growth driver.' }, { ticker: 'SOL', coingeckoId: 'solana', qty: 28.5, avgCost: 152.2, price: 162.4, change24h: -0.91, thesis: 'High-throughput L1. DEX volume + NFT activity recovering. Ecosystem growing.' }, { ticker: 'LINK', coingeckoId: 'chainlink', qty: 750, avgCost: 11.8, price: 14.82, change24h: 3.24, thesis: 'Oracle infra — DeFi dependency. CCIP cross-chain expansion is underpriced.' }, { ticker: 'DOGE', coingeckoId: 'dogecoin', qty: 58000, avgCost: 0.168, price: 0.182, change24h: -1.44, thesis: 'Meme coin with real volume. DOGE-1 satellite + X payments optionality.' }, { ticker: 'LTC', coingeckoId: 'litecoin', qty: 85, avgCost: 82.5, price: 91.4, change24h: 0.67, thesis: 'Payments rail. MimbleWimble privacy upgrade. Low corr to BTC at times.' }, ]; const cash = 46_230; const totalEquity = positions.reduce((s, p) => s + p.qty * p.price, 0) + cash; const startingValue = 100_000; const btcBenchmarkReturn = 0.172; // BTC +17.2% since strategy start const portfolioReturn = (totalEquity - startingValue) / startingValue; // ── Equity curve (60 days from 2026-02-28, date-stamped for LW Charts) ── const baseDate = new Date('2026-02-28'); const equityCurve = Array.from({ length: 60 }, (_, i) => { const d = new Date(baseDate); d.setDate(d.getDate() + i); const t = i / 59; const noise = () => (Math.sin(i * 1.7 + 2.3) * 0.009 + Math.sin(i * 0.8) * 0.005); const btcNoise = () => (Math.sin(i * 1.4 + 0.7) * 0.012 + Math.sin(i * 0.5 + 1) * 0.006); const port = startingValue * (1 + portfolioReturn * t + noise()); const btc = startingValue * (1 + btcBenchmarkReturn * t + btcNoise()); return { day: i, date: d.toISOString().slice(0, 10), portfolio: Math.round(port * 100) / 100, spy: Math.round(btc * 100) / 100, }; }); // ── Compute risk metrics ──────────────────────────────────────────── const portValues = equityCurve.map(d => d.portfolio); const portReturns = computeReturns(portValues); const mdd = maxDrawdown(portValues); const riskMetrics = { sharpe: +sharpe(portReturns).toFixed(3), sortino: +sortino(portReturns).toFixed(3), maxDD: { value: +mdd.value.toFixed(4), peakDate: equityCurve[mdd.peakIdx]?.date, troughDate: equityCurve[mdd.troughIdx]?.date }, calmar: +calmar(portReturns, mdd).toFixed(3), annVol: +rollingVol(equityCurve), rollingVol14: +rollingVol(equityCurve, 14), }; // ── Routines (crypto agent runs 24/7) ────────────────────────────── const routines = [ { id: 'scan', name: 'Market Scan', cron: '*/30 * * * *', schedule: 'Every 30 min', status: 'running', lastRun: '15:30', nextRun: '16:00', purpose: 'Fetch all 6 positions via Alpaca. Check stop-loss levels. Queue rebalance if triggered.', tokensAvg: 22_100 }, { id: 'morning', name: 'Morning Brief', cron: '08:00 * * * *', schedule: '08:00 UTC', status: 'idle', lastRun: '08:00', nextRun: 'Tomorrow 08:00', purpose: 'Research overnight catalysts, macro, on-chain metrics. Draft strategy note.', tokensAvg: 38_400 }, { id: 'rebal', name: 'Rebalance Check', cron: '0 */4 * * *', schedule: 'Every 4h', status: 'scheduled', lastRun: '12:00', nextRun: '16:00', purpose: 'Check portfolio drift. Re-size positions if >2% off target. Execute via Alpaca.', tokensAvg: 18_700 }, { id: 'risk', name: 'Risk Review', cron: '0 20 * * *', schedule: '20:00 UTC', status: 'idle', lastRun: 'Yesterday 20:00', nextRun: 'Today 20:00', purpose: 'Compute Sharpe/Drawdown. Write daily summary to trade-log.md. Git commit.', tokensAvg: 44_900 }, { id: 'weekly', name: 'Weekly Review', cron: '0 18 * * 0', schedule: '18:00 UTC Sun', status: 'idle', lastRun: 'Sun 18:00', nextRun: 'Sunday 18:00', purpose: 'Deep review. Update strategy.md. Grade week vs BTC benchmark.', tokensAvg: 72_300 }, ]; // ── Activity log ─────────────────────────────────────────────────── const activity = [ { t: '15:32:04', routine: 'scan', level: 'info', msg: 'Reading memory/strategy.md (crypto edition, 203 lines)' }, { t: '15:32:07', routine: 'scan', level: 'info', msg: 'Fetching 6 positions via Alpaca GET /v2/positions' }, { t: '15:32:09', routine: 'scan', level: 'ok', msg: '6 crypto positions loaded. Total equity $102,750.88' }, { t: '15:32:14', routine: 'scan', level: 'think', msg: 'BTC +17.0% from avgCost — tighten stop 7% → 5% per strategy rule' }, { t: '15:32:20', routine: 'scan', level: 'think', msg: 'DOGE at −1.4% intraday. Within noise. Hold. Stop at −7% from avg.' }, { t: '15:32:27', routine: 'scan', level: 'info', msg: 'Querying CoinGecko: live prices for BTC/ETH/SOL/LINK/DOGE/LTC' }, { t: '15:32:29', routine: 'scan', level: 'ok', msg: 'CoinGecko: all 6 prices fetched. Max latency 140ms.' }, { t: '15:32:35', routine: 'scan', level: 'act', msg: 'ACTION: tighten BTC trailing stop 7% → 5%' }, { t: '15:32:41', routine: 'scan', level: 'ok', msg: 'Alpaca PATCH /v2/orders/stop-btc-001 → 200 OK' }, { t: '15:32:47', routine: 'scan', level: 'info', msg: 'Appending to memory/trade-log.md' }, { t: '15:32:50', routine: 'scan', level: 'info', msg: 'Git commit: "scan 15:30 UTC: tighten BTC stop to 5%"' }, { t: '15:33:02', routine: 'scan', level: 'ok', msg: 'Scan complete. No other actions. Next: 16:00 UTC.' }, ]; // ── Trade log ────────────────────────────────────────────────────── const tradeLog = [ { date: '2026-05-07', time: '15:32', action: 'ADJUST', ticker: 'BTC', qty: '—', price: 96420, reason: 'Tighten trailing stop 7%→5%. BTC +17% from avgCost. Lock in gains.' }, { date: '2026-05-07', time: '08:15', action: 'BUY', ticker: 'LINK', qty: 150, price: 14.22, reason: 'CCIP mainnet announcement. Adding to existing LINK. Conviction high.' }, { date: '2026-05-06', time: '20:07', action: 'SELL', ticker: 'AVAX', qty: 45, price: 28.80, reason: 'Stop triggered. −7.2% from cost. Exit clean. Thesis deteriorating post-unlock.' }, { date: '2026-05-06', time: '12:00', action: 'BUY', ticker: 'SOL', qty: 8.5, price: 158.60, reason: 'Rebalance. SOL drifted to 12% of portfolio. Adding to bring back to 15% target.' }, { date: '2026-05-05', time: '08:10', action: 'BUY', ticker: 'LTC', qty: 20, price: 88.40, reason: 'Payments rail thesis. Low correlation to BTC. Defensive add.' }, { date: '2026-05-04', time: '20:00', action: 'ADJUST', ticker: 'ETH', qty: '—', price: 3210, reason: 'Tighten stop after Dencun fee burn data. +13% from cost. Protect gains.' }, { date: '2026-05-03', time: '14:32', action: 'BUY', ticker: 'DOGE', qty: 15000, price: 0.172, reason: 'Scaling in. X payments integration rumor. Sized small per speculative rules.' }, { date: '2026-05-02', time: '08:05', action: 'BUY', ticker: 'BTC', qty: 0.024, price: 91200, reason: 'Dollar-cost averaging. Strong ETF inflow week. Adding to core.' }, ]; // ── Memory files (crypto strategy) ───────────────────────────────── const memoryFiles = [ { name: 'CLAUDE.md', size: '3.1 KB', updated: '2026-05-07 15:32', desc: 'Agent identity + project-wide instructions' }, { name: 'strategy.md', size: '12.8 KB', updated: '2026-05-04 20:03', desc: 'Core crypto trading strategy, signals, thesis framework' }, { name: 'trade-log.md', size: '52.1 KB', updated: '2026-05-07 15:32', desc: 'Every trade with reasoning. Auto-appended after each action.' }, { name: 'research-log.md', size: '94.7 KB', updated: '2026-05-07 15:32', desc: 'CoinGecko/on-chain queries, synthesis, thesis notes' }, { name: 'weekly-review.md',size: '24.3 KB', updated: '2026-05-04 18:02', desc: 'Weekly self-grades + strategy adjustments vs BTC benchmark' }, { name: 'guardrails.md', size: '1.9 KB', updated: '2026-04-26 09:20', desc: 'Hard rules. ALPACA_ALLOW_LIVE=false enforced here.' }, { name: 'positions.md', size: '4.6 KB', updated: '2026-05-07 15:32', desc: 'Current crypto portfolio snapshot + per-position thesis' }, { name: 'learnings.md', size: '9.2 KB', updated: '2026-05-04 18:03', desc: 'Mistakes + lessons. Prevents repeat errors.' }, ]; const fileContents = { 'CLAUDE.md': `# TAM — Trading Agent Marek (Crypto Edition) You are TAM, a disciplined crypto swing/momentum agent on Alpaca paper. Your job is to beat BTC buy-and-hold over a multi-month horizon. ## How you wake up (stateless) Every routine fires statelessly. You MUST: 1. Read memory/strategy.md 2. Read memory/positions.md + memory/trade-log.md (last 20) 3. Read memory/guardrails.md — HARD RULES, non-negotiable. 4. Do the routine's specific job. 5. Append to trade-log.md / research-log.md. 6. git commit + push so the next routine inherits your work. ## Loop PowerShell PID running every 30 min, 24/7. ALPACA_ALLOW_LIVE=false — paper only, permanent. ## Personality - Patient. Not a scalper. - On-chain data > price action narratives. - Write like a fund manager's memo. `, 'strategy.md': `# Core Crypto Strategy ## Thesis Beat BTC buy-and-hold via concentrated (4–6 names) quality L1/L2/infrastructure. Opportunistic swings on conviction catalysts. ## Position rules - Max 6 positions. - Max 20% of portfolio in any single position. - Initial trailing stop: 7%. - Tighten to 5% after +10% unrealized. - Tighten to 3% after +20% unrealized. ## Entry signals - Fundamental: token utility growing, supply shock (halving/burn), narrative catalyst - On-chain: rising active addresses, increasing DEX volume, staking inflows - Technical: above 50-day MA on entry, volume confirms breakout ## Exit signals - Stop triggered (non-negotiable) - Thesis break (unlock event, regulatory FUD with merit, dev exodus) - Better opportunity with >2× conviction ## Benchmark BTC buy-and-hold. If we can't beat BTC, buy BTC. ## No-gos - Leverage / margin. Ever. - Stablecoins for yield (not our business). - Meme coins > 5% of portfolio. - Anything < $500M market cap. `, 'guardrails.md': `# Hard Rules — DO NOT OVERRIDE 1. Max position size: 20% of equity. 2. Daily loss cap: 3% of equity. If hit, STAND DOWN. 3. Max 2 new positions per week. 4. ALPACA_ALLOW_LIVE=false — paper only, permanent. 5. Never use margin. Cash only. 6. Trailing stops: NON-NEGOTIABLE. Never cancel to "give it room". 7. If confidence < 60%, do not trade. Log and wait. 8. DOGE/meme: max 5% combined. Speculative half-size rule. `, 'learnings.md': `# Lessons ## 2026-05-06 — AVAX unlock trap Bought AVAX before token unlock. Supply hit, price tanked −7.2%. Rule: Check vesting/unlock schedule before entry. Token Terminal is the source. ## 2026-05-03 — Don't FOMO into DOGE spikes Bought DOGE at +8% intraday on X payments rumor. Stopped out next day. Rule: No chasing meme pumps > 5%. Revised: Sized to half. Acceptable. ## 2026-04-28 — Rebalance too infrequent Held 12% ETH while strategy target was 15%. Missed 3% ETH run by not rebalancing. Add: 4h rebalance check routine. `, 'trade-log.md': `# Trade Log (most recent on top) [2026-05-07 15:32] ADJUST BTC — tighten trailing stop 7%→5%. +17.0% unrealized. [2026-05-07 08:15] BUY LINK 150 @ 14.22 — CCIP mainnet announcement. [2026-05-06 20:07] SELL AVAX 45 @ 28.80 — stop triggered. Unlock supply hit. [2026-05-06 12:00] BUY SOL 8.5 @ 158.60 — rebalance to 15% target. ...`, 'weekly-review.md': `# Week of 2026-04-28 → 2026-05-04 Grade: B ## What worked - LINK entry on CCIP announcement timed well. - BTC stop tightening protected gains during mid-week dip. ## What didn't - AVAX unlock trap. Classic mistake, now in guardrails. - DOGE sizing still too large on first entry. Fixed in learnings. ## Benchmark comparison Portfolio WTD: +2.8% | BTC WTD: +3.1% Slightly under. BTC rally was concentrated. Alt exposure dragged. ## Adjustments - Added 4h rebalance check routine. - Max DOGE/meme now 5% combined (down from 8%). `, 'research-log.md': `# Research Log (excerpt) ## 2026-05-07 15:32 — BTC stop tightening rationale Query: "Bitcoin on-chain holder behavior May 2026" Sources: 3 (glassnode, cryptoquant, coinmetrics) Synthesis: Long-term holder supply increasing. NUPL in "belief" zone. → Thesis intact. Tighten stop, don't exit. ## 2026-05-07 08:00 — Morning brief Query: "Crypto overnight catalysts May 7 2026" Sources: 4 Synthesis: ETH Dencun fee burn +18% WoW. SOL DEX volume ATH. → Maintain ETH/SOL overweight. `, 'positions.md': `# Current Positions (Alpaca paper, auto-synced) BTC 0.124 @ 82400 → 96420 (+17.0%) [stop: 5% trail] ETH 3.200 @ 2900 → 3280 (+13.1%) [stop: 5% trail] SOL 28.500 @ 152.2 → 162.4 (+6.7%) [stop: 7% trail] LINK 750.000 @ 11.80 → 14.82 (+25.6%) [stop: 5% trail] DOGE 58000 @ 0.168 → 0.182 (+8.3%) [stop: 7% trail] LTC 85.000 @ 82.50 → 91.40 (+10.8%) [stop: 7% trail] Cash: $46,230 Total: ~$102,750 ALPACA_ALLOW_LIVE=false | Paper only `, }; const guardrails = { maxPositionPct: 20, dailyLossCapPct: 3, maxNewPerWeek: 2, initialStopPct: 7, tightenAtGainPct: 10, tightStopPct: 5, minConfidencePct: 60, paperMode: true, allowLive: false, }; const agentThoughts = [ { role: 'system', content: 'Routine: scan (30min loop). Reading memory files...' }, { role: 'agent', content: 'Strategy, guardrails, and last 20 trades loaded. Fetching live positions from Alpaca paper now.' }, { role: 'tool', content: 'alpaca.getPositions() → 6 crypto positions. Total equity $102,750.88.' }, { role: 'agent', content: 'Portfolio +2.75% since start vs BTC benchmark +17.2%. We\'re behind BTC. Underperformance driven by DOGE and AVAX drag. Core L1 positions are healthy though.' }, { role: 'agent', content: 'BTC +17.0% from avgCost. Per strategy.md, above +10% unrealized → tighten stop 7%→5%. Doing that now.' }, { role: 'tool', content: 'alpaca.replaceOrder(stop-btc-001, trail_percent=5) → 200 OK' }, { role: 'agent', content: 'DOGE −1.4% intraday. Within noise. Stop at −7% from avgCost (0.168). Not triggered. Hold.' }, { role: 'agent', content: 'SOL on-chain: DEX volume ATH per morning brief. Thesis intact. No action.' }, { role: 'agent', content: 'No other triggers. Appending to trade-log.md and committing.' }, { role: 'tool', content: 'git commit -m "scan 15:30 UTC: tighten BTC stop to 5%" && git push' }, { role: 'agent', content: 'Done. Next scan at 16:00 UTC. Rebalance check at 16:00 UTC (4h window). Standing by.' }, ]; return { now, positions, cash, totalEquity, startingValue, btcBenchmarkReturn, portfolioReturn, equityCurve, riskMetrics, routines, activity, tradeLog, memoryFiles, fileContents, guardrails, agentThoughts, }; })();