TradR.fun is a free and opensource cryptocurrency price signal prediction application.
Gemini BTC/USDT Ladder Trading Bot
A simple, deterministic ladder trading bot for Gemini with FastAPI web UI. Runs on Raspberry Pi with file-based storage (no database required).
Features
- Ladder Buy Strategy: Scale into BTC position as price drops
- Ladder Sell Strategy: Scale out of BTC position as price rises with profit
- VWAP Tracking: Maintains accurate cost basis across all trades
- Paper Trading: Test strategy without real money
- Web UI: Monitor, configure, and analyze via browser
- Persistent State: Survives restarts with file-based storage
- Single Process: Simple architecture, easy to run
Quick Start
1. Install Dependencies
# Run the setup script (creates venv and installs deps)
./setup.sh
Or manually:
python3 -m venv venv
./venv/bin/pip install -r requirements.txt
2. Configure Gemini API Credentials
Edit data/secrets.json:
{
"apikey": "YOURGEMINIAPIKEY",
"apisecret": "YOURGEMINIAPISECRET"
}
Get your API keys from: https://exchange.gemini.com/settings/api
Important:
- Enable "Trading" permission
- Save your API secret securely (shown only once)
3. Configure Strategy
Edit data/config.json to customize:
paper_mode: Set tofalsefor live trading (default:true)enabled_trading: Enable/disable trading (default:true)buy_ladder: Define buy rungs (drop %, USDT amount)sell_ladder: Define sell rungs (rise %, % of BTC)maxbtcexposure_pct: Maximum BTC exposure (default: 75%)cooldown_seconds: Wait time between trades (default: 300s)
4. Run the Bot
./venv/bin/uvicorn app:app --host 0.0.0.0 --port 8000
Or activate venv and run:
source venv/bin/activate
uvicorn app:app --host 0.0.0.0 --port 8000
5. Access Web UI
Open browser to: http://localhost:8000 (or http://YOURPIIP:8000)
Web Interface
- Dashboard (
/): Real-time status, balances, positions, ladder status - Config (
/config): Edit strategy parameters via JSON form - History (
/history): View all fills and orders - Charts (
/charts): Equity curve, BTC holdings, price vs VWAP
Auto-Start on Raspberry Pi
Option 1: systemd Service (Recommended)
# Copy service file
sudo cp cryptobot.service /etc/systemd/system/
Edit paths in service file if needed
sudo nano /etc/systemd/system/cryptobot.service
Enable and start service
sudo systemctl enable cryptobot.service
sudo systemctl start cryptobot.service
Check status
sudo systemctl status cryptobot.service
View logs
sudo journalctl -u cryptobot.service -f
Option 2: Crontab (Fallback)
# Edit crontab
crontab -e
Add this line (adjust paths):
@reboot cd /home/pi/crypto_bot && /usr/bin/python3 -m uvicorn app:app --host 0.0.0.0 --port 8000 >> data/events.log 2>&1
Strategy Explanation
Buy Ladder (Scale-In)
Bot places buy orders as price drops below reference price (last fill price):
Example:
- Drop 2% โ Buy $100 USDT worth
- Drop 4% โ Buy $150 USDT worth
- Drop 7% โ Buy $200 USDT worth
- Drop 11% โ Buy $250 USDT worth
- Drop 16% โ Buy $300 USDT worth
- Maximum of
maxbuyrungscan be filled - Won't exceed
maxbtcexposure_pct - Cooldown enforced between fills
- Only one order at a time
Sell Ladder (Scale-Out)
Bot places sell orders as price rises above VWAP (cost basis):
Example:
- Rise 3% above VWAP โ Sell 25% of BTC
- Rise 6% above VWAP โ Sell 25% of BTC
- Rise 10% above VWAP โ Sell 25% of BTC
- Rise 16% above VWAP โ Sell 15% of BTC
- Rise 25% above VWAP โ Sell 10% of BTC
- Sell threshold includes
feebufferbpsto ensure profit - Won't sell if no BTC position
- Cooldown enforced between fills
- Only one order at a time
VWAP Accounting
Bot maintains accurate cost basis:
- On BUY: Add to total BTC and total cost
- On SELL: Subtract from total BTC and cost (using VWAP)
- On ZERO position: Reset state and reference price
File Structure
crypto_bot/
โโโ app.py # Main application
โโโ requirements.txt # Python dependencies
โโโ cryptobot.service # Systemd service file
โโโ README.md # This file
โโโ data/ # Data directory (created automatically)
โโโ config.json # Strategy parameters (editable)
โโโ secrets.json # API credentials (sensitive)
โโโ state.json # Runtime state (persistent)
โโโ orders.csv # Order history (append-only)
โโโ fills.csv # Fill history (append-only)
โโโ equity.csv # Equity snapshots (append-only)
โโโ events.log # Application logs (append-only)
Safety Features
- Paper Mode: Test without real money
- Cooldown: Prevents rapid-fire trading
- Exposure Limits: Caps maximum BTC position
- Limit Orders Only: Never uses market orders
- Fee Buffer: Ensures profitable sells
- Persistent State: Survives crashes and restarts
- Nonce Management: Strict ordering for API requests
Monitoring
View Logs
tail -f data/events.log
Check Status
curl http://localhost:8000/api/equity.json | jq
Systemd Service
sudo systemctl status cryptobot.service
sudo journalctl -u cryptobot.service -f
Configuration Reference
config.json
| Parameter | Type | Description | Default | |-----------|------|-------------|---------| | symbol | string | Trading pair | "btcusdt" | | loop_seconds | int | Loop interval in seconds | 60 | | enabled_trading | bool | Enable/disable trading | true | | paper_mode | bool | Paper trading mode | true | | limitoffsetbps | int | Limit order offset (basis points) | 5 | | feebufferbps | int | Minimum profit buffer (basis points) | 60 | | maxbtcexposure_pct | float | Maximum BTC exposure % | 75 | | maxbuyrungs | int | Maximum buy rungs to fill | 5 | | cooldown_seconds | int | Cooldown after fills | 300 | | buy_ladder | array | Buy rung definitions | See config.json | | sell_ladder | array | Sell rung definitions | See config.json |
Buy Rung
{
"drop_pct": 2.0, // % drop from reference price
"usdt_amount": 100 // USDT to spend
}
Sell Rung
{
"rise_pct": 3.0, // % rise above VWAP
"pct_btc": 25 // % of BTC holdings to sell
}
Troubleshooting
Bot Not Trading
- Check
enabled_tradingistruein config.json - Check API credentials in data/secrets.json
- Verify sufficient balance
- Check logs:
tail -f data/events.log
API Errors
- 403 Forbidden: Invalid API key or signature
- Nonce errors: Delete state.json and restart (CAUTION: resets tracking)
- Rate limits: Increase
loop_seconds
Web UI Not Accessible
# Check if running
ps aux | grep uvicorn
Check port
sudo netstat -tlnp | grep 8000
Check firewall
sudo ufw status
sudo ufw allow 8000/tcp
Development
Test in Paper Mode
- Set
paper_mode: truein config.json - Bot will log "SIMULATED ORDER" instead of placing real orders
- State tracking still works normally
Modify Strategy
- Edit config.json via web UI at
/config - Changes take effect on next loop cycle
- No restart required
Reset State
WARNING: This will reset VWAP tracking and rung states.
# Backup first
cp data/state.json data/state.json.backup
Reset
echo '{"lastnonce": 0, "lasttradeid": null, "lastfillprice": null, "btctotal": 0, "costusdttotal": 0, "filledbuyrungs": [], "filledsellrungs": [], "lastfillts": 0}' > data/state.json
Advanced
Multiple Instances
Run multiple bots on different ports:
uvicorn app:app --host 0.0.0.0 --port 8001
uvicorn app:app --host 0.0.0.0 --port 8002
Each needs separate data/ directory.
Custom Data Directory
Modify DATA_DIR in app.py:
DATA_DIR = Path("/custom/path/to/data")
Security Notes
- Never commit secrets.json to version control
- Use
.gitignoreto exclude sensitive files - Restrict file permissions:
chmod 600 data/secrets.json - Use Gemini API IP whitelist if possible
- Monitor logs for unauthorized access
Support
- Gemini API Docs: https://docs.gemini.com/rest-api/
- Issues: Check logs in
data/events.log - Configuration: All settings in
data/config.json
License
This is a simple trading bot for educational purposes. Use at your own risk.
DISCLAIMER: Trading cryptocurrencies involves substantial risk. This bot is provided as-is with no warranty. Always test in paper mode first. Never trade with money you can't afford to lose.