A conservative PumpAPI-powered trading bot with Jito bundle support and one shared code path for live trading, paper trading, and historical replay.
- Connects to the PumpAPI WebSocket stream for live or paper-mode signal processing.
- Uses a safety-first strategy layer with token filters, locked-liquidity checks, post-migration fee checks, alpha confirmation, and risk controls.
- Submits orders via Jito bundles (atomic, front-run-resistant) or standard PumpAPI Actions for optimal execution.
- Supports claimCashback, burn, wrapSol, transfer, createToken, and migrate operations for full account lifecycle management.
- Routes execution through the same
ExecutionServicefor live, unsigned, and simulated trades. - Stores every fill and rejection in an SQLite database (
trades.sqlite) for crash recovery, restart safety, and post-session analysis. - Logs every token rejection with stage, reason, confidence, and a full event snapshot so filter tuning never happens blind.
- Runs post-session analysis after every replay — portfolio PnL, win rate, max drawdown, profit factor, and a pipeline-funnel breakdown of every filter stage.
- Replays PumpAPI hourly archives from compressed
.jsonl.zstfiles with realistic simulation of latency, slippage, spread, and fees. - Retries transient API failures with exponential backoff (3 attempts, 200ms base).
Runs the bot against the realtime stream and sends real orders through PumpAPI using Jito bundles.
LIVE_MODE=true PRIVATE_KEY=<key> cargo run --release -- liveWhen only PUBLIC_KEY is provided, the bot still routes orders to the live
PumpAPI endpoint but with publicKey instead of privateKey. The API returns
a base64-encoded transaction that must be signed and submitted externally.
LIVE_MODE=true PUBLIC_KEY=<key> cargo run --release -- liveA warning is logged at startup; execution proceeds normally.
Runs the same strategy and execution flow, but fills are simulated locally with realistic latency, spread, slippage, and fee modelling.
cargo run --release -- liveDownloads PumpAPI replay archives, caches them locally, and feeds every event into the same engine used for paper and live trading. Pacing and simulation parameters keep the replay close to real-time behaviour. After all events are processed, a full analysis report is printed to stdout.
cargo run --release -- replay \
--start 2026-04-18T00:00:00Z \
--end 2026-04-19T00:00:00Z \
--speed 1.0Analyse an existing SQLite database without re-running the replay:
cargo run --release -- analyze --db trades.sqliteOutput includes win rate, total PnL, avg win/loss, profit factor, expectancy, max drawdown, average hold time, and rejection breakdowns by stage and reason.
When JITO_ENABLED=true (default after copying .env), orders are submitted as Jito bundles for:
- Front-run resistance — transactions land in a specific block without MEV extraction.
- Atomic execution — buy and sell are bundled together.
- Guaranteed delivery — sells are re-submitted until confirmed.
- Priority via tip —
JITO_TIP_SOLincentivises validators to include your bundle.
The replay loader expects hourly compressed files in this shape:
https://replay.pumpapi.io/YYYY/MM/DD/HH.jsonl.zst
Each decompressed line is a single JSON event in the same schema as the live data stream.
- Copy
.env.exampleto.env. - Fill in your wallet keys and Telegram settings.
- Install Rust (
rustup install stable). - Run one of the commands above.
cp .env.example .env
cargo run --release -- live| Variable | Purpose | Default |
|---|---|---|
LIVE_MODE |
true for live trading, false for paper |
false |
PRIVATE_KEY |
Live trading wallet private key (base58) | — |
PUBLIC_KEY |
Public key for unsigned live trading | — |
PUMPAPI_URL |
PumpAPI HTTP endpoint | https://api.pumpapi.io |
STREAM_URL |
WebSocket stream endpoint | wss://stream.pumpapi.io/ |
STREAM_RECONNECT_SECS |
Stream reconnection delay (s) | 5 |
REPLAY_BASE_URL |
Historical replay archive base URL | https://replay.pumpapi.io |
REPLAY_CACHE_DIR |
Local cache for replay archives | ./replay-cache |
JITO_ENABLED |
Use Jito bundles for order submission | true |
JITO_TIP_SOL |
Tip in SOL for Jito validators | 0.0002 |
SLIPPAGE_PCT |
Max slippage on live orders (%) | 20.0 |
PRIORITY_FEE_SOL |
Base priority fee for transactions | 0.00002 |
QUOTE_MINT |
Restrict trading to this quote-mint | — |
POOL_ID |
Restrict trading to this specific pool | — |
ACCOUNT_BALANCE_SOL |
Starting balance for sizing and reports | 20.0 |
MAX_RISK_PCT |
Maximum risk per trade (%) | 1.0 |
MAX_DAILY_LOSS_PCT |
Halt entries after daily drawdown (%) | 5.0 |
MAX_CONCURRENT_POSITIONS |
Position cap | 5 |
MIN_POSITION_SOL |
Minimum position size | 0.05 |
MAX_POSITION_SOL |
Maximum position size | 0.25 |
TP_PCT |
Default take-profit percentage | 30.0 |
SL_PCT |
Default stop-loss percentage | 10.0 |
TRAILING_STOP |
Enables trailing exits | true |
TRAILING_ACTIVATION_PCT |
Trailing distance from the peak | 15.0 |
POSITION_TTL_MINUTES |
Max hold time before forced close (0=disabled) | 30 |
MIN_MC_QUOTE |
Minimum market cap filter (SOL) | 20.0 |
MAX_MC_QUOTE |
Maximum market cap filter (SOL) | 500.0 |
MAX_POOL_FEE_RATE |
Pool fee soft-penalty threshold | 0.02 |
MIN_LOCKED_LIQUIDITY_PCT |
Soft penalty threshold for locked liquidity (%) | 100.0 |
MAX_POOL_FEE_RATE_AFTER_MIGRATION |
Soft penalty threshold for post-migration fee | 0.05 |
REQUIRE_BURNED_LIQUIDITY_PCT |
Burned liquidity soft-penalty threshold (%) | 50.0 |
ALLOW_MAYHEM_MODE |
Permit mayhem-mode pools | false |
ALLOW_CUSTOM_POOLS |
Permit custom pools | false |
SIM_LATENCY_MS |
Simulated fill latency | 450 |
SIM_SPREAD_BPS |
Simulated spread (basis points) | 15.0 |
SIM_PRICE_IMPACT_BPS_PER_NOTIONAL |
Price impact per SOL notional | 8.0 |
SIM_FEE_BPS |
Simulated round-trip fee (basis points) | 10.0 |
TELEGRAM_ENABLED |
Enable Telegram reporting | false |
TELEGRAM_BOT_TOKEN |
Telegram bot token | — |
TELEGRAM_CHAT_ID |
Telegram chat ID | — |
TELEGRAM_MAX_RETRIES |
Telegram retry limit | 5 |
TELEGRAM_INITIAL_BACKOFF_MS |
Initial Telegram retry delay (ms) | 500 |
TELEGRAM_MAX_BACKOFF_MS |
Maximum Telegram retry delay (ms) | 10000 |
The old JSONL journal (JOURNAL_PATH, JOURNAL_MAX_BYTES) has been replaced by
an SQLite database (trades.sqlite by default). These variables are still
accepted but ignored.
- Live execution depends on PumpAPI order validation and on-chain conditions.
- LocalUnsigned mode sends the public key; the API returns an unsigned transaction that must be signed off-chain.
- Paper trading and replay use a realistic simulation model that includes latency drift, bid-ask spread, price impact, and fees. Results should approximate live performance but are not guaranteed to match.
- No strategy can guarantee profit; use conservative sizing and test first.
- Exit priority: stop-loss → trailing stop → take-profit → TTL (time limit).
- All PumpAPI endpoints use
POST /— theactionfield in the JSON body routes internally (buy,sell,create,migrate,burn,claimCashback,wrapSol,transfer,getBalances,getTokenInfo). - Telegram timestamps are displayed in Jalali (Persian) calendar with Tehran timezone.
trades.sqlite— SQLite database withtradesandrejection_logtables./replay-cache/— cached hourly replay archives