A production-ready automated options scalping bot powered by Alpaca's API. The bot performs pre-market scanning, real-time signal detection using EMA/RSI indicators, and enforces strict risk management with profit targets, stop-losses, and time-based exits.
- Pre-Market Scanning: Evaluates watchlist using weighted metrics (volume, gap %, IV rank, OI, ATR)
- Technical Analysis: EMA crossover detection with RSI confirmation and volume filters
- Smart Position Sizing: Risk-based allocation (configurable % of capital per trade)
- Exit Management: Multiple exit triggers (profit target, stop loss, EMA reversal, timeout, EOD)
- Discord Notifications: Real-time alerts for all trading events
- Web Dashboard: Beautiful real-time web interface for monitoring from any device
- Circuit Breaker: Automatic pause on repeated errors for safety
- Health Monitoring: Built-in health checks and error tracking
- 0DTE/1DTE Focus: Targets same-day or next-day expiration options
- Production Ready: Systemd service, logging, state persistence, comprehensive tests
- Python 3.9 or higher
- pip (Python package manager)
- Git
- Alpaca Trading Account (paper or live)
- Paper trading: Free with IEX data feed
- Live trading: Requires AlgoTrader Plus subscription ($99/month) for SIP data feed
- Discord Webhook (optional, for notifications)
- Raspberry Pi 4 (2GB+ RAM) or any Linux/macOS machine
- Stable internet connection
- Recommended: UPS for power backup
git clone <your-repo-url>
cd scalp-botchmod +x setup.sh
./setup.shcp config.yaml.example config.yaml
# Edit config.yaml with your API keys and preferencessource venv/bin/activate
pytestpython main.pyObtain your Alpaca API keys:
- Sign up at alpaca.markets
- Navigate to Paper Trading or Live Trading dashboard
- Generate API keys
- Update
config.yaml:
alpaca:
paper:
api_key_id: "YOUR_PAPER_KEY"
api_secret_key: "YOUR_PAPER_SECRET"- Create a Discord server (or use existing)
- Create a channel for bot notifications
- Get webhook URL: Server Settings → Integrations → Webhooks → New Webhook
- Update
config.yaml:
notifications:
discord_webhook_url: "https://discord.com/api/webhooks/YOUR_WEBHOOK"Risk Management:
trading:
max_risk_pct: 0.01 # Risk 1% per trade
profit_target_pct: 0.15 # 15% profit target
stop_loss_pct: 0.07 # 7% stop lossSignal Filters:
signals:
ema_short_period: 9
ema_long_period: 21
rsi_call_min: 60 # Bullish above 60
rsi_put_max: 40 # Bearish below 40
volume_multiplier: 1.2 # 20% above averageTrading Windows:
signals:
trading_windows:
- "09:30-10:30" # Market open volatility
- "15:00-16:00" # Market close volatilityscalp-bot/
├── config.yaml # Runtime configuration and API credentials
├── requirements.txt # Python dependencies
├── main.py # Entry point and scheduler orchestration
├── broker.py # Alpaca API wrapper (orders, positions, data)
├── scan.py # Pre-market scanning and scoring logic
├── signals.py # Indicator calculations and signal validation
├── monitor.py # Position monitoring and exit enforcement
├── notifications.py # Discord webhook integration
├── utils.py # Shared helpers (config load, time utils, persistence)
└── data/
└── state.json # Persistent runtime state (e.g., ticker-of-the-day)
| Module | Purpose | Key Functions |
|---|---|---|
main.py |
Orchestrator | Scheduler, job coordination, circuit breaker, health checks |
broker.py |
Alpaca API | Market data, orders, positions, account info |
scan.py |
Pre-market analysis | Metric calculation, scoring, ticker selection |
signals.py |
Technical analysis | EMA/RSI indicators, signal detection, filters |
monitor.py |
Exit management | Position tracking, exit rule enforcement |
notifications.py |
Alerts | Discord webhook integration |
utils.py |
Utilities | Config, logging, state persistence, helpers |
08:30 ET → Pre-Market Scan
↓
Evaluate watchlist metrics
↓
Select Ticker of the Day
↓
Persist to state.json
↓
Alert via Discord
During Trading Windows (09:30-10:30, 15:00-16:00)
↓
Poll for price data (every 15s)
↓
Calculate EMA/RSI indicators
↓
Check for crossover signal
↓
Validate RSI + volume filters
↓
[Signal Detected]
↓
Select ATM/OTM option contract
↓
Calculate position size (1% risk)
↓
Submit buy order
↓
Wait for fill
↓
Persist position state
↓
Alert via Discord
Position Monitoring (every 5s)
↓
Check profit target (15%)
Check stop loss (7%)
Check EMA reversal
Check timeout (5 min)
Check EOD (15:55)
↓
[Exit Trigger]
↓
Close position
↓
Log trade to CSV
↓
Alert via Discord
- Circuit Breaker: Automatically pauses trading after 5 errors in 5 minutes
- Health Checks: Validates broker connectivity and state file access
- Error Tracking: Maintains error window for pattern detection
- Timeout Protection: Exits stale positions after 5 minutes
- EOD Exit: Force-closes positions 5 minutes before market close
- State Persistence: Survives restarts without losing position data
- Comprehensive Logging: All actions logged with timestamps
pytestpytest --cov=. --cov-report=html
# Open htmlcov/index.html for coverage reportpytest tests/test_utils.py -v
pytest tests/test_broker.py -v
pytest tests/test_signals.py -v- Unit Tests: Test individual functions and methods
- Integration Tests: Test module interactions (mark with
@pytest.mark.integration) - Mocked Tests: All external API calls are mocked for reliability
# Update system
sudo apt update && sudo apt upgrade -y
# Install dependencies
sudo apt install python3-pip python3-venv git -y
# Configure NTP for accurate time
sudo timedatectl set-timezone America/New_York
sudo apt install ntp -y
sudo systemctl enable ntpcd /home/pi
git clone <your-repo-url> scalp-bot
cd scalp-bot
./setup.sh# Copy service file
sudo cp scalp-bot.service /etc/systemd/system/
# Edit service file if needed (adjust paths/user)
sudo nano /etc/systemd/system/scalp-bot.service
# Enable and start
sudo systemctl daemon-reload
sudo systemctl enable scalp-bot
sudo systemctl start scalp-bot# Check service status
sudo systemctl status scalp-bot
# View logs
sudo journalctl -u scalp-bot -f
# Check bot logs
tail -f logs/bot.log- API keys configured and tested
- Discord webhook receiving notifications
- Watchlist contains liquid, high-volume symbols
- Risk parameters appropriate for account size
- Time zone configured correctly (US/Eastern)
- NTP service running for accurate time
- Systemd service enabled for auto-restart
- Log rotation configured
- Backup power (UPS) connected
- Monitoring/alerting configured
- Application logs:
logs/bot.log - Trade records:
data/trades.csv - Runtime state:
data/state.json - System logs:
journalctl -u scalp-bot
- Daily P/L: Track in
data/trades.csv - Win Rate: Number of profitable trades / total trades
- Average Return: Mean P/L percentage
- Max Drawdown: Largest peak-to-trough decline
- Error Rate: Check logs for exceptions
- Circuit Breaker: Monitor for activation events
The bot sends notifications for:
- ✅ Startup confirmation
- 🎯 Ticker of the Day selection
- 📈 Trade signals (call/put)
- 💰 Order fills
- 🚪 Position exits (with P/L and reason)
⚠️ Errors and warnings- 🛑 Circuit breaker activation
Manual health check:
from main import ScalpingBot
bot = ScalpingBot()
status = bot.health_check()
print(status)Check logs:
sudo journalctl -u scalp-bot -n 50Common issues:
- Missing API keys in config.yaml
- Invalid config.yaml syntax
- Permission issues on data/ or logs/ directories
- Python version < 3.9
Verify:
- Market is open:
broker.is_market_open() - Ticker selected: Check
data/state.json - Current time in trading window
- Sufficient account balance
- Signal criteria met (check logs for "Signal detected")
Steps:
- Review logs for root cause:
tail -100 logs/bot.log - Fix underlying issue (API keys, network, etc.)
- Restart service:
sudo systemctl restart scalp-bot - Monitor for recurrence
Check:
- Option liquidity (low volume options may not fill)
- Bid-ask spread too wide
- Market conditions (halt, circuit breaker)
- Account buying power
Optimize:
- Reduce polling frequency in config
- Decrease watchlist size
- Check for memory leaks in logs
- Monitor with
toporhtop
scalp-bot/
├── main.py # Bot orchestrator and entry point
├── broker.py # Alpaca API wrapper
├── scan.py # Pre-market scanning logic
├── signals.py # Technical indicators and signal detection
├── monitor.py # Position monitoring and exits
├── notifications.py # Discord integration
├── utils.py # Shared utilities
├── config.yaml # Configuration (not in git)
├── config.yaml.example # Configuration template
├── requirements.txt # Python dependencies
├── setup.sh # Setup automation script
├── scalp-bot.service # Systemd service definition
├── pytest.ini # Test configuration
├── .gitignore # Git ignore rules
├── README.md # This file
├── data/ # Runtime data (gitignored)
│ ├── state.json # Persistent bot state
│ └── trades.csv # Trade history log
├── logs/ # Application logs (gitignored)
│ └── bot.log # Rotating log file
└── tests/ # Unit tests
├── test_broker.py
├── test_scan.py
├── test_signals.py
├── test_monitor.py
├── test_notifications.py
└── test_utils.py
Contributions welcome! Please:
- Fork the repository
- Create a feature branch
- Add tests for new functionality
- Ensure all tests pass:
pytest - Submit a pull request
MIT License - see LICENSE file for details
This bot is for educational purposes only. Trading options involves substantial risk of loss. Past performance does not guarantee future results. Use at your own risk. The authors assume no liability for trading losses.