Skip to content

VictoriousWealth/tradestream

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

426 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

TradeStream — Distributed Trading Platform

Event-driven trading system with Spring/Java microservices, Kafka/Redpanda, PostgreSQL, Redis, and Docker. This root README is the entry for recruiters and engineers: what’s here today, how to run it, and where to look next.

Repo Size CI Status Open Issues Pull Requests License Last Commit


TL;DR

  • Edge security: Spring Cloud API Gateway (Java 21) validates PS256 JWT at the perimeter, injects X-Request-Id, applies Resilience4j circuit breakers, and Redis IP rate limits login.
  • Order → Trade pipeline: Orders ServiceMatching Engine (price–time priority) → Transaction Processor (immutable journal).
  • Read models: Portfolio Service projects positions & realized PnL. Market Data Consumer aggregates OHLCV and keeps “latest” hot in Redis.
  • Everything is containerized; Flyway manages schemas; Actuator provides health/metrics.

This repo is educational/portfolio—it simulates a trading stack; it does not process real money.


Case Study

TradeStream is my strongest Java/Spring Boot backend and fintech systems project. I built it to model how order, trade, transaction and portfolio flows can move through separate services without becoming a single CRUD app.

  • Problem: build a finance-style backend where service boundaries, state ownership and event flow are visible.
  • Build: Spring Cloud Gateway handles edge concerns; auth and user services manage access; orders publish events to Redpanda/Kafka; the matching engine emits trade events; transaction and portfolio services project downstream state into PostgreSQL-backed models.
  • Evidence: the repo includes Docker Compose orchestration, GitHub Actions CI, end-to-end scripts, architecture docs, event contracts, security notes and operational runbooks.
  • Main lesson: event-driven systems need clear ownership of durable state, idempotency, retries, observability and honest boundaries between what is working locally and what would be needed for production.

What’s the current status?

Component Path Status Notes
API Gateway api-gateway/ PS256 JWT verification, Redis rate limit (login), circuit breakers, CORS, tracing header
User Registration services/user-registration-service/ Internal-only /register gated by X-Internal-Caller: api-gateway, BCrypt, Postgres
Authentication Service services/authentication-service/ /login issues PS256-signed access+refresh; /refresh is internal-only
Orders Service services/orders-service/ REST + Kafka producer/consumer, pessimistic locks, idempotent fill tracking
Matching Engine services/matching-engine/ Price–time priority, idempotency ledger, DLQ
Transaction Processor services/transaction-processor/ Journals trade.executed.v1 → emits transaction.recorded.v1, REST queries
Portfolio Service services/portfolio-service/ Projects transactions → positions & realized PnL; pessimistic locking + ledger
Market Data Consumer services/market-data-consumer/ Kafka→Postgres OHLCV; Redis-cached “latest” with precise eviction
Docs: recruiter summary CVREADME.md Hybrid, recruiter-friendly project overview
Docs: codebase review CODEBASE_REVIEW_7POINTS.md Interview-oriented review of architecture, trade-offs, bugs, and redesign ideas
Docs: observability docs/observability-stack-guide.md Metrics/logs/tracing/alerting implementation plan and readiness checklist
Docs: future work docs/future-enhancements.md Prioritized roadmap for analytics, simulation bots, schema contracts, observability, infra
CI (GitHub Actions) .github/workflows/ci.yml Docker Compose E2E checks for core flows
Roadmap delivery 🔜 Next work is documented, but not implemented: observability stack, analytics console, contracts, bot simulation, infra hardening
RabbitMQ option Not used—message bus is Kafka/Redpanda only
JWE (encrypted JWTs) Not used—project uses signed JWT (PS256) only

Legend: ✅ present & working (dev), 🔜 planned, ❌ not applicable.


Architecture at a glance

Clients
  │
  ▼
