Skip to content

Repository files navigation

aerodrome-lp-studio

Related articles: The Agentic Quant Desk · Part 1: Building the Harness

Aerodrome (Base) LP management + sniping primitives, with a dashboard — in one repo. Discover pools, read gauge emissions, compute position PnL & impermanent loss, mint/stake/remove on-chain, and see it all in a Streamlit UI.

Extracted from a private trading desk. Mechanics only — pool discovery, gauge/PnL/IL reads, an on-chain executor, and a dashboard. The tuned sniping selection, range-sizing, and rebalance triggers (the edge) stay private; sniping is shown here as primitives + a trivial example rule you replace.

Two halves, one install

src/aero_lp/          on-chain primitives
                      pool discovery · gauge/emission · PnL & IL · mint/stake/remove executor
                      deployment registry · math · backtest CL valuation

src/aero_dashboard/   Streamlit UI
                      JSONL loaders · equity/drawdown/metrics components
                      metrics.py SessionAnalyzer · live.py glue → aero_lp

examples/             manage_demo.py (live PnL) · snipe_demo.py (rank + dry-run mint)
                      backtest_lp.py (offline sim) · sample-snapshots/ (demo data)

pip install -e . gives you the CLI, Python libraries, and dashboard:

aero-lp --help
aero-lp doctor
aero-lp schema
python -m aero_lp --help
aero-dashboard

Run the dashboard (offline, no keys)

pip install -e .
streamlit run src/aero_dashboard/app.py   # 3 bundled samples: equity, drawdown, metrics, hedge

CLI-first LP workflow

All LP analysis and operations are available through aero-lp. Work commands return a JSON envelope:

{"success": true, "data": {}, "timestamp": "..."}

Discovery and research:

aero-lp doctor
aero-lp schema rank-pools
aero-lp tokens
aero-lp pools WETH cbBTC --tick-spacing 50
aero-lp rank-pools WETH cbBTC --tick-spacing 50
aero-lp pool-state <pool>
aero-lp suggest-range <pool> --width-bps 500
aero-lp backtest neutral --token0 WETH --token1 cbBTC --hours 240 --capital 10000
aero-lp backtest directional --token0 WETH --token1 cbBTC --hours 240 --capital 10000
aero-lp backtest hedge --symbol-a ETHUSDT --symbol-b BTCUSDT --capital 30000
aero-lp walk-forward --token0 WETH --token1 cbBTC --hours 1000 --window 168 --stride 24

Live reads and dry-run operations:

aero-lp position-pnl <token_id> --gauge <gauge>
aero-lp should-rebalance <token_id> --gauge <gauge>
aero-lp live-apr <token_id> --gauge <gauge> --range-width-ticks 10
aero-lp mint --token0 WETH --token1 cbBTC --tick-spacing 50 --tick-lower <lo> --tick-upper <hi> --amount0 <raw> --amount1 <raw>
aero-lp rebalance <token_id> --tick-lower <lo> --tick-upper <hi> --gauge <gauge>

Write commands are dry-run by default. Add --execute only after reviewing the dry-run output. Use aero-lp schema <command> for required parameters, units, key JSON fields, common failures, and next actions.

Encrypted wallet (recommended for live)

Keys are encrypted at rest (Ethereum keystore — scrypt + AES-128-CTR). Only the password is needed at runtime; no plaintext key ever touches disk or the env.

python -m aero_lp.aerodrome.cli_keystore generate  # new wallet → keystore (prompts password)
python -m aero_lp.aerodrome.cli_keystore encrypt   # or encrypt a key you already have
python -m aero_lp.aerodrome.cli_keystore info      # show address (no decrypt)
python -m aero_lp.aerodrome.cli_keystore verify    # test decryption

Default keystore file is base_wallet.json (override with KEYSTORE_PATH). At runtime:

export KEYSTORE_PASSWORD='...'   # only secret in the env; key stays encrypted on disk

The executor resolves a key automatically, in order: explicit private_key=encrypted keystore (KEYSTORE_PATH + KEYSTORE_PASSWORD) → plaintext BASE_PRIVATE_KEY. So once the keystore + password are set, construct AerodromeExecutor(...) with no private_key= and it signs from the keystore.

Helpers are re-exported for convenience:

from aero_lp import load_key, get_keystore_address, get_default_wallet_address
addr = get_default_wallet_address()   # read address without decrypting

.gitignore already excludes *keystore*.json and base_wallet*.json. A generated wallet still needs manual funding (ETH for gas + pair tokens on Base).

Manage / snipe (live — needs an RPC)

