Skip to main content
When you scaffold a workspace with crunch-node init, you get a fully working Crunch Node powered by the crunch-node engine. This page walks through how the default implementation works.

Architecture

The Crunch Node runs as a set of independent Docker workers that communicate through a shared PostgreSQL database. This separation ensures that real-time prediction gathering, scoring, and reporting can scale independently.
Diagram showing the worker pipeline: predict-worker, score-worker, and report-worker

High-level overview of the local environment

Workers

Predict worker

The predict worker coordinates all participant models in real-time:
  1. Reads latest feed data from the database
  2. Ticks all connected models — sends market data via the Model Runner Client so models can update their internal state
  3. Calls predict() on all models for each configured scope (subject, horizon, step)
  4. Stores raw predictions in the predictions table for asynchronous scoring
The worker uses the DynamicSubclassModelConcurrentRunner to fan out requests to all models concurrently. Key configuration:
For details on model connection and request handling, see the Model Runner documentation.

Score worker

The score worker transforms raw predictions into scores and leaderboard rankings. It runs independently from the predict worker, so CPU-intensive scoring never blocks real-time prediction collection. Pipeline:
  1. Resolve ground truth — fetch realized values from feed records
  2. Score predictions — evaluate each prediction against ground truth using the configured scoring function
  3. Aggregate snapshots — combine per-prediction scores into model-level metrics over time windows
  4. Rebuild leaderboard — rank all models based on overall performance
  5. Prune old data — remove expired predictions and snapshots

Scoring function

The scoring function is a Python callable that you define in your challenge package. The default scaffold provides a placeholder in challenge/starter_challenge/scoring.py:
You configure the path to your scoring function via the SCORING_FUNCTION environment variable.

Multi-metric scoring

Every score cycle also computes portfolio-level metrics alongside the per-prediction scoring function. Active metrics are defined in your CrunchConfig:
Built-in metrics include Information Coefficient (IC), IC Sharpe, hit rate, max drawdown, Sortino ratio, turnover, and more. You can also register custom metrics.
Individual prediction scoring:For each submitted prediction, the score worker:
  1. Validates the prediction returned the expected output shape
  2. Retrieves the realized ground truth from feed records
  3. Evaluates the prediction using the configured scoring function
  4. Stores the result in the scores table
Model-level aggregation:After individual predictions are scored, the worker computes model-level performance:
  • Recent score — performance over the most recent time window (detects current form)
  • Steady score — medium-term performance (balances recency and stability)
  • Anchor scores — per-parameter breakdown (by subject, horizon, step combinations)
  • Overall score — weighted combination used for final ranking
Snapshots enable time-series reporting, allowing participants to track performance trends.

Report worker

The report worker provides the HTTP API for accessing competition data. Key endpoints:

API security

Endpoints are protected by API key authentication when API_KEY is set in your environment. Public endpoints (leaderboard, schema, docs) are always accessible.

Custom endpoints

Add endpoints by dropping Python files in node/api/:
Any .py file in api/ with a router attribute is auto-mounted at startup.

Configuration

All configuration is via environment variables in node/.local.env. The most important settings:

CrunchConfig

All type shapes and competition behavior are defined in a CrunchConfig object. The engine auto-discovers your config from node/config/crunch_config.py:
See the crunch-node documentation for the full configuration reference.

Extension points

Customize competition behavior by setting callable paths in your environment:

Next: Challenge package example

Learn how to structure the participant-facing package that ML engineers use to join your competition.