#!/usr/bin/env bash set -euo pipefail # Bull->Bear Parameter Sweep # Usage: ./analysis/run-bullbear-sweep.sh [--help] [mode] show_help() { cat <<'EOF' Usage: ./analysis/run-bullbear-sweep.sh [--help] [mode] Run a deterministic bull->bear parameter sweep using BullBearSweep.s.sol. Each parameter combo runs: 10 buys (bull) -> sell all (bear) -> measure trader PnL. Modes: quick 27 combos (~2 min) — 3 CI x 3 AS x 3 AW x 1 DD standard 225 combos (~15 min) — 5 CI x 5 AS x 3 AW x 3 DD (default) fine 375 combos (~25 min) — 5 CI x 5 AS x 5 AW x 3 DD full 1050 combos (~70 min) — 10 CI x 7 AS x 5 AW x 3 DD (comprehensive 4D) focused 42 combos (~3 min) — 1 CI x 7 AS x 6 AW x 1 DD (best region) Output: analysis/sweep-BULLBEAR-summary.csv Environment variable overrides (applied after mode defaults): BULL_BUYS, BUY_SIZE_ETH, LM_FUNDING_ETH, SWEEP_TAG, CI_VALUES, AS_VALUES, AW_VALUES, DD_VALUES Examples: ./analysis/run-bullbear-sweep.sh quick ./analysis/run-bullbear-sweep.sh standard BULL_BUYS=20 ./analysis/run-bullbear-sweep.sh standard EOF exit 0 } if [[ "${1:-}" == "--help" ]] || [[ "${1:-}" == "-h" ]]; then show_help fi cd "$(dirname "$0")/.." MODE="${1:-standard}" case "$MODE" in quick) echo "=== QUICK MODE: 27 combos ===" export CI_VALUES="${CI_VALUES:-0,500000000000000000,1000000000000000000}" export AS_VALUES="${AS_VALUES:-100000000000000000,500000000000000000,1000000000000000000}" export AW_VALUES="${AW_VALUES:-20,50,80}" export DD_VALUES="${DD_VALUES:-500000000000000000}" export BULL_BUYS="${BULL_BUYS:-10}" export BUY_SIZE_ETH="${BUY_SIZE_ETH:-15}" ;; standard) echo "=== STANDARD MODE: 225 combos ===" export CI_VALUES="${CI_VALUES:-0,300000000000000000,500000000000000000,800000000000000000,1000000000000000000}" export AS_VALUES="${AS_VALUES:-100000000000000000,300000000000000000,500000000000000000,700000000000000000,1000000000000000000}" export AW_VALUES="${AW_VALUES:-20,50,80}" export DD_VALUES="${DD_VALUES:-200000000000000000,500000000000000000,1000000000000000000}" export BULL_BUYS="${BULL_BUYS:-10}" export BUY_SIZE_ETH="${BUY_SIZE_ETH:-15}" ;; fine) echo "=== FINE MODE: 375 combos ===" export CI_VALUES="${CI_VALUES:-0,200000000000000000,400000000000000000,600000000000000000,800000000000000000}" export AS_VALUES="${AS_VALUES:-100000000000000000,200000000000000000,300000000000000000,500000000000000000,1000000000000000000}" export AW_VALUES="${AW_VALUES:-20,40,60,80,100}" export DD_VALUES="${DD_VALUES:-200000000000000000,500000000000000000,1000000000000000000}" export BULL_BUYS="${BULL_BUYS:-10}" export BUY_SIZE_ETH="${BUY_SIZE_ETH:-15}" ;; full) echo "=== FULL MODE: 1050 combos (comprehensive 4D sweep) ===" # 10 CI values (0-100% in ~10% steps) x 7 AS x 5 AW x 3 DD # Fine CI resolution to precisely map safe/unsafe boundary export CI_VALUES="${CI_VALUES:-0,100000000000000000,200000000000000000,300000000000000000,400000000000000000,500000000000000000,600000000000000000,700000000000000000,800000000000000000,1000000000000000000}" export AS_VALUES="${AS_VALUES:-100000000000000000,200000000000000000,300000000000000000,400000000000000000,500000000000000000,700000000000000000,1000000000000000000}" export AW_VALUES="${AW_VALUES:-20,40,60,80,100}" export DD_VALUES="${DD_VALUES:-200000000000000000,500000000000000000,1000000000000000000}" export BULL_BUYS="${BULL_BUYS:-10}" export BUY_SIZE_ETH="${BUY_SIZE_ETH:-15}" ;; focused) echo "=== FOCUSED MODE: 42 combos (best region) ===" # Fine-grained sweep around the optimal AS=5-35%, AW=50-100 region # CI fixed at 50% (confirmed zero effect with ratchet), DD fixed at 50% export CI_VALUES="${CI_VALUES:-500000000000000000}" export AS_VALUES="${AS_VALUES:-50000000000000000,100000000000000000,150000000000000000,200000000000000000,250000000000000000,300000000000000000,350000000000000000}" export AW_VALUES="${AW_VALUES:-50,60,70,80,90,100}" export DD_VALUES="${DD_VALUES:-500000000000000000}" export BULL_BUYS="${BULL_BUYS:-10}" export BUY_SIZE_ETH="${BUY_SIZE_ETH:-15}" ;; *) echo "Unknown mode: $MODE" echo "Use: quick, standard, fine, full, focused (or --help)" exit 1 ;; esac export SWEEP_TAG="${SWEEP_TAG:-BULLBEAR}" export LM_FUNDING_ETH="${LM_FUNDING_ETH:-200}" echo "Running sweep..." forge script analysis/BullBearSweep.s.sol --skip-simulation --gas-limit 18446744073709551615 2>&1 | tee /tmp/bullbear-sweep.log echo "" echo "=== Results ===" RESULTS="analysis/sweep-${SWEEP_TAG}-summary.csv" if [ -f "$RESULTS" ]; then TOTAL=$(tail -n +2 "$RESULTS" | wc -l) UNSAFE=$(tail -n +2 "$RESULTS" | awk -F',' '{if ($5+0 > 0) print}' | wc -l || true) echo "Total combos: $TOTAL" echo "Unsafe (trader profit): $UNSAFE" echo "" echo "Top 10 safest (most trader loss = most LM gain):" tail -n +2 "$RESULTS" | sort -t',' -k5 -n | head -10 echo "" echo "Bottom 10 (least trader loss):" tail -n +2 "$RESULTS" | sort -t',' -k5 -n -r | head -10 echo "" echo "Lowest drawdown (most stable during bear):" tail -n +2 "$RESULTS" | sort -t',' -k13 -n | head -10 echo "" echo "Top 10 by fee revenue (WETH fees total, descending):" tail -n +2 "$RESULTS" | sort -t',' -k18 -n -r | head -10 fi