A minimal, Kubernetes and Docker friendly mono-repo consisting of two services:
- poller: periodically fetches market data (via yfinance), computes diffs, publishes to Redis pub/sub, and maintains a full snapshot in Redis.
- api: exposes REST endpoints and WebSockets, serving the Redis snapshot and real-time diffs to clients (with optional per-connection watchlists).
Project structure using packages follows uv workspace guidance.
const socket = new WebSocket("ws://localhost:8000/ws/prices");
socket.addEventListener("open", () => {
setInterval(() => socket.send("ping"), 30000);
socket.send(JSON.stringify({ watchlist: ["AAPL", "MSFT"] }));
});
socket.addEventListener("message", evt => {
try { console.log("Update:", JSON.parse(evt.data)); }
catch { console.warn("Non-JSON:", evt.data); }
});
socket.addEventListener("close", () => console.log("Closed"));
socket.addEventListener("error", e => console.error("WS error", e));- Python 3.13+ installed
- Docker & Docker Compose
- make (for convenience)
-
poller service
-
settings.pyreadsTICKERS,POLL_FREQ,REDIS_URLfrom environment /.env. -
main.pylaunches one asyncio task per symbol:while True: info = await to_thread(yf.Ticker(sym).info) await update_prices({ sym: data }) await redis.publish("price-diffs", json.dumps(payload)) await sleep(POLL_FREQ)
-
Maintains an in-memory snapshot map for fast merges, atomically
SET pricesin Redis. -
Stores the latest full snapshot in a Redis hash (key prices).
-
Publishes incremental diffs on a Redis pub/sub channel (prices).
-
-
api service (REST)
GET /tickers- full snapshot from Redis (GET prices)GET /tickers/{symbol}- one symbol or 404GET /tickers/{symbol}- one symbol or 404GET /tickers/{symbol}/history?start={start_date}&end={end_date}- one symbol or 404 - start and end date in format YYYY-MM-DD (2025-06-01)
-
api service (WebSockets)
/ws/prices— on connect, send full snapshot then stream diff messages/ws/news— same pattern for news items- Clients may send
{ "watchlist": ["SYM",…] }to receive only those symbols.
{ "watchlist": ["AAPL", "MSFT", ...] }
Simply clone the repo and run make start:
make start- API available at
http://localhost:8000 - WebSocket endpoints at
ws://localhost:8000/ws/pricesand/ws/news
Run unit tests:
make testThere is also an Azure CI pipeline that will run lint checks and execute tests.
The project uses Ruff for linting, formatting and sorting imports for code consistency. Simply run:
make format