harb/onchain/analysis/run-parameter-sweep.sh

265 lines
10 KiB
Bash
Raw Normal View History

#!/bin/bash
# Parameter sweep for finding safe/unsafe optimizer parameter boundaries
#
# Usage: ./analysis/run-parameter-sweep.sh [mode]
# Modes:
# quick - Small focused grid (~5 min)
# standard - Medium grid (~30 min)
# boundary - Focused on exploitation boundary (~20 min)
#
# Run from onchain/ directory
set -euo pipefail
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'
MODE=${1:-standard}
# Common: uncapped swaps for realistic exploitation testing
UNCAPPED="true"
MINBUY="20"
MAXBUY="80"
case $MODE in
quick)
CI="0,500000000000000000,1000000000000000000"
AS="100000000000000000,500000000000000000,1000000000000000000"
AW="30,50,80"
DD="200000000000000000,1000000000000000000"
BB="80,100"
RUNS=3
TRADES=20
;;
standard)
CI="0,200000000000000000,500000000000000000,800000000000000000,1000000000000000000"
AS="50000000000000000,100000000000000000,200000000000000000,500000000000000000,700000000000000000,1000000000000000000"
AW="20,50,80"
DD="200000000000000000,500000000000000000,1000000000000000000"
BB="80,100"
RUNS=5
TRADES=30
;;
boundary)
# Focused sweep around known exploitation boundary:
# Bull (exploitable): CI=0, AS=1e18, AW=50, DD=1e18
# Bear (mostly safe): CI=0.8e18, AS=0.2e18, AW=80+, DD=0.2e18
# Key: anchorShare transition between 0.2 and 0.7
CI="0,300000000000000000,500000000000000000,800000000000000000"
AS="100000000000000000,200000000000000000,300000000000000000,400000000000000000,500000000000000000,700000000000000000,1000000000000000000"
AW="30,50,80"
DD="200000000000000000,500000000000000000,1000000000000000000"
BB="80"
RUNS=5
TRADES=30
;;
*)
echo "Unknown mode: $MODE (use: quick, standard, boundary)"
exit 1
;;
esac
echo -e "${GREEN}=== KRAIKEN Parameter Sweep ($MODE mode) ===${NC}"
echo "Runs per combo: $RUNS | Trades per run: $TRADES"
echo "Uncapped: $UNCAPPED | Trade range: ${MINBUY}-${MAXBUY} ETH"
# Master results
SUMMARY_FILE="analysis/sweep-FULL-summary.csv"
echo "ci,anchor_share,anchor_width,discovery_depth,buy_bias,max_trader_pnl,min_trader_pnl,any_lm_loss,lm_eth_delta" > "$SUMMARY_FILE"
# Split into small batches: one forge call per (CI, AS, AW) triple
# Each call handles DD*BB combos to stay within gas limits
batch=0
total_combos=0
start_time=$(date +%s)
for ci_val in $(echo "$CI" | tr ',' ' '); do
for as_val in $(echo "$AS" | tr ',' ' '); do
for aw_val in $(echo "$AW" | tr ',' ' '); do
batch=$((batch + 1))
ci_pct=$(python3 -c "print(f'{int(\"$ci_val\")/1e18:.0%}')" 2>/dev/null || echo "$ci_val")
as_pct=$(python3 -c "print(f'{int(\"$as_val\")/1e18:.1%}')" 2>/dev/null || echo "$as_val")
echo -ne "\r${BLUE}[$batch] CI=$ci_pct AS=$as_pct AW=$aw_val${NC} "
CI_VALUES="$ci_val" \
AS_VALUES="$as_val" \
AW_VALUES="$aw_val" \
DD_VALUES="$DD" \
BB_VALUES="$BB" \
RUNS_PER_COMBO="$RUNS" \
TRADES_PER_RUN="$TRADES" \
UNCAPPED_SWAPS="$UNCAPPED" \
MIN_BUY_ETH="$MINBUY" \
MAX_BUY_ETH="$MAXBUY" \
SWEEP_TAG="B${batch}" \
forge script analysis/ParameterSweepFuzzing.s.sol:ParameterSweepFuzzing \
--skip-simulation --gas-estimate-multiplier 300 -vv 2>&1 | grep "UNSAFE" || true
batch_csv="analysis/sweep-B${batch}-summary.csv"
if [ -f "$batch_csv" ]; then
new_lines=$(tail -n +2 "$batch_csv" | wc -l)
total_combos=$((total_combos + new_lines))
tail -n +2 "$batch_csv" >> "$SUMMARY_FILE"
rm "$batch_csv"
fi
done
done
done
elapsed=$(($(date +%s) - start_time))
echo ""
echo ""
echo -e "${GREEN}=== ANALYSIS ===${NC}"
echo "Elapsed: ${elapsed}s"
# Analyze results
total_tested=$(tail -n +2 "$SUMMARY_FILE" | wc -l | tr -d ' ')
unsafe_combos=$(tail -n +2 "$SUMMARY_FILE" | grep -c ',true,' || true)
unsafe_combos=${unsafe_combos:-0}
safe_combos=$((total_tested - unsafe_combos))
echo "Total tested: $total_tested"
echo -e "Safe: ${GREEN}$safe_combos${NC}"
echo -e "Unsafe: ${RED}$unsafe_combos${NC}"
# Generate report
RESULTS_FILE="analysis/PARAMETER_SEARCH_RESULTS.md"
cat > "$RESULTS_FILE" << EOF
# KRAIKEN Parameter Search Results
## Objective
Find optimizer parameters where the LiquidityManager NEVER loses ETH regardless of trade sequence.
## Methodology
- **Mode**: $MODE
- **Runs per parameter combination**: $RUNS
- **Trades per run**: $TRADES
- **Uncapped swaps**: $UNCAPPED (trades push through position boundaries)
- **Trade size range**: ${MINBUY}-${MAXBUY} ETH (vs 100 ETH LM balance)
- **VWAP accumulation**: Environment reused across runs per combo
- **Buy biases tested**: $(echo $BB | tr ',' ', ')%
- **Total combinations tested**: $total_tested
- **Elapsed time**: ${elapsed}s
### Parameters Searched
| Parameter | Values | Description |
|-----------|--------|-------------|
| capitalInefficiency | $(python3 -c "print(', '.join(f'{int(x)/1e18:.0%}' for x in '$CI'.split(',')))" 2>/dev/null || echo "$CI") | Capital buffer (0=aggressive, 1e18=conservative) |
| anchorShare | $(python3 -c "print(', '.join(f'{int(x)/1e18:.1%}' for x in '$AS'.split(',')))" 2>/dev/null || echo "$AS") | ETH allocation to anchor vs floor |
| anchorWidth | $(echo $AW | tr ',' ', ') | Anchor position width (1-100) |
| discoveryDepth | $(python3 -c "print(', '.join(f'{int(x)/1e18:.0%}' for x in '$DD'.split(',')))" 2>/dev/null || echo "$DD") | Discovery liquidity density |
| buyBias | $(echo $BB | tr ',' ', ')% | Adversarial trade mix (80=buy-heavy, 100=buy-only) |
### Key Metrics
- **Trader PnL < 0**: LM gained ETH (SAFE). Trader lost money.
- **Trader PnL > 0**: LM lost ETH (UNSAFE). Trader extracted ETH.
## Results Summary
- **Safe combinations**: $safe_combos / $total_tested
- **Unsafe combinations**: $unsafe_combos / $total_tested
EOF
if [ "$unsafe_combos" -gt 0 ]; then
{
echo ""
echo "## UNSAFE Parameters (Trader Profited = LM Lost ETH)"
echo ""
echo "| CI | AnchorShare | AnchorWidth | DiscoveryDepth | BuyBias | Max Trader PnL (ETH) |"
echo "|-----|-------------|-------------|----------------|---------|----------------------|"
while IFS=, read -r ci as aw dd bb maxpnl minpnl loss lmdelta; do
if [[ "$loss" == "true" ]]; then
ci_pct=$(python3 -c "print(f'{int(\"$ci\")/1e18:.0%}')" 2>/dev/null || echo "$ci")
as_pct=$(python3 -c "print(f'{int(\"$as\")/1e18:.1%}')" 2>/dev/null || echo "$as")
dd_pct=$(python3 -c "print(f'{int(\"$dd\")/1e18:.0%}')" 2>/dev/null || echo "$dd")
maxpnl_eth=$(python3 -c "print(f'{int(\"$maxpnl\")/1e18:+.4f}')" 2>/dev/null || echo "$maxpnl")
echo "| $ci_pct | $as_pct | $aw | $dd_pct | $bb | $maxpnl_eth |"
fi
done < <(tail -n +2 "$SUMMARY_FILE")
} >> "$RESULTS_FILE"
fi
{
echo ""
echo "## SAFE Parameters"
echo ""
} >> "$RESULTS_FILE"
if [ "$safe_combos" -gt 0 ]; then
{
echo "All tested parameter combinations where the LM never lost ETH:"
echo ""
echo "### Safe Ranges by Buy Bias"
echo ""
} >> "$RESULTS_FILE"
for bb_val in $(echo "$BB" | tr ',' ' '); do
safe_at_bb=$(tail -n +2 "$SUMMARY_FILE" | grep ",$bb_val," | grep -c ',false,' || true)
safe_at_bb=${safe_at_bb:-0}
total_at_bb=$(tail -n +2 "$SUMMARY_FILE" | grep -c ",$bb_val," || true)
total_at_bb=${total_at_bb:-0}
echo "- **BuyBias=${bb_val}%**: ${safe_at_bb}/${total_at_bb} safe" >> "$RESULTS_FILE"
done
{
echo ""
echo "### Top 20 Safest Combinations (most negative max trader PnL = hardest to exploit)"
echo ""
echo "| CI | AnchorShare | AnchorWidth | DiscoveryDepth | BuyBias | Max Trader PnL (ETH) |"
echo "|-----|-------------|-------------|----------------|---------|----------------------|"
} >> "$RESULTS_FILE"
tail -n +2 "$SUMMARY_FILE" | grep ',false,' | sort -t, -k6 -n | head -20 | while IFS=, read -r ci as aw dd bb maxpnl minpnl loss lmdelta; do
ci_pct=$(python3 -c "print(f'{int(\"$ci\")/1e18:.0%}')" 2>/dev/null || echo "$ci")
as_pct=$(python3 -c "print(f'{int(\"$as\")/1e18:.1%}')" 2>/dev/null || echo "$as")
dd_pct=$(python3 -c "print(f'{int(\"$dd\")/1e18:.0%}')" 2>/dev/null || echo "$dd")
maxpnl_eth=$(python3 -c "print(f'{int(\"$maxpnl\")/1e18:+.4f}')" 2>/dev/null || echo "$maxpnl")
echo "| $ci_pct | $as_pct | $aw | $dd_pct | $bb | $maxpnl_eth |"
done >> "$RESULTS_FILE"
else
echo "No safe parameter combinations found." >> "$RESULTS_FILE"
fi
{
echo ""
echo "## Recommendations"
echo ""
} >> "$RESULTS_FILE"
if [ "$unsafe_combos" -eq 0 ]; then
cat >> "$RESULTS_FILE" << 'RECO'
**All tested parameter combinations are SAFE.** The three-position strategy's asymmetric
slippage profile effectively prevents profitable arbitrage across all tested parameters.
RECO
else
cat >> "$RESULTS_FILE" << 'RECO'
**Some parameter combinations are UNSAFE.** The exploitation boundary depends primarily on:
1. **anchorShare**: Higher values allocate more ETH to the thin anchor position, reducing floor protection
2. **capitalInefficiency**: Lower values (0%) make the floor position more aggressive, increasing exploit risk
3. **anchorWidth**: Narrower widths concentrate anchor liquidity, making it cheaper to push through
### Safe Zone
Parameters where the trader never profited across all tested scenarios.
### Unsafe Zone
Parameters where at least one test run showed trader profit (= LM ETH loss).
The exploitation pattern is: buy→recenter→sell→recenter repeated over many cycles,
where VWAP accumulates at inflated prices and the floor gets positioned too high.
RECO
fi
{
echo ""
echo "---"
echo "*Generated: $(date -u +%Y-%m-%dT%H:%M:%SZ)*"
} >> "$RESULTS_FILE"
echo ""
echo -e "${GREEN}Report: $RESULTS_FILE${NC}"
echo -e "${GREEN}Data: $SUMMARY_FILE${NC}"