export BASE_RPC_URL="https://mainnet.base.org"
aero-lp pools WETH cbBTC
aero-lp rank-pools WETH cbBTC
aero-lp suggest-range <pool> --width-bps 300
aero-lp mint --token0 WETH --token1 cbBTC --tick-spacing 50 --tick-lower <lo> --tick-upper <hi> --amount0 <raw> --amount1 <raw>
aero-lp stake <token_id> --gauge <gauge>

See docs/running-lp-strategies.md for the complete CLI runbook. Writes default to dry-run; supply RPC + keystore/private key (.env.example) and add --execute only to send. Verify deployment/gauge consistency before staking a migrated pair.

How the halves connect

The dashboard reads the same snapshot schema the toolkit (and the private bots) produce. live.py is the bridge: it calls aero_lp.GaugeMonitor.get_position_pnl(...) and shapes the result into the exact DataFrame the dashboard components render — so the same UI shows backtest samples (offline) or your live book (RPC).

Run a real strategy

Full walkthrough — discover → range → mint → stake → monitor → rebalance → exit — for WETH/cbBTC CL50 using either an S1-style sniper (emission-ranked entry) or an S17-style directional LP (hold + rebalance): docs/running-lp-strategies.md.

Agentic LP research skill

Agents should use the shared project-local skill at .agents/skills/quant-researcher/SKILL.md for LP analysis and management. Codex, Claude, and Gemini wrappers only point to this shared source. It keeps the agent workflow CLI-first and points to focused references for command contracts, live LP workflows, backtest/session metrics, decision rules, troubleshooting, and dry-run-first safety checks.

Backtest (offline, no keys)

A CL valuation engine ships in aero_lp.backtest (position value as price moves, IL vs HODL) and a session scorer in aero_dashboard.SessionAnalyzer (return, Sharpe, drawdown, time-in-range, rebalance efficiency — the same metrics used on paper/live data). What's not shipped is the price feed and the rebalance rule — those are yours (real candles + your edge).

aero-lp backtest neutral --token0 WETH --token1 cbBTC --hours 240 --capital 10000 --out-dir /tmp/aero-neutral
aero-lp backtest directional --token0 WETH --token1 cbBTC --hours 240 --capital 10000 --offset-pct 0.25
aero-lp backtest hedge --symbol-a ETHUSDT --symbol-b BTCUSDT --capital 30000
aero-lp compare --token0 WETH --token1 cbBTC --hours 240
aero-lp session-summary /tmp/aero-neutral --strategy neutral --pair WETH-cbBTC

Runnable examples remain under examples/, but the CLI is the agent/operator surface.

All examples fetch real Bybit prices (public klines, no API key) and fall back to synthetic GBM only if offline: The CLI backtests fetch real Bybit prices (public klines, no API key) and fall back to deterministic synthetic paths when offline. Pair→symbol resolution mirrors the live desk: direct (X/stable → that symbol), cross (WETH/cbBTC → ETHBTCUSDT), synthetic (ratio of two USDT legs).

Walk-forward (examples/walk_forward.py) — one path is one noisy number; slice a long history into many windows and judge against the distribution:

aero-lp walk-forward --token0 WETH --token1 USDC --hours 1000 --window 168 --stride 24

Your own signal/rule still replaces the stubs. (scenario_builder regime labelling / signal-driven sims / tuned policies stay private.)

Real APR, not a guess (examples/live_apr_backtest.py): emission APR is range/time-specific, so fetch it from a live position rather than hardcoding —

aero-lp live-apr <token_id> --gauge <gauge> --range-width-ticks 12
aero-lp rank-pools WETH cbBTC

live-apr returns the live position APR and optional range-sweep inputs; rank-pools gives prospective pool emission comparisons.

What's deliberately out

The tuned sniping logic — snipe_engine (efficiency scoring / pool selection), vol_range (adaptive range sizing), the rebalance/dust triggers, and the backtest's tuned layer (scenario_builder regime construction, signal-driven sims, rebalance policies). Those are the alpha. You get the primitives + a "pick the highest-emission pool" / "re-center on OOR" stub to replace with your own.

Test

pip install -e ".[dev]" && pytest   # primitives + IL math + dashboard render + alpha-absence

License

MIT.

About

Aerodrome (Base) LP management + sniping primitives with a Streamlit dashboard — pool discovery, gauge emissions, PnL & impermanent-loss reads, and an on-chain mint/stake/remove executor.

Topics

Resources

Stars

Watchers

Forks

Releases

Packages

Contributors

Languages