尚未检测到更新。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.