尚未偵測到更新。GitHub 發布版本後會顯示在這裡。
個人 GitHub 帳號下公開儲存庫的擁有者可以登入並驗證所有權,自行管理介紹,無需管理員核准。
登入並產生驗證檔案,在 30 分鐘內將其提交至此儲存庫的預設分支。其他分支或分叉儲存庫中的檔案無效。然後在下方檢查檔案,即可無需管理員核准直接管理專案。請保留檔案以維持管理權限。
如需登入,將前往登入頁面。登入後請回到此處,再次點擊所選的驗證按鈕。
在專案資料夾中執行 /nomorevibe verify,即可驗證所有權並自行管理介紹。
一分鐘完成驗證正在載入完整 README。 以下為已儲存的摘錄。
CW Research Terminal is a research workstation for Vietnamese covered warrants and their
underlying equities, combining realtime market monitoring, quantitative analytics,
historical research, and AI-assisted analysis.
▶ Live demo: https://cw-research-terminal.vercel.app — no account needed; the dashboard,
research, market data, quant analytics, and history are all fully public.檢視完整 README ↗CW Research Terminal is a research workstation for Vietnamese covered warrants and their underlying equities, combining realtime market monitoring, quantitative analytics, historical research, and AI-assisted analysis.
▶ Live demo: https://cw-research-terminal.vercel.app — no account needed; the dashboard, research, market data, quant analytics, and history are all fully public.
It is a personal project. Runtime market data comes from public Vnstock Community
KBS/VCI adapters plus the SSI iBoard WebSocket protocol documented by vnstock-js. It is
not affiliated with, sponsored by, or operated on behalf of those projects or providers.
A covered warrant (CW) is an exchange-listed option-like security issued by a securities firm. A HOSE call CW gives the holder the right to buy a fixed underlying stock (e.g. HPG) at a fixed exercise price by a fixed maturity, converted at a fixed ratio (e.g. 5:1 — five warrants per share). Its price is driven by the underlying's price, time to maturity, and volatility — so it is priced and risk-managed with a Black-Scholes-Merton model. This terminal pairs each CW with its underlying and computes the standard analytics (theoretical price, implied volatility, Greeks, moneyness, spread, days-to-expiry).
REALTIME
SSI iBoard WebSocket + KBS recovery poll ─► VnstockProvider
─► MarketState (normalized bid/ask/trade)
─► Redis warm cache (L2 recovery) ─► FastAPI WebSocket (/ws/market) ─► React
LiveQuantEngine ◄─ market ticks ─► BSM / IV / Greeks / theo price ─► analytics patches ─► WS
HISTORICAL
history_read_service (PostgreSQL-first)
complete DB hit → 0 provider calls
legitimate in-horizon gap → 1 controlled, single-flighted Vnstock fill → persist
PostgresHistoricalBarSource → HistoricalVolatilityService (HV_22) → in-memory estimate → LiveQuantEngine
QUANT
market quote + contract terms (effective strike/ratio) ─► BSM / IV / Greeks / theo / HV ─► analytics
RESEARCH
market + history + quant context ─► research views ─► AI-assisted explanation / comparison / summarization
AUTH (optional)
Supabase Auth ─► JWT verified locally ─► /api/me/* only (user-specific persistence)
MarketDataProvider is a vendor-neutral abstraction (connect, set_subscriptions,
get_historical_bars, set_event_callback). The runtime implementation is
VnstockProvider; source changes stay behind this boundary and do not alter the
subscription planner, market-state pipeline, or quant engine.q = 0 — see
backend/app/quant/dividend_convention.py.| Decision | Why |
|---|---|
MarketDataProvider abstraction | Vendor-neutral seam; the subscription planner, market-state pipeline and quant engine never import a vendor SDK. |
| One backend replica / one Uvicorn worker | The provider owns one SSI socket, the bounded recovery poller, and shared in-memory state; a second worker would duplicate upstream traffic and split process-local WS state. |
| PostgreSQL-first history | A complete DB hit makes zero provider calls; only a legitimate in-horizon gap triggers one controlled, advisory-locked, single-flighted fill, which is then persisted. |
| Redis warm state | L2 recovery of the latest canonical market snapshot across restarts/sessions, plus the distributed rate limiter (separate key prefixes). |
q = 0 dividend convention | CWs are dividend-protected via strike/ratio adjustment; a BSM q > 0 would double-count and underprice. |
| Adjusted stock history vs RAW CW history | Underlying HV is computed from corporate-action-adjusted closes (removes ex-date jumps from the volatility estimate); CW bars are stored RAW because CW terms are re-based on the ex-date, so there is nothing to adjust. |
Backend 1,500+ pytest cases (quant verification, provider lifecycle, ingestion /
history, auth, rate-limit / security, repo-hygiene) + frontend ~190 vitest cases,
tsc --noEmit, and pyright. Normal CI tests use captured provider fixtures and make no
live market-data request.
cd backend && .venv/bin/python -m pytest -q
cd frontend && npm test && npx tsc --noEmit && npm run build
The persistence tests spin up a disposable local PostgreSQL cluster and skip cleanly when
initdb / pg_ctl are not on PATH.
| Piece | Where |
|---|---|
| Frontend (static Vite build) | Vercel — https://cw-research-terminal.vercel.app |
| Backend (FastAPI, 1 replica / 1 Uvicorn worker) | Railway |
| PostgreSQL + Redis | Railway (private networking) |
— rather than stale values.MarketDataProvider boundary or the existing persisted public enrichment pipeline.| Layer | Technology |
|---|---|
| Backend | Python 3.13, FastAPI, SQLAlchemy 2 (async), Alembic |
| Realtime provider | SSI iBoard WebSocket (documented by vnstock-js) + Vnstock KBS recovery polling |
| Storage | PostgreSQL (historical bars), Redis (warm market-state cache + rate limiter) |
| Auth (optional) | Supabase Auth — JWT verified locally; only /api/me/* is protected |
| AI assistant (optional) | OpenRouter |
| Frontend | React 18, TypeScript, Vite, TanStack Query |
Prerequisites: Python 3.13, Node.js 18+, PostgreSQL 15+, Redis, and a Vnstock Community API key for the Python data adapter.
# backend
cd backend
python -m venv .venv && .venv/bin/pip install -r requirements.txt
cp ../.env.example ../.env # fill in VNSTOCK_API_KEY (+ DB/Redis if used)
.venv/bin/alembic upgrade head # only if DATABASE_ENABLED=true
.venv/bin/python -m app.main # http://localhost:8501
# frontend
cd frontend
npm install
npm run dev # http://localhost:5173
All configuration is environment-driven — see .env.example for the full annotated
list. The only market-data credential the runtime needs is the server-side Vnstock key, and
optionally a PostgreSQL URL, a Redis URL, a Supabase project (auth), and an OpenRouter key
(AI). Never commit a real .env.
The domain modeling — covered-warrant contract mechanics, corporate-action term
adjustments, the analytics column set — reflects experience building trading-desk research
tooling during a software-engineering internship. Every line in this repository is an
independent implementation over public market rules and public data sources. The SSI
subscription envelope and frame layout are adapted from the Apache-2.0 vnstock-js
project; see THIRD_PARTY_NOTICES.md. The repository contains no credentials.