A distributed platform for evaluating contestant-submitted trading engines under real market conditions. Built for the IICPC Summer Hackathon 2026.
Contestants submit a trading engine (C++, Rust, or Go) as a .tar.gz archive. The platform:
- Builds a Docker image from the source in an isolated sandbox
- Deploys the engine as a container on a private network
- Fires a fleet of synthetic trading bots at it (LIMIT, MARKET, CANCEL orders)
- Measures P50/P90/P99 latency, peak TPS, and order correctness
- Streams live rankings to a real-time leaderboard
┌─────────────┐ gRPC ┌───────────────────┐ Kafka ┌─────────────┐
│ Gateway │ ────────▶ │ Submission Engine │ ────────▶ │ Bot Fleet │
│ (port 9090)│ │ (build + sandbox) │ │ (bots x N) │
└─────────────┘ └───────────────────┘ └──────┬──────┘
│ │ Kafka
│ SSE ▼
│ ┌─────────────────┐ ┌───────────────────────┐
└─────────▶ │ Leaderboard API │ ◀──Kafka── │ Telemetry Ingester │
│ (port 8080) │ │ (score + percentiles) │
└─────────────────┘ └───────────────────────┘
│
┌───────────┴───────────┐
│ TimescaleDB │
│ (telemetry records) │
└───────────────────────┘
Services: Gateway · Submission Engine · Bot Fleet · Telemetry Ingester · Leaderboard API
Infrastructure: Redpanda (Kafka) · TimescaleDB · Redis · Docker Registry
Full architecture details in the Design Document.
- Docker Desktop (or Docker Engine + Compose v2)
- Go 1.22+ (for proto regeneration only)
git clone https://github.com/kryoton98/IICPC-Hackathon.git
cd IICPC-Hackathon/iicpc-platform
docker compose -f docker-compose.dev.yml up --buildOpen http://localhost:9090 in your browser.
All 9 containers start automatically with health checks and dependency ordering:
| Container | Port | Role |
|---|---|---|
iicpc-gateway |
9090 | Web UI + API entrypoint |
iicpc-leaderboard-api |
8080 | Score aggregation + SSE |
iicpc-submission-engine |
50051 | gRPC build + sandbox |
iicpc-bot-fleet |
— | Load generator |
iicpc-telemetry-ingester |
— | Scoring pipeline |
iicpc-redpanda |
9092 | Kafka broker |
iicpc-timescaledb |
5432 | Time-series DB |
iicpc-redis |
6379 | State cache |
iicpc-registry |
5000 | Image registry |
docker compose -f docker-compose.dev.yml build --no-cache <service-name>
docker compose -f docker-compose.dev.yml up -d <service-name># Requires protoc, protoc-gen-go, protoc-gen-go-grpc
make protoYour engine must listen on port 8080 and implement:
Request body (JSON):
| Field | Type | Description |
|---|---|---|
order_id |
string | UUID v4 — echo this back in the response |
order_type |
int | 1=LIMIT, 2=MARKET, 3=CANCEL |
side |
int | 1=BUY, 2=SELL |
price_bp |
int64 | Price in basis points (ignored for MARKET) |
quantity |
int64 | Units (ignored for CANCEL) |
cancel_target_order_id |
string | UUID of order to cancel (CANCEL only) |
Response body (JSON):
| Field | Type | Description |
|---|---|---|
order_id |
string | Echo request order_id (or cancel_target_order_id for CANCEL) |
status |
string | ACCEPTED, FILLED, CANCELLED, or REJECTED |
filled_quantity |
int64 | Quantity filled (0 for ACCEPTED/CANCELLED) |
filled_price_bp |
int64 | Fill price in basis points (0 for ACCEPTED/CANCELLED) |
Return HTTP 200. Used by the platform to verify the engine is alive before firing bots.
| Order type | Expected status | Additional check |
|---|---|---|
| LIMIT | ACCEPTED or FILLED |
If FILLED: BUY fill price ≤ limit price; SELL fill price ≥ limit price |
| MARKET | FILLED |
filled_quantity > 0 |
| CANCEL | CANCELLED |
order_id in response = cancel_target_order_id in request |
| Language | Path |
|---|---|
| Go | samples/demo-go/ |
| C++ | samples/demo-cpp/ |
Package your engine as a .tar.gz archive containing your source files, then submit via the web UI.
Go engines must include a vendor/ directory or work with -mod=mod.
C++ engines may use a flat main.cpp or a CMakeLists.txt (auto-detected).
Rust engines must include a Cargo.toml.
Scores are recomputed every 10 seconds from all accumulated telemetry:
composite = 0.4 × latencyScore + 0.4 × tpsScore + 0.2 × correctnessRate
latencyScore = 1 / (1 + p99_ns / 1e7) # 1ms p99 ≈ 0.99, 50ms p99 ≈ 0.17
tpsScore = min(peak_tps / 250, 1.0) # 250 TPS = full score
correctness = correct_fills / total_fills
Latency is measured as the HTTP round-trip time at the bot, excluding Kafka pipeline delay.
TPS is the peak 1-second bucket count, not the average over the window.
iicpc-platform/
├── services/
│ ├── gateway/ # HTTP entrypoint, static frontend
│ ├── submission-engine/ # Build pipeline, Docker sandbox
│ ├── bot-fleet/ # Synthetic order generation
│ ├── telemetry-ingester/ # Latency measurement, scoring
│ └── leaderboard-api/ # SSE streaming, score reads
├── shared/
│ ├── proto/ # platform.proto (source of truth)
│ ├── gen/platform/ # Generated pb.go stubs
│ └── contracts/ # Hand-written Go types
├── samples/
│ ├── demo-go/ # Reference Go engine
│ └── demo-cpp/ # Reference C++ engine
├── docker-compose.dev.yml
└── Makefile
Full architecture deep-dive: docs/architecture.pdf
| Category | Technology |
|---|---|
| Services | Go 1.25 |
| RPC | gRPC + Protocol Buffers |
| Messaging | Redpanda v23.3 (Kafka-compatible) |
| Time-series DB | TimescaleDB (PostgreSQL 16) |
| State cache | Redis 7 |
| Container runtime | Docker (moby/moby SDK) |
| Frontend | Vanilla HTML/CSS/JS, Server-Sent Events |
| Dev IaC | Docker Compose |
| Prod IaC | Kubernetes + Kustomize + Terraform |
IICPC Summer Hackathon 2026
