sturlese
numerai_signals_pipeline
Python

Downloads data from Yahoo Finance, generates features, trains a model and submits the predictions to the tournament.

Last updated Apr 18, 2026
26
Stars
4
Forks
0
Issues
0
Stars/day
Attention Score
16
Language breakdown
Python 100.0%
โ–ธ Files click to expand
README

Numerai Signals Pipeline

Build your own technical-analysis features from Yahoo Finance data and submit them to the
Numerai Signals tournament.

Python Tests Coverage Lint License

The pipeline downloads price/volume data from Yahoo Finance, builds a large set of custom technical-analysis features (indicators โ†’ lags โ†’ per-era normalisation), joins them to Numerai's official targets, trains an XGBoost model and produces a valid tournament submission.

What is Numerai Signals?

Numerai runs a hedge fund driven by a crowd-sourced meta-model. In Signals you map stock-market data to a per-ticker signal โ€” a number strictly between 0 and 1 โ€” over the global equity universe. Numerai neutralises your signal against its own risk factors, scores the residual alpha, and pays or burns your stake based on live performance. A submission is just: for each ticker in the current round's universe, a signal in (0, 1).

Quickstart

Requires Python โ‰ฅ 3.10.

# install (uv recommended; plain venv + pip works too)
uv venv --python 3.13
uv pip install -e '.[dev]'

run the full pipeline: download โ†’ features โ†’ train โ†’ submit

nsp run --properties props.json

or build the files without uploading (and train on CPU)

nsp run --properties props.json --no-submit --device cpu

props.json holds your Numerai credentials โ€” keep it out of git:

{ "publicid": "...", "secretkey": "...", "model_id": "..." }

Useful flags: --root (data dir, default data), --jobs (parallel processes for indicator computation), --device (cuda by default, cpu to train without a GPU), --skip-download, --static-data, --no-submit, --keep-intermediate. See nsp run --help.

Architecture

Pure, IO-free logic (unit-tested) is separated from thin IO/network/multiprocessing glue.

raw OHLCV โ”€โ”€โ–ถ indicators โ”€โ”€โ–ถ denoise โ”€โ”€โ–ถ lags โ”€โ”€โ–ถ per-era normalise + encode โ”€โ”€โ”
 (Yahoo)      (registry)    (winsorise)  (shift)   (bin / zscore / rank)        โ”‚
                                                                                โ–ผ
    Numerai API โ”€โ”€ targets + universe โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ”€โ–ถ assemble ML dataset โ”€โ”€โ–ถ XGBoost โ”€โ”€โ–ถ submission
    (downloaddataset / tickeruniverse)                                              numerai_ticker + signal โˆˆ (0,1)

The centrepiece is the declarative feature/lag engine:

  • Indicators are pure functions in a registry (nsp.domain.indicators), keyed by name โ€” no
boilerplate classes.
  • An immutable IndicatorSpec (nsp.domain.specs) is the single source of truth for what
to build. build_specs() is the only place lags are resolved: windowed indicators get lags that are fractions of their window (int(window * fraction), de-duplicated); fixed indicators get absolute integer lags.
  • Lagging is one vectorised groupby(ticker).shift(lag) (nsp.domain.features.apply_lags),
not a per-ticker Python loop.

Project layout

src/nsp/
  config.py            immutable dataclass config (Data/Indicator/Model/Submission)
  paths.py  io.py       filesystem layout + parquet/csv helpers
  naming.py            canonical feature-column naming (single source of truth)
  domain/
    indicators/        registry of pure indicator functions (price / volume / custom ADX,ATR)
    specs.py           IndicatorSpec + build_specs (lag resolution)
    features.py        compute indicators, applylags, normaliseperera, encodelabels
    denoise.py         outlier-row drop + winsorising
    tickers.py         bloombergโ†”numerai_ticker + Yahoo ticker map
    target.py          optional custom forward-return target
  data/
    yahoo.py           OHLCV downloader (pure parsers + network glue)
    numerai.py         Numerai data-API adapter (targets / universe / upload)
  dataset.py           assemble train/validation/live ML frame
  model/predict.py     feature selection, training, submission builder
  pipeline.py  cli.py   orchestration + command-line entry point
tests/                 unit tests + an offline end-to-end pipeline test

Data sources

  • Prices โ€” Yahoo Finance (nsp.data.yahoo).
  • Targets & universe โ€” Numerai's data API (nsp.data.numerai):
download_dataset('signals/<version>/{train,validation}.parquet') for targets and SignalsAPI.ticker_universe() for the live universe.
  • Bloombergโ†”Yahoo ticker map โ€” a configurable community mirror with a bundled fallback.
Bloomberg tickers are mapped to numerai_ticker via the ISO country-code table from Numerai's example_model.ipynb.

Configuration

Immutable dataclasses in nsp.config:

  • IndicatorConfig โ€” indicators (windowed vs fixed), windows, windowedlagfractions,
fixed_lags, and the per-era transformation (bin / zscore / rank).
  • ModelConfig โ€” XGBoost hyper-parameters, target_name, device (GPU by default),
maxfeaturecorr (highly-correlated TA features are dropped before training).
  • DataConfig โ€” data root, dataset version, minerasize, ticker-map URL.

Output

Under --root (default data/):

  • dbmlcsv/ml_data.csv โ€” the assembled train/validation/live dataset (features + target).
  • dbpredictions/submission.csv โ€” the upload file: numeraiticker, friday_date, signal,
with signal rank-normalised strictly into (0, 1).
  • dbrawdownloaded/ โ€” cached Yahoo data (reusable with --skip-download).
Intermediate directories are wiped after a run unless --keep-intermediate is passed.

Testing

pytest                 # 93 tests, ~99% coverage (configured in pyproject.toml)
ruff check src tests   # lint

The suite is fully offline โ€” synthetic fixtures, no network, no GPU โ€” with unit tests for every transformation plus an end-to-end pipeline run that produces a valid submission.

Running live (notes)

A real run needs your Numerai credentials, downloads the multi-GB v2.x parquet datasets and (by default) trains on a GPU. The offline tests exercise every transformation, but the live data path is not run here. Confirm one thing against a real download: the exact target column in signals/<version>/*.parquet (set via ModelConfig.target_name, default target); nsp.data.numerai raises a clear DataError listing the available columns if it does not match.

Roadmap

  • Era-wise purged cross-validation for hyper-parameter tuning.
  • Feature selection via Mean Decrease Accuracy.
  • Signal neutralisation against Numerai's risk factors before submitting.
  • Confirm the v2.x parquet schema (target / id column names) against a live download.

License

MIT (see pyproject.toml).

๐Ÿ”— More in this category

ยฉ 2026 GitRepoTrend ยท sturlese/numerai_signals_pipeline ยท Updated daily from GitHub