Automated delta-neutral bot that captures funding rate spreads between Extended and Pacifica perpetual futures exchanges.
Can also be used to farm trading volume while limiting risk (refreshes positions every hold_duration_hours=12 hours by default, but can be changed).
π° Support this project:
- Extended: Sign up at extended.xyz
- Pacifica: Sign up at app.pacifica.fi and use one of the following referral codes when registering (if one is already taken, try another):
BYVJRCM791XFCF5K ENPVKJ1WAVYNV2Z0 6HR2WM4C0JQ7D39Q 411J9J7CYNFZN3SX 2K7D40A9H53M2TJT S1G3A2063Q7410BV XH2V3VY9CQ7535CX EK8NXX12VDKJJWNK 6NBS6TT7Y1SV2P53 E5ZYTD2FVXJA123W
The bot maintains market-neutral positions by going long on the exchange with lower funding rate and short on the exchange with higher funding rate, collecting the funding rate differential while minimizing directional price risk.
Can also be used to farm trading volume while limiting risk (refreshes positions every hold_duration_hours=12 hours by default, but can be changed).
π‘ Example: If Extended funding is +10% APR and Pacifica is +50% APR:
- Long position on Extended (pay 10%)
- Short position on Pacifica (receive 50%)
- Net profit: ~40% APR
pip install -r requirements.txtCopy .env.example to .env and add your credentials:
cp .env.example .envEdit .env with your API keys:
- Extended:
EXTENDED_BASE_URL,EXTENDED_API_KEY,EXTENDED_API_SECRET,EXTENDED_ACCOUNT_ID, optionalEXTENDED_SUBACCOUNT - Pacifica:
SOL_WALLET,API_PUBLIC,API_PRIVATE
Edit bot_config.json:
{
"symbols_to_monitor": ["BTC", "ETH", "SOL", "ASTER", ...],
"leverage": 3,
"base_capital_allocation": 100.0,
"hold_duration_hours": 12.0,
"min_net_apr_threshold": 5.0
}Key Parameters:
base_capital_allocation: Base capital in USD (actual position = base Γ leverage Γ 0.98 buffer)leverage: Target leverage (auto-capped at 20x, reduced if exchange limits are lower)hold_duration_hours: How long to hold each positionmin_net_apr_threshold: Minimum funding spread to open position
python extended_pacifica_hedge.py# Build the image
docker-compose build
# Build and start
docker-compose up -d
# View logs
docker-compose logs -f hedge-bot
# Stop
docker-compose down
# Rebuild after code changes
docker-compose build && docker-compose up -d- π Analyze: Fetches funding rates from both exchanges every cycle and prints a funding APR table (Extended 8h rate converted to hourly, Pacifica hourly rate)
- π― Select: Chooses symbol with highest net APR above threshold
- π Open: Opens delta-neutral position (long/short) with synchronized leverage
- β±οΈ Hold: Monitors position health and waits for the configured holding period
- π Close: Closes both positions simultaneously
- βΈοΈ Wait: Brief cooldown before next cycle
- β Balance Checks: Confirms both venues have sufficient collateral before opening a position.
- β
State Persistence: Saves progress to
bot_state_extended_pacifica.jsonso restarts resume safely. - β Graceful Shutdown: Attempts to close any open position if a shutdown signal is received.
- β
Emergency Closer:
python emergency_close.py --forcewill flatten all legs on both venues using the same environment defaults as the bot.
- Extended API returns cumulative 8-hour funding; the bot and test suite convert this to hourly by dividing by 8 before annualising (Γ8760).
- Pacifica API returns hourly funding; the bot multiplies directly by 24Γ365 to derive APR.
- Funding snapshots are logged at startup, before opening a position, and during position monitoring so you can compare both exchanges quickly.
With base_capital_allocation: 100:
| Leverage | Safety Buffer | Position Size per Exchange |
|---|---|---|
| 1x | $98 | $98 |
| 3x | $98 | $294 |
| 5x | $98 | $490 |
| 10x | $98 | $980 |
Position size is further reduced if insufficient margin available (uses 95% of max available).
Stop-loss is triggered by the worst leg PnL (not total PnL) to protect against one-sided losses that could lead to liquidation.
| Leverage | Stop-Loss % | Capital Loss at Trigger | Buffer Before Liquidation |
|---|---|---|---|
| 1x | -50% | 50% | ~50% |
| 3x | -20% | 60% | ~40% |
| 5x | -12% | 60% | ~40% |
| 10x | -6% | 60% | ~40% |
| 20x | -3% | 60% | ~40% |
When triggered: Both positions are immediately closed via market orders, PnL is calculated, and the bot enters a waiting period (5 minutes by default) before starting a new cycle.
The bot displays comprehensive color-coded status during position holding (every 60 seconds by default):
Status includes:
- Position timing and time remaining
- Position sizes and notional value
- Account balances and total equity
- Long-term PnL since bot start (tracked via initial capital)
- Current leverage on both exchanges
- Real-time funding rates and spread
- Individual leg PnL (Extended and Pacifica)
- Total unrealized PnL
- Risk metrics: Stop-loss level, current PnL %, worst leg performance, distance to stop-loss
Close all open positions on both exchanges:
# Interactive mode - shows positions and asks to press Enter to confirm
python emergency_close.py
# Close specific symbol only
python emergency_close.py --symbol BTC
# Close all without confirmation
python emergency_close.py --force
# Preview without executing
python emergency_close.py --dry-runThe script scans symbols from bot_config.json and displays all open positions with PnL. In interactive mode, simply press Enter to confirm closing (or Ctrl+C to cancel).
Check market conditions before running the bot:
# Check 24h trading volume for all symbols
python check_24h_volume.py
# Check mid-price spreads between exchanges
python check_spreads.py
# Use custom config file
python check_24h_volume.py --config custom_config.json
python check_spreads.py --config custom_config.jsoncheck_24h_volume.py: Displays 24h trading volume in both base currency and USD for all symbols on both exchanges. Helps identify liquid markets.
check_spreads.py: Shows bid/ask/mid prices and spread percentages between Extended and Pacifica. Helps identify symbols with tight spreads for optimal trading.
Test your setup with the included test suite:
# Test Extended connection and balance
python test/test_extended_balance.py
# Test Pacifica connection and balance
python test/test_pacifica_balance.py
# Test funding rates
python test/test_extended_funding.py
python test/test_pacifica_funding.py
# Test positions
python test/test_extended_positions.py
python test/test_pacifica_positions.py
# Full lifecycle test (opens and closes positions - uses real funds!)
python test/test_extended_market_order.py
python test/test_pacifica_market_order.pySee test/README_TESTS.md for detailed documentation on all available tests.
Note: Market order tests place real orders and use real funds. Start with small amounts.
extended_pacifica_hedge.py- Main botemergency_close.py- Emergency position closercheck_24h_volume.py- Volume checker utilitycheck_spreads.py- Spread checker utilityextended_client.py- Extended exchange wrapperpacifica_client.py- Pacifica exchange clientbot_config.json- Configurationbot_state_extended_pacifica.json- Persistent state (auto-created)logs/extended_pacifica_hedge.log- Log file (resets on start)
- Single Position: Bot manages one position at a time
- Symbol Filtering: Symbols not on both exchanges are automatically ignored
- Volume & Spread Filtering: Checked at startup and before each cycle to ensure liquid, efficient markets
- Minimum $50M 24h volume on Pacifica
- Maximum 0.15% spread between exchanges
- Cycle Tracking: Cycle number persists across restarts
- Initial Capital: Captured at first run and used for long-term PnL calculation
- Monitoring Frequency: Position checked every 60 seconds by default (
check_interval_seconds) - Stop-Loss Protection: Based on worst performing leg, not total PnL
- Log Reset: Log file resets on every bot start
- UTC Timestamps: All times displayed in UTC
CLAUDE.md- Detailed architecture and development guide for Claude Codetest/README_TESTS.md- Test suite documentation.env.example- Environment variable template
- Python 3.12+
- Active accounts on Extended and Pacifica
- Sufficient balance on both exchanges (~$50+ recommended per exchange)
- API credentials with trading permissions
This bot is for educational and research purposes. Use at your own risk. Always test with small amounts first.
