Reddit Options Trader (ROT)
IMPORTANT DISCLAIMER -- READ BEFORE PROCEEDING
ROT is a research and educational tool only. It is a signal intelligence platform, not a trading execution engine. Nothing in this repository constitutes financial advice, investment advice, or a recommendation to buy or sell any security or derivative. Options trading carries significant financial risk -- you can lose 100% of the premium paid. Signal scores and trade ideas are experimental and have not been independently validated. Never risk capital you cannot afford to lose. The authors accept no liability for financial losses arising from use of this software.
Round 7 Features
Options Paper Trader (src/rot/paper/options_paper.py)
Simulates options trades with full position tracking, BSM mark-to-market, and portfolio metrics — no real capital required.
| Class / Type | Role |
|---|---|
OptionPosition | Open position: contract_id, ticker, strategy, strikes, expiry, quantity, entry_premium, current_value, delta, pnl |
ClosedTrade | Closed trade record with realised_pnl and is_winner |
PortfolioSummary | Snapshot: total_pnl, open_positions, closed_trades, win_rate, max_drawdown, cash |
OptionsPaperTrader | open_trade(), close_trade(), mark_to_market(), get_summary() |
Signal Strength Ranker (src/rot/ranking.py)
Ranks tickers by composite signal strength across five dimensions with tiered labels and ASCII leaderboard output.
| Class / Type | Role |
|---|---|
RankingDimension | SENTIMENT, IV_RANK, VOLUME_SURGE, MOMENTUM, OPTIONS_FLOW |
TierRanking | ticker, score, tier (S/A/B/C/D), breakdown |
SignalRanker | rank(tickers, dimension_scores), leaderboard(top_n=10), configurable weights |
Round 6 Features
Options Chain Analyzer (src/rot/analytics/chain_analyzer.py)
Fetches and analyses the full options chain for any ticker via yfinance.
| Class / Type | Role |
|---|---|
OptionQuote | Single contract: strike, bid, ask, mid, iv, delta, gamma, theta, open_interest, volume |
ChainSnapshot | Full chain for one expiry: ticker, spot_price, expiry, calls, puts, timestamp |
ChainAnalyzer | fetch_chain(ticker, expiry_target_days=30), max_pain(snapshot), put_call_ratio(snapshot), skew(snapshot) |
API route: GET /api/v1/options/chain/{ticker}?expiry_days=30 — returns max-pain, PCR, IV skew, and the full call/put quote list.
from rot.analytics.chain_analyzer import ChainAnalyzer
analyzer = ChainAnalyzer()
snapshot = analyzer.fetch_chain("AAPL", expiry_target_days=30)
print(analyzer.max_pain(snapshot)) # e.g. 190.0
print(analyzer.put_call_ratio(snapshot)) # e.g. 1.2
print(analyzer.skew(snapshot)) # e.g. 0.05 (5 pp)Watchlist Manager (src/rot/watchlist.py)
SQLite-backed persistent watchlist with async CRUD and price-alert detection.
| Class / Type | Role |
|---|---|
WatchlistItem | Item: ticker, added_date, tags, notes, alert_price |
Watchlist | add(item), remove(ticker), list(), get(ticker), tag_filter(tag), check_alerts(prices) |
API routes:
GET /watchlist— HTML dashboard pageGET /api/v1/watchlist— JSON list of all itemsPOST /api/v1/watchlist— add an itemDELETE /api/v1/watchlist/{ticker}— remove an item
from rot.watchlist import Watchlist, WatchlistItem
wl = Watchlist("watchlist.db")
await wl.init()
await wl.add(WatchlistItem(ticker="AAPL", tags=["tech"], alert_price=180.0))
alerts = await wl.check_alerts({"AAPL": 175.0}) # returns AAPL itemRound 5 Features
Reddit Signal Backtester (src/rot/backtest/options_backtest.py — Round 5 additions)
Replays historical Reddit-generated signals against price data and evaluates ATM options profitability.
| Class / Type | Role |
|---|---|
HistoricalSignal | One Reddit signal: ticker, signal_type, date, predicted_direction, confidence |
BacktestTrade | Simulated trade: entry_price, exit_price, strategy_pnl, holding_days, outcome |
BacktestResult | Aggregate stats: win_rate, avg_pnl, total_pnl, sharpe, max_drawdown, best_trade, worst_trade |
BacktestEngine | run(signals, price_data) — simulates ATM call/put entry, walks forward, exits on stop-loss (20%), take-profit (50%), or expiry (30 days) |
from rot.backtest.options_backtest import BacktestEngine, HistoricalSignal
import datetime
signals = [
HistoricalSignal(ticker="AAPL", signal_type="bull_call",
date=datetime.date(2024, 1, 2),
predicted_direction="bullish", confidence=0.75),
]
price_data = {"AAPL": {datetime.date(2024, 1, 2): 185.0, ...}}
result = BacktestEngine().run(signals, price_data)
print(result.win_rate, result.sharpe)Sentiment Aggregator (src/rot/sentiment/aggregator.py)
Combines Reddit, news, options flow, and technical indicator sentiment into a single composite signal with confidence weighting and recency decay.
| Class / Type | Role |
|---|---|
SentimentSource | Enum: REDDIT, NEWS, OPTIONS_FLOW, TECHNICAL_INDICATOR |
SentimentScore | One source score: source, ticker, score [-1,1], confidence, timestamp |
AggregatedSentiment | Output: composite_score, source_breakdown, signal_strength, n_sources |
SentimentAggregator | aggregate(scores) — weighted average with per-source weights and exponential recency decay |
Signal strength thresholds: STRONG_BULL (>0.6), BULL (>0.2), NEUTRAL, BEAR (<-0.2), STRONG_BEAR (<-0.6).
from rot.sentiment.aggregator import SentimentAggregator, SentimentScore, SentimentSource
import datetime
scores = [
SentimentScore(SentimentSource.REDDIT, "AAPL", 0.65, 0.8, datetime.datetime.utcnow()),
SentimentScore(SentimentSource.OPTIONS_FLOW, "AAPL", 0.80, 0.9, datetime.datetime.utcnow()),
]
result = SentimentAggregator().aggregate(scores)
print(result.composite_score, result.signal_strength) # e.g. 0.74 STRONG_BULLRound 4 Features
Options Position Tracker (src/rot/portfolio/positions.py)
Provides an in-memory ledger for multi-leg options positions with mark-to-market updates, portfolio Greeks aggregation, and expiry-risk detection.
| Class / Type | Role |
|---|---|
OptionLeg | One contract leg: contract, side (Long/Short), strike, expiry, premium, quantity, Greeks |
OptionsPosition | Full position: symbol, strategy, legs, entry_cost, current_value, theta_decay |
PositionTracker | Ledger: add_position, close_position, mark_to_market, positions_at_risk, portfolio_greeks |
PortfolioGreeks | Aggregated total_delta, total_gamma, total_theta, total_vega |
render_positions_page | Renders GET /portfolio/positions as a dark-themed HTML page with position cards |
Delta-adjusted PnL: realized_pnl + unrealized_pnl + theta_decay_collected.
Discord Webhook Notifier (src/rot/notifications/discord.py)
Extends the existing DiscordNotifier with alert levels, three new send methods, and a token-bucket rate limiter (max 5 msg/5 s).
| Feature | Detail |
|---|---|
AlertLevel | INFO (blue), WARNING (yellow), CRITICAL (red) — colour-coded embeds |
send_signal_alert(signal, ticker, confidence) | Rich embed with signal name, ticker, confidence, and severity |
send_position_alert(position, alert_type) | Expiry warnings, loss alerts with position Greeks and PnL |
send_daily_summary(portfolio_greeks, daily_pnl) | End-of-day recap with full Greek snapshot |
| Rate limiting | Token bucket: 5 messages per 5 seconds; excess messages dropped gracefully |
| Graceful no-op | Raises ValueError at construction if no webhook URL is configured |
import asyncio
from rot.notifications.discord import DiscordNotifier, AlertLevel
notifier = DiscordNotifier(webhook_url="https://discord.com/api/webhooks/...")
asyncio.run(notifier.send_signal_alert(
signal="bull_call_spread",
ticker="AAPL",
confidence=0.82,
level=AlertLevel.INFO,
))What is ROT?
ROT is a full-stack financial intelligence platform that watches Reddit discussions and institutional RSS feeds in real time, passes every post through a 9-stage ML/NLP pipeline, scores its credibility with a gradient-boosting model, optionally augments reasoning with an LLM, and surfaces the result as a structured options trade idea -- complete with strike selection, expiry heuristics, max-loss calculation, and a full provenance audit trail. The web dashboard streams signals live via WebSocket, while the broker integration layer lets you route approved ideas directly to an Alpaca paper-trading account with one configuration change. ROT tells you what the crowd is reacting to before price fully reacts; what you do with that information is entirely your responsibility.
Live deployment: rot.up.railway.app
5-Minute Quickstart
Option A -- Docker (recommended)
git clone https://github.com/Mattbusel/Reddit-Options-Trader-ROT-.git
cd Reddit-Options-Trader-ROT-
# 1. Copy the environment template
cp .env.example .env
# 2. Open .env and set at minimum:
# ROT_REDDIT_CLIENT_ID, ROT_REDDIT_CLIENT_SECRET
# (everything else has sensible defaults -- LLM key is optional)
# 3. Build and start
docker compose up --build
# Dashboard: http://localhost:8000/dashboard
# API docs: http://localhost:8000/docs
# Health: http://localhost:8000/api/healthYou will see signals appearing on the dashboard within seconds once the Reddit poller starts. No LLM key is required; the system runs in stub-reasoning mode and still generates trade ideas.
Option B -- Manual (virtualenv)
git clone https://github.com/Mattbusel/Reddit-Options-Trader-ROT-.git
cd Reddit-Options-Trader-ROT-
python -m venv .venv
source .venv/bin/activate # Windows: .venv\Scripts\activate
pip install -e ".[dev]"
cp .env.example .env
# Edit .env -- see Configuration Guide below
# Start the full web server
python -m rot.app.server
# Or run a standalone pipeline loop (no web server)
python -m rot.app.loop
# Or run a single pipeline pass and print results
python -m rot.app.mainRound 3 Features
IV Rank Calculator (src/rot/analytics/iv_rank.py)
IVRankCalculator fetches the live options chain via yfinance and inverts ATM option prices to implied volatility using Newton-Raphson Black-Scholes-Merton inversion. It then computes IV rank and IV percentile from a rolling 252-day IV history derived from realized volatility.
| Class / Type | Role |
|---|---|
IVRankCalculator | Orchestrates fetch, inversion, and rank computation |
IVData | Output: symbol, current_iv, iv_52w_high/low, iv_rank, iv_percentile, iv_mean_30d, classification |
IVRegime | IV_CRUSH_ZONE (rank>80), NORMAL (20-80), `IV_EXPANSION_Z |
…