Formerly Upbit Alpha Desk. Full-stack intelligence console for KRW market structure, listings, and market data operations.
Upbit Alpha Desk is a full-stack trading-intel console for the KRW market.
It blends Upbit day-candles, cached tickers, saved trading-value files, and Bybit-based listing strategies into one React frontend backed by an Express + Redis API layer.
- Backend: Node.js, Express, TypeScript, Redis (market-data cache), Axios schedulers
- Frontend: React (Vite + TypeScript), React Query, Chart.js, date-fns
- Scheduling: Listing calendar & listing strategy analyzers (3h), ticker cache persistence, saved_data parsing, midnight candle refresh
- Package Manager: pnpm
src/ # Express server + schedulers
โโโ server.ts # API & static serving entry
โโโ config.ts # CORS / API key / rate-limit config
โโโ clients/
โ โโโ redisClient.ts # Lazy Redis connector
โ โโโ bybitClient.ts # Bybit hourly candle fetcher
โโโ services/ # DataManager + schedulers
frontend/ # React/Vite SPA (served as static build)
โโโ src/components/... # Sidebar, analytics, listing lab, insights
โโโ src/api/ # Typed API client + DTOs
public/ # Legacy static assets (still served)
cache/ # JSON snapshots for schedulers & ticker cache
saved_data/ # Trading-value JSON files parsed into Redis
- Backend
pnpm install pnpm dev # tsx + nodemon - Frontend
cd frontend pnpm install pnpm dev # http://localhost:5173 (uses VITE_API_BASE_URL)
- Production build
The Express server automatically serves
pnpm build # compiles backend + frontend pnpm start # serves /api and the built SPA
frontend/dist(setSERVE_FRONTEND=falseto disable). - Tests
pnpm test # vitest unit tests (rate limiter, etc.)
Copy .env.example (backend root):
CORS_ORIGINS=https://app.your-domain.com
API_KEY=optional-x-api-key
RATE_LIMIT_WINDOW_MS=60000
RATE_LIMIT_MAX=120
REDIS_URL=redis://default:password@host:11219
SERVE_FRONTEND=true
PORT=3000For the React dev server, copy frontend/.env.example and adjust:
VITE_API_BASE_URL=http://localhost:3000| Route | Description |
|---|---|
GET /api/coins |
Supported KRW markets (volume sorted). |
GET /api/data/:coin/latest?days=30 |
Latest day-candle slice. |
GET /api/data/:coin/range?start=YYYY-MM-DD&end=YYYY-MM-DD |
Day-candle slice for a date range (start required, end defaults to today). |
GET /api/data/:coin/statistics |
Min/Max/Range per coin. |
GET /api/market-data/:coin |
Redis-backed trading-value overlay (falls back to saved files). |
GET /api/coins/listing-dates |
Cached listing calendar snapshot (3h cadence). |
GET /api/coins/listing-strategies |
Cached Bybit short-scenario lab (3h cadence). |
GET /api/ticker / GET /api/ticker/:coins |
1-minute cached Upbit tickers (API-key protected if set). |
- Ticker cache: 60s TTL + persisted JSON (restored on restart).
- Day candles: Loaded on-demand and updated daily at 00:05 KST.
- Market data overlay: Parsed once per
saved_datamtime, then cached in Redis for 6h per coin. - Listing calendar & lab: Every 3 hours; results saved to
cache/and, after restart, to Redis for warm responses.
Upbit Alpha Desk๋ KRW ๋ง์ผ์ฉ ๋ฆฌ์กํธ ๊ธฐ๋ฐ ๋์๋ณด๋์
๋๋ค.
Upbit ์ผ๋ด, 1๋ถ ์บ์ ํฐ์ปค, saved_data ๊ฑฐ๋๋๊ธ, Bybit ์์ฅ ์ ์ ๋ต ํต๊ณ๋ฅผ Redis๊ฐ ๋ท๋จ์์ ์บ์ฑํ๊ณ Express API๋ก ์ ๊ณตํฉ๋๋ค.
- ๋ฐฑ์๋: Node.js, Express, TypeScript, Redis ์บ์, Axios ์ค์ผ์ค๋ฌ
- ํ๋ฐํธ์๋: React (Vite), React Query, Chart.js, date-fns
- ์ค์ผ์ค๋ฌ: ์์ฅ ์บ๋ฆฐ๋ / ์์ฅ ์ ๋ต(3์๊ฐ), ํฐ์ปค ์บ์, saved_data ํ์, ์์ ๋ฐ์ดํฐ ๊ฐฑ์
src/ # Express API + ์ค์ผ์ค๋ฌ
frontend/ # React/Vite SPA
public/ # ๊ธฐ์กด ์ ์ ์์
cache/, saved_data/ # ์ด์ ์บ์/๋ฐ์ดํฐ
- ๋ฃจํธ์์
pnpm install,pnpm dev(API ์๋ฒ). frontend/์์pnpm install,pnpm dev(Vite)..env์VITE_API_BASE_URL์ ๋ฐฑ์๋ ์ฃผ์๋ก ์ง์ .- ๋ฐฐํฌ ์
pnpm build(๋ฐฑ/ํ๋ฐํธ ๋์ ๋น๋) ํpnpm start์คํ โ Express๊ฐfrontend/dist(SPA)์/api/*๋ฅผ ํจ๊ป ์๋น์คํฉ๋๋ค. pnpm test๋ช ๋ น์ผ๋ก ๊ธฐ๋ณธ ์ ๋ ํ ์คํธ(๋ ์ดํธ ๋ฆฌ๋ฏธํฐ)๋ฅผ ๋๋ฆด ์ ์์ต๋๋ค.
CORS_ORIGINS=https://app.example.com
API_KEY=์ ํ์ ์ธ์ฆ ํค
RATE_LIMIT_WINDOW_MS=60000
RATE_LIMIT_MAX=120
REDIS_URL=redis://default:password@host:11219
SERVE_FRONTEND=trueํ๋ฐํธ๋ frontend/.env ์์ VITE_API_BASE_URL์ ์ค์ ํ์ธ์.
| ๊ฒฝ๋ก | ์ค๋ช |
|---|---|
/api/coins |
์ง์ KRW ๋ง์ผ ๋ชฉ๋ก |
/api/data/:coin/latest?days=N |
์ต๊ทผ N์ผ ์ผ๋ด ๋ฐ์ดํฐ |
/api/data/:coin/range?start=YYYY-MM-DD&end=YYYY-MM-DD |
๊ธฐ๊ฐ๋ณ ์ผ๋ด ๋ฐ์ดํฐ (start ํ์, end ๋ฏธ์ง์ ์ ์ค๋) |
/api/data/:coin/statistics |
ํต๊ณ (์ต๊ณ /์ต์ ๋ฑ) |
/api/market-data/:coin |
Redis ์บ์๋ ๊ฑฐ๋๋๊ธ/๊ฑฐ๋๋ |
/api/coins/listing-dates |
3์๊ฐ๋ง๋ค ๊ฐฑ์ ๋๋ ์์ฅ ์บ๋ฆฐ๋ |
/api/coins/listing-strategies |
3์๊ฐ๋ง๋ค ๊ณ์ฐ๋๋ ์์ฅ ์ ์ ๋ต ๋ณด๊ณ ์ |
/api/ticker / /api/ticker/:coins |
1๋ถ ์บ์ Upbit ํฐ์ปค |
- ํฐ์ปค: 1๋ถ TTL + ๋์คํฌ ๋ฐฑ์
- ์ผ๋ด ๋ฐ์ดํฐ: ์์ (00:05) ์๋ ์ ๋ฐ์ดํธ
- ๊ฑฐ๋๋๊ธ:
saved_dataํ์ผ ๋ณ๊ฒฝ ์ ์ฌํ์ฑ โ Redis 6์๊ฐ ์บ์ - ์์ฅ ์บ๋ฆฐ๋/์ ๋ต: 3์๊ฐ๋ง๋ค ์ฌ๊ณ์ฐ + ๋์คํฌ/Redis ์ค๋ ์ท
์์ด/ํ๊ตญ์ด ์ค๋ช ์ ํจ๊ป ์ ๊ณตํ๋ ํ๋ซํผํ ์์ ์ ์ฐธ๊ณ ํ์ธ์.