A Qt 6 desktop app with a dark, Finviz-style table: Reddit r/wallstreetbets sentiment, SEC EDGAR fundamentals, World Bank US CPI, a Stooq portfolio snapshot, plus Finnhub (quote, metrics, analyst trends) and Twelve Data (RSI, MACD, EMA) per ticker. Data is merged into a single QTableView model.
- C++17
- Qt 6 (
Core,Widgets,Network) - CMake
| Path | Role |
|---|---|
src/main.cpp |
Application entry |
src/ui/mainwindow.* |
Main window, toolbar, table, log, status bar, stylesheet |
src/ui/sentimentdelegate.* |
Custom delegate for the Sentiment column (value + mini bar) |
src/network/apiclient.* |
All HTTP clients, throttled queue for Finnhub/Twelve, signals |
src/models/screenermodel.* |
QAbstractTableModel (16 columns, colors, sorting roles) |
src/models/stockdata.h |
Row struct (ticker, fundamentals, market / technical fields) |
src/core/utils.h |
Header-only parsers and helpers (Reddit, SEC, CPI, Stooq, Finnhub & Twelve JSON) |
- CMake ≥ 3.16
- Qt 6 development packages: Core, Widgets, Network
- C++17 compiler
- Optional:
clang-format,gdb(see Makefile targets)
cmake -S . -B build
cmake --build build -j
./build/StockScreenermake build
make runOther targets: configure, debug, format, format-check, clean (see Makefile).
- Table: Fixed column widths and
Qt::ElideNoneso labels like EPS, CPI, Beta, and Analyst (Neutral / Bullish / Bearish) are not truncated with…. Widen the window or adjust widths inmainwindow.cppif you add longer headers. - Theme: Dark QSS in
MainWindow::applyStylesheet()(#0d1117,#161b22,#30363d, etc.). - Status bar: Tags for SEC, WSB, Portfolio, Econdb (World Bank CPI), Finnhub, Twelve Data (
✓/✗/—).
- Fetch / Refresh runs Reddit, World Bank CPI, Stooq (query ticker or default), optional SEC for the typed ticker, and queues Finnhub + Twelve jobs for every row currently in the table (if the table is empty until Reddit returns, fetch again after rows appear).
- Finnhub and Twelve Data share a single FIFO queue in
ApiClient: at most one Finnhub request every 200 ms and one Twelve request every 8 seconds (free-tier friendly). Other APIs are unchanged and not throttled on that queue.
| Source | Usage |
|---|---|
| Reddit WSB hot JSON | Sentiment scores for a fixed watchlist |
| SEC EDGAR company facts | EPS, revenue (per CIK / ticker) |
| World Bank | US CPI inflation indicator |
| Stooq CSV | Portfolio / snapshot line for selected ticker |
| Finnhub | Quote (c, dp), stock/metric, stock/recommendation |
| Twelve Data | rsi, macd, ema (daily, outputsize=1) |
API keys for Finnhub and Twelve are embedded in src/network/apiclient.cpp for this demo. For production, move them to environment variables or a local config file and do not commit secrets.
SEC: Requests must use a descriptive User-Agent (see apiclient.cpp).
Shared JSON helpers used by ApiClient include:
jsonGetDouble— numeric field from aQJsonObject(uses existingtoDoubleSafe)finnhubQuotePriceAndChangePct,finnhubExtractMetrics,finnhubAnalystScoreFromRecommendationJsontwelveDataFirstValuesRow,twelveDataApiErrorMessage,twelveDataFirstSeriesDouble,twelveDataMacdMinusSignal
.clang-format (LLVM-based, Allman braces, 4 spaces). Run make format or make format-check.
- Third-party APIs may change schemas or rate limits without notice.
- Finnhub/Twelve queues are sequential; many tickers imply a long total refresh time.
- Tracked Reddit tickers and CIK map are curated in code (
utils.h/apiclientpatterns), not a full market database.