API Gateway (8080)  — PS256 JWT, Circuit Breakers, Redis Rate Limit (login), X-Request-Id
  │
  ├─ /api/users/register  → user-registration-service (8081) [internal header required]
  ├─ /api/auth/*          → authentication-service (8082)    [/login public, /refresh internal-only]
  ├─ /api/orders/*        → orders-service (8085)
  ├─ /api/transactions/*  → transaction-processor (8084)
  ├─ /api/portfolio/*     → portfolio-service (8087)
  └─ /api/market-data/*   → market-data-consumer (8083)

Kafka/Redpanda (9092)
  ├─ order.placed.v1 → Matching Engine (8086) → trade.executed.v1
  └─ trade.executed.v1 → Transaction Processor → transaction.recorded.v1 → Portfolio Service

Tech stack (actual)

  • Language/Frameworks: Java 17/21, Spring Boot 3, Spring Cloud Gateway, Project Reactor
  • Messaging: Kafka-compatible Redpanda
  • Datastores: PostgreSQL (per service, Flyway migrations), Redis (rate limit + market latest)
  • Resilience/Obs: Resilience4j circuit breakers, Spring Actuator
  • Packaging: Docker & Docker Compose (local dev)
  • Auth: JWT (PS256) at the gateway; private key in Auth service; public key at Gateway
  • CI/CD/Cloud: GitHub Actions (E2E via Docker Compose); deployment/orchestration beyond local Compose is roadmap work, not in-repo

Documentation map

Start here depending on what you need:

  • README.md — current implementation overview and local runbook
  • CVREADME.md — recruiter-facing summary
  • CODEBASE_REVIEW_7POINTS.md — architecture/trade-off/bug/redesign review for interview prep
  • docs/tradestream-prd.md — project requirements and architecture rationale
  • docs/api-design.md — gateway routes and service API behavior
  • docs/future-enhancements.md — concrete roadmap for simulation bots, analytics UI, schema governance, observability, and platform hardening
  • docs/observability-stack-guide.md — implementation guide for metrics, logs, traces, lag dashboards, and alerting
  • docs/known-risks-and-non-goals.md — explicit current limitations, deferred scope, and implementation risks confirmed in code
  • docs/event-contracts.md — topic-by-topic Kafka contract details, idempotency behavior, and contract gaps
  • docs/security-model.md — current auth, trust boundaries, token model, and known security gaps
  • docs/test-strategy.md — what the current scripts and CI actually validate, plus drift and coverage gaps
  • docs/operational-runbook.md — local runtime troubleshooting guide for gateway, Kafka, Redis, and downstream services
  • docs/architecture-decisions.md — concrete architecture choices visible in the repo and their consequences
  • docs/order-placement-matching-trade-execution-diagram.md — order placement to trade execution flow
  • docs/trade-execution-market-data-&-portfolio-updates-+-order-status-diagram.md — downstream projection/update flow

Run it locally

Prereqs

  • Docker & Docker Compose
  • openssl (for JWT keypair)
  • jq (nice to have)
  • (optional) kcat for Kafka testing

1) Generate PS256 keys

mkdir -p secrets
openssl genpkey -algorithm RSA -pkeyopt rsa_keygen_bits:2048 -out secrets/jwt_private.pem
openssl rsa -in secrets/jwt_private.pem -pubout -out secrets/jwt_public.pem

2) Bring everything up

docker compose up -d --build

3) Health check

curl -s http://localhost:8080/actuator/health
# {"status":"UP"}

Quickstart (Gateway-first)

Register → Login

export DEMO_PASSWORD='<set-a-local-dev-password>'

curl -sS -X POST http://localhost:8080/api/users/register \
  -H 'Content-Type: application/json' \
  -d "{\"username\":\"alice\",\"password\":\"$DEMO_PASSWORD\"}"

ACCESS=$(curl -sS -X POST http://localhost:8080/api/auth/login \
  -H 'Content-Type: application/json' \
  -d "{\"username\":\"alice\",\"password\":\"$DEMO_PASSWORD\"}" | jq -r .access_token)
echo "ACCESS=$ACCESS"

Place an order

curl -sS -X POST http://localhost:8080/api/orders \
  -H "Authorization: Bearer $ACCESS" -H 'Content-Type: application/json' \
  -d '{"userId":"<uuid>","ticker":"AAPL","side":"BUY","type":"LIMIT","timeInForce":"GTC","quantity":10,"price":150.5}' | jq .

Portfolio & Market Data

curl -sS -H "Authorization: Bearer $ACCESS" \
  http://localhost:8080/api/portfolio/<uuid>/positions | jq .

curl -sS -H "Authorization: Bearer $ACCESS" \
  "http://localhost:8080/api/market-data/candles/AAPL/latest?interval=1m" | jq .

Handy scripts live at repo root: e2e_trade_pipeline_test.sh, e2e_portfolio_service.sh, gateway_smoke.sh.


CI and operational readiness

GitHub Actions currently validates the stack using Docker Compose end-to-end checks:

  • generates temporary JWT test keys for CI
  • sets up JDK 21
  • builds the API Gateway jar
  • builds and starts the Compose stack
  • waits for core services to become healthy before testing
  • runs portfolio, trade pipeline, cancel flow, and scenario scripts

Primary workflow:

  • .github/workflows/ci.yml

Operationally relevant docs:

  • docs/observability-stack-guide.md
  • gateway_smoke.sh
  • e2e_trade_pipeline_test.sh
  • e2e_portfolio_service.sh
  • e2e_scenarios.sh

Future work (documented, not implemented)

The next tranche of work is already scoped in docs/future-enhancements.md and docs/observability-stack-guide.md. The most concrete items are:

  • Observability implementation: Prometheus/Grafana, Loki, Jaeger/OpenTelemetry, lag dashboards, DLT alerting.
  • Schema governance: Confluent Schema Registry and CI contract tests for order.placed.v1, trade.executed.v1, and transaction.recorded.v1.
  • Analytics console: Streamlit + Plotly ops dashboard for PnL, market data, bot activity, order flow, and risk.
  • Bot market simulation: retail, market-maker, institutional, hedge, HFT, and portfolio bots to stress the event pipeline with richer market behavior.
  • Platform hardening: stronger service-to-service auth, refresh-token rotation/revocation, per-user gateway limits, and eventual cloud/IaC work.

This keeps the README honest about what exists today while making the intended direction explicit for reviewers.


Gateway routes (reality-checked)

Area Route Auth Rewrites to…
Auth POST /api/auth/login No /login → authentication-service (8082)
Auth POST /api/auth/refresh No /refresh (internal-only header enforced)
Users POST /api/users/register No /register → user-registration (8081)
Orders POST /api/orders Yes /orders → orders-service (8085)
Orders GET /api/orders/{id} Yes /orders/{id}
Orders POST /api/orders/{id}/cancel Yes /orders/{id}/cancel
Transactions GET /api/transactions/** Yes (no rewrite) → transaction-processor (8084)
Portfolio GET /api/portfolio/{userId}/positions[...] Yes /portfolio/... → portfolio-service (8087)
Market Data GET /api/market-data/candles/{ticker}[/latest] Yes /candles/... → market-data-consumer (8083)
Ops GET /actuator/health, GET /actuator/info No Gateway itself
Ops GET /actuator/gateway/**, GET /actuator/metrics Yes Gateway itself
  • Login is IP rate-limited via Redis (token-bucket).
  • Only /actuator/health and /actuator/info are public; other actuator routes still require JWT.
  • Circuit breakers return predictable JSON fallbacks.
  • X-Request-Id injected if missing; cookies stripped.

Security model (current)

  • JWT at edge: Gateway is a resource server validating PS256 signatures with the public key.

  • Internal caller gates:

    • authentication-service /refresh requires X-Internal-Caller: api-gateway.
    • user-registration-service /register requires the same header (added by the Gateway).
  • No JWE (encryption) — signed JWTs only.

  • Rate limiting: Redis-backed rate limit on login endpoints.

  • CORS: permissive in dev; tighten in prod (config in Gateway).


Troubleshooting (real problems you’ll see)

Symptom Likely cause Fix
401 at gateway Missing/expired/invalid JWT (PS256) Re-login; verify public key mount
429 on /api/auth/login Rate limit tripped Back off; expected behavior
Gateway degraded JSON (503) Circuit breaker open on downstream Check downstream /actuator/health
Orders don’t execute Matching Engine or Kafka not consuming Inspect topics/consumer logs
Duplicate fills / position drift Ledger/migration missing Ensure Flyway applied; check unique constraints
Stale market “latest” Quiet feed; TTL not expired Next trade will evict → fresh read
/register returns 403 Missing internal-caller header Ensure Gateway injects X-Internal-Caller

Repo layout (trimmed)

.
├── api-gateway/
├── services/
│   ├── authentication-service/
│   ├── user-registration-service/
│   ├── orders-service/
│   ├── matching-engine/
│   ├── transaction-processor/
│   ├── portfolio-service/
│   └── market-data-consumer/
├── docs/
├── docker-compose.yml
├── secrets/                       # jwt_private.pem / jwt_public.pem
├── CVREADME.md                    # recruiter-facing overview
├── CODEBASE_REVIEW_7POINTS.md     # architecture/trade-off/bug review
├── e2e_*.sh / gateway_smoke.sh
└── bench_out/

Per-service READMEs (sources of truth):

  • api-gateway/README.md
  • services/authentication-service/README.md
  • services/user-registration-service/README.md
  • services/orders-service/README.md
  • services/matching-engine/README.md
  • services/transaction-processor/README.md
  • services/market-data-consumer/README.md

License

This project is licensed under CC BY-NC 4.0. See LICENSE.


About

TradeStream: educational, containerized trading stack (Spring Boot, Kafka/Redpanda, Postgres); API Gateway enforces PS256 JWT; end-to-end demos included.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors