Projects / StockPredictor

Forecasting / Live ML

StockPredictor

Measure the move.
Rank the week.
Log every forecast.

00 / The idea

Forecast what the evidence
says is forecastable.

StockPredictor began as a next-day direction forecaster and became a study in measuring what can actually be predicted. None of its daily direction models, among twenty-four it trained, beat the base rate. The size of the next move and the relative ranking of stocks over a week did, so those are the forecasts it publishes every session.

Forecasts
Next-session move size with an 80% band, and a five-session ranking.
Universe
Fifty large caps for move size; one hundred large and mid caps for the ranking.
Evidence
Purged six-year walk-forward tests and an immutable prospective scorecard.
Delivery
A daily GitHub Actions pipeline, a FastAPI service, and a live React dashboard.

01 / In the dashboard

Five views.
One forecast record.

Follow the live dashboard from the next session's outlook through the weekly ranking to the evidence behind both models.

01Overview

Tomorrow's market, read honestly.

The landing view leads with the average expected move for the next session, then states plainly which models passed their gates and which forecast is only a base rate. Coverage, the immutable forecast count, matured outcomes, and data freshness sit beside the biggest expected movers and this week's ranking.

  • Average expected move across the large caps
  • Gate status for every live model
  • Biggest movers and this week's leaders

02Move-size forecasts

How far each stock may move, with a calibrated range.

Every large cap gets an expected absolute move, an 80% band, and the probability of a big move. The table sorts by expected move or big-move probability and filters by symbol; the up-probability column openly shows the training base rate rather than a direction call.

  • Expected move with its 80% band
  • Sort by size or P(big move)
  • Direction shown as the base rate

03Weekly ranking

Which stocks should beat the others this week.

A separate model ranks one hundred large and mid caps by their expected five-session return relative to the rest of the universe. The view shows the top and bottom quintiles side by side, then the full percentile list with each stock's cohort.

  • Leaders and laggards over five sessions
  • Large-cap and mid-cap cohorts
  • Full ranking with percentiles

04Track record & model catalog

Every forecast is scored, and every model is accounted for.

The track record fills only with prospective results: band coverage per forecast day, the weekly ranking portfolio, and each champion/challenger retraining decision. The catalog lists all twenty-four models trained in the project, including the seventeen that failed their baselines.

  • Live scorecards from logged forecasts
  • Weekly retraining history
  • Passed, failed, and benchmark models

05Research evidence

The walk-forward evidence behind each claim.

The research tab shows why the live models exist: move size rising cleanly across forecast quintiles, the 80% band holding in every test year, rank IC by year, the long-short backtest, and how returns change as trading costs rise.

  • Move size by forecast quintile
  • Band coverage in each test year
  • Backtest curve and cost sensitivity

02 / System architecture

Compute in the pipeline.
Serve from the edge.

Collection, training, and inference run on GitHub Actions because they need LightGBM, FinBERT, and the full dataset. Vercel only serves the published results through a read-only API and a static dashboard.

Heavy work runs in the pipeline; Vercel only serves resultsStockPredictor / System map
Sources & archiveDaily GitHub Actions pipelineServing
Free data sourcesAlpaca bars + news · SEC XBRL · ALFRED · GDELT
Content-addressed archiveraw responses by SHA-256 · manifests · checkpoints
Prepared datasetsclean bars · features · labels · purged blocks
Refresh & featuresextract · prepare · news · FinBERT scores
Forecast, rank & scoretwo-head bundle · 5-day ranker · scorecards
Weekly retrainingchampion / challenger on 13 unseen weeks
Neon PostgreSQLappend-only forecasts · rankings · model events
FastAPI on Vercelread-only role · CDN-cached responses
React dashboardstatic build · bundled snapshot fallback
Training and inference need LightGBM, FinBERT, and the full dataset, so they run on Actions runners. The private S3 archive is the immutable record; PostgreSQL is the query copy the API reads.
Archive

Keep the raw record.

Every source response is stored by content hash before it is parsed, with credentials redacted and checksums verified on read.

Forecasts

Write once.

Each session's forecasts are one immutable file. A repeated run with different values is refused rather than silently replaced.

Serving

Read only.

The API connects as a role that can only select. The pipeline role can append forecasts but never rewrite them.

03 / The live loop

Forecast before the open.
Score after the close.

Every weekday after the close, the pipeline refreshes its inputs, logs the next session's forecasts, and scores the ones whose outcomes have matured. Once a week of new outcomes exists, a challenger must pass the study's own gate before it replaces production.

One immutable forecast per session, scored when the outcome existsStockPredictor / System map
After the closeBefore the openOutcome maturesEach week
Refresh inputsbars · SEC filings · news · new FinBERT scores
Forecast & logwrite <origin>.json once · archive collision check
Score matured rowsband coverage · rank IC · weekly portfolio
Challenger gatepromote only if it beats the comparator
The champion stays frozen between retrains, so every logged forecast is a clean test of the model that made it. Every evaluation, promoted or not, is appended to the model registry.
The daily run starts at 22:45 UTC on weekdays, more than 30 minutes after the close in both EST and EDT. A logged forecast can never be revised; a repeated run with different values fails.

04 / Research discipline

Twenty-four models.
Two earned their place.

Gradient boosting, linear and ARIMA baselines, LSTMs, a CNN-LSTM, a residual MLP, a foundation model, and fine-tuned FinBERT were all evaluated on purged chronological data against gates declared before testing. The failures are reported with the same care as the passes.

Every model faces a frozen, purged evaluationStockPredictor / System map
Frozen inputsChronologyPre-declared gateOutcome
Checksummed datasetmanifest · recipe hash · code fingerprint
Purged chronologyfixed blocks or yearly folds · tuning before test
Gate vs baseline5 of 6 years and pooled · set before testing
Live or documentedpromoted bundle, or a failure report
Test years never choose features, settings, or thresholds. A model that only wins after looking at its test results is not promoted.
Twenty-four models were trained. Seventeen failed their baseline or gate, three are reference benchmarks, one was superseded, one passed in research, and two serve live forecasts.

05 / Engineering underneath

Reproducible from
raw bytes to forecast.

Recipe hashes cover configuration, input checksums, and source code, so an identical run reuses its results. Models are saved as native LightGBM text and JSON, and every file is checked before it loads.