ContextQuant is a deep learning system that produces a 5-class stock guidance signal — [Strong Sell, Sell, Hold, Buy, Strong Buy] — by fusing two distinct information streams:
- Temporal branch: a stacked LSTM over a 60-day window of OHLCV data + technical indicators (RSI, MACD, Bollinger Bands)
- Linguistic branch: a FinBERT sentiment vector derived from financial news headlines
Both branches are merged by a fully-connected fusion head trained end-to-end.
- Python 3.11 installed (python.org)
- uv installed (
pip install uvor the standalone installer) - Internet access for the initial data download and (optionally) FinBERT model weights
uv syncThis reads
pyproject.tomlanduv.lock, creates a.venv, and installs every dependency at the exact pinned versions — including PyTorch CPU wheels from the official PyTorch index.To also install the Jupyter and dev extras:
uv sync --extra jupyter --extra dev
uv run python verify_setup.pyEvery line should show a checkmark. If anything fails, run uv sync again or check the error message.
uv run python -m src.train --ticker AAPL --epochs 60This downloads AAPL price data, computes technical indicators, trains the fusion model, and saves the best checkpoint to models/AAPL_best.pt. Training takes a few minutes on CPU.
You can swap the ticker for any symbol supported by Yahoo Finance (e.g. MSFT, NVDA, TSLA).
uv run streamlit run app.pyOpen the URL printed in the terminal (usually http://localhost:8501).
- Pick a ticker and date range in the sidebar
- Select the checkpoint you just trained from the Checkpoint dropdown
- Optionally paste a news headline to incorporate live sentiment
- Click Analyse — the model outputs a guidance signal with a full probability breakdown
uv run python -m src.train --ticker AAPL # defaults: 60 epochs, lr=1e-3, batch=64, patience=10
uv run python -m src.train --ticker MSFT --epochs 100 --lr 5e-4 --batch-size 128The best checkpoint is saved to models/<ticker>_best.pt and automatically picked up by the dashboard.
from src.data_loader import build_dataset
from src.model import build_model
from src.train import train, evaluate_test
data = build_dataset("AAPL") # download, indicators, windowing, splits
model = build_model()
history = train(model, data, n_epochs=60) # trains + saves best checkpoint
results = evaluate_test(model, data)
print(results["report"]) # per-class precision / recall / F1Branch A (Temporal) [B, 60, 11] ──► 2-layer LSTM ──────────────────────┐
├──► Fusion FC ──► [B, 5]
Branch B (Linguistic) [B, 3] ──► 2-layer MLP (FinBERT probs) ────────┘
The sentiment input is a [positive, negative, neutral] probability vector from ProsusAI/finbert. When no headline is provided the model falls back to a uniform neutral prior.
├── app.py # Streamlit dashboard
├── src/
│ ├── data_loader.py # OHLCV download, indicators, windowing, splits
│ ├── model.py # ContextQuantFusionNet (LSTM + MLP + fusion head)
│ ├── train.py # Training loop, early stopping, checkpointing
│ └── utils.py # Indicator helpers, seed, device, metrics
├── data/ # Raw / processed data (git-ignored)
├── models/ # .pt checkpoints (git-ignored)
├── notebooks/ # Progressive learning curriculum (see below)
├── pyproject.toml # dependencies + uv index config
├── uv.lock # exact pinned versions (commit this)
├── .python-version # Python 3.11 pin for uv
└── verify_setup.py
A self-contained learning curriculum lives in notebooks/ — six progressive modules covering PyTorch fundamentals through the full ContextQuant system. Each module is standalone and requires no imports from src/.
uv sync --extra jupyter
uv run jupyter lab # then open notebooks/ and start at 00_pytorch_fundamentals/