A paper trading bot that combines technical analysis with AI-powered news sentiment to make buy/sell decisions using fake money and real market data.
Trades only execute when both signals agree: strong technicals and confirming news sentiment. This two-layer filter reduces false signals and keeps the bot from acting on noise.
Alpaca Market Data (free IEX feed)
│
▼
┌─────────────────────┐
│ Technical Analysis │ RSI, SMA crossover, MACD, Bollinger Bands, Volume
│ (strategy.py) │ → weighted score from -1.0 to +1.0
└────────┬────────────┘
│ strong signals only (|score| ≥ 0.25)
▼
┌─────────────────────┐
│ News Headlines │ Fetched from Alpaca's Benzinga-sourced News API
│ (news.py) │ → last 24 hours, up to 6 per stock
└────────┬────────────┘
│
▼
┌─────────────────────┐
│ Claude Sentiment │ Claude Haiku classifies headlines as
│ (claude_strategy.py)│ BULLISH / BEARISH / NEUTRAL
└────────┬────────────┘
│ trade only if technicals + sentiment agree
▼
┌─────────────────────┐
│ Portfolio Manager │ Fractional shares, position limits,
│ (portfolio.py) │ cash management, CSV logging
└─────────────────────┘
- Python 3.10+
- Free Alpaca account (for market data + news)
- Anthropic API key (for Claude sentiment filter)
pip install -r requirements.txtCreate a .env file in the project root:
ALPACA_API_KEY=your_alpaca_key
ALPACA_SECRET_KEY=your_alpaca_secret
ANTHROPIC_API_KEY=your_anthropic_key
# Single scan (--force runs outside market hours)
python engine.py --force
# Live paper trading (scans every 15 min during market hours)
python engine.py --live
# Dry run — full pipeline with real API calls, but no trades committed
python engine.py --force --dry-run
# Backtest over historical data (rule-based only, no sentiment)
python engine.py --backtest
python engine.py --backtest --backtest-days 365
# Check portfolio status anytime
python status.py
python status.py --fullAll settings live in config.py:
| Setting | Default | Description |
|---|---|---|
STARTING_CASH |
$100 | Paper trading balance |
MAX_POSITIONS |
5 | Max stocks held at once |
MAX_POSITION_PCT |
25% | Max portfolio allocation per stock |
WATCHLIST |
25 stocks | S&P 500 blue chips + tech + growth |
BAR_TIMEFRAME_MINUTES |
15 | Intraday bar size (5, 15, 30, 60) |
STRONG_BUY_THRESHOLD |
0.25 | Min score to trigger Claude check |
CLAUDE_MONTHLY_BUDGET |
$8.00 | Hard cap on API spending per month |
CLAUDE_MODEL |
claude-haiku-4-5 | Model used for sentiment |
BENCHMARK_TICKER |
SPY | Buy-and-hold comparison index |
Each indicator contributes to a combined score. Weights sum to 1.0:
| Weight | Value | Indicator |
|---|---|---|
WEIGHT_RSI |
0.25 | Relative Strength Index |
WEIGHT_MA_CROSSOVER |
0.25 | SMA short/long crossover |
WEIGHT_MACD |
0.25 | MACD histogram |
WEIGHT_BOLLINGER |
0.15 | Bollinger Band position |
WEIGHT_VOLUME |
0.10 | Volume vs 20-day average |
DayTrader/
├── engine.py # Main entry point — orchestrates the full scan loop
├── config.py # All tunable parameters in one place
├── strategy.py # Technical indicators + weighted scoring
├── claude_strategy.py # Claude sentiment filter (BULLISH/BEARISH/NEUTRAL)
├── news.py # Alpaca news headline fetcher
├── data_source.py # Alpaca market data client (bars + quotes)
├── portfolio.py # Portfolio tracking, fractional shares, trade logging
├── budget.py # Monthly API spend tracker with hard cap
├── benchmark.py # SPY buy-and-hold comparison (alpha tracking)
├── decision_log.py # Per-signal audit log (why each trade was taken/skipped)
├── status.py # Quick portfolio summary CLI
└── requirements.txt # Python dependencies
- Two-layer filter: Technicals alone generate too many false signals. Claude reads actual news headlines and only confirms trades with clear material catalysts. No trade executes without both layers agreeing.
- Categorical sentiment, not confidence scores: Claude returns BULLISH/BEARISH/NEUTRAL — no fake confidence percentages. A 3-way vote is harder for the model to fudge and easier to audit.
- Budget-capped AI: Hard monthly spending limit on Claude API calls. When the budget is hit, all sentiment checks return NEUTRAL (safe default — no trades execute).
- Fail-safe defaults: API errors, missing news, budget caps — all result in NEUTRAL sentiment, which blocks trades. The bot never acts on incomplete information.
- SPY benchmark: Every scan logs portfolio return vs SPY buy-and-hold. If alpha is consistently negative, the strategy isn't working.
- This is a learning/research tool, not financial advice.
- Alpaca free tier uses IEX data (slight delay, subset of full market) — fine for paper trading.
- Backtest mode uses yfinance and is rule-based only (no sentiment) since historical news archives aren't available.
- The decision log (
logs/decision_log_YYYY-MM.csv) records every strong signal evaluation for post-hoc analysis.