PolyOpt is a self-hosted web app for Polymarket traders who want a single place to view positions, live market context (prices + order book), correlation-style similarity across markets, CVaR-based hedge suggestions, optional CLOB order signing, and operational alerts — without relying on a third-party SaaS for your workflow.
Disclaimer: Analytics, correlations, and optimizer output are model-based decision support, not investment advice. Polymarket trading involves risk; verify execution, fees, and settlement on your own.
| Capability | What you get |
|---|---|
| Unified book view | Positions and exposures derived from Polymarket Data API + Gamma metadata + CLOB top-of-book where available. |
| Hedge ideation | Run a Python CVaR optimizer against your book and scenario presets; preview hedges without a full optimize pass. |
| Linkages | Correlation matrix (feature similarity, not classical return correlation) and Hedge Map graph to spot clusters and concentration. |
| Execution path | Connect a wallet (Reown AppKit / Wagmi), EIP-712 sign orders, relay via your backend to Polymarket CLOB (with optional server-side L2 headers in Pro). |
| Risk & ops | Alerts (rules + channels), health checks, Market Scan (crypto / sports / politics), exports and audit-style trails on portfolio pages. |
| Pro tier | Rate limits, security headers, Postgres-backed alert sync, enriched feed metadata, institutional-style risk report API — for production deployments. |
- Backend (Node.js + Express) — Auth (sessions + Passport local), REST API, WebSocket market polling, and spawned Python for
server/optimize.py. - Database (PostgreSQL) — Users, portfolios/positions (demo path), sessions (
connect-pg-simple), and Prouser_alert_statefor durable alerts. - Frontend (React + Vite) — Dashboard, portfolio detail, live markets, correlations, hedge map, alerts, integrations, market scan.
- Polymarket — Positions from Data API; market text/slugs from Gamma; books and orders via CLOB. Retries/timeouts are configurable.
- Wallet split — Set
POLYMARKET_WALLET_ADDRESSfor read/analytics; the in-app connected wallet is used for signing when you place orders.
| Area | Route | Purpose |
|---|---|---|
| Portfolios | / |
Overview of linked Polymarket-style portfolio and summaries. |
| Portfolio strategy | /portfolio/:id |
Positions, RUN ALGORITHM, hedge results, presets, risk attribution, Pro risk report (if enabled). |
| Live markets | /markets |
Per-market cards: probability, exposure-style metrics, spread/depth, mini trends, links to map/correlations/alerts. |
| Market scan | /market-scan |
Category scan (crypto / sports / politics) for active, liquid markets. |
| Correlations | /correlations |
Weighted matrix, top pairs, drilldown, hedge preview API. |
| Hedge map | /hedge-map |
Graph of linkages, thresholds, node rankings. |
| Alerts | /alerts |
Rule types, severity, channels; Pro persists rules/events in DB. |
| Integrations | /integrations |
PWA, system health (API reachability, Pro tier, uptime). |
- Runtime: Node 20+ (recommended), TypeScript, Express 5
- UI: React 18, Wouter, TanStack Query, Tailwind, Radix, Recharts
- Wallet: Reown AppKit, Wagmi, Viem (Polygon)
- DB: PostgreSQL, Drizzle ORM
- Optimizer: Python 3.12+ (
cvxpy,numpy, …) viauvor plainpython - Build: Vite (client →
dist/public), esbuild (server →dist/index.cjs)
- Node.js 20+ and npm
- PostgreSQL (URL in
DATABASE_URL) - Python 3.12+ with optimizer deps — easiest: install uv and run from repo root:
uv sync(usespyproject.toml)
Or installnumpy,cvxpy(seepyproject.toml) and setOPTIMIZER_CMD=pythonif you don’t useuv. - Git
Optional:
VITE_WALLETCONNECT_PROJECT_ID— wallet modal / QR connect- Polymarket
POLYMARKET_WALLET_ADDRESS— populate dashboards from a specific address
git clone <your-fork-or-repo-url> Market-Hedge-Bot
cd Market-Hedge-Bot
npm installCreate a database and set:
cp .env.example .env
# Edit .env — set DATABASE_URL, SESSION_SECRET (long random string)Apply schema (Drizzle):
npm run db:pushIf you use Pro (APP_TIER=pro), ensure migration for alerts exists or db:push picked up user_alert_state (see migrations/).
Minimum for a working app:
| Variable | Purpose |
|---|---|
DATABASE_URL |
PostgreSQL connection string |
SESSION_SECRET |
Session signing (use a long random value) |
POLYMARKET_WALLET_ADDRESS |
(Recommended) Address whose Polymarket positions power analytics |
See .env.example for Pro, CLOB relay, timeouts, and frontend keys.
npm run devOpen the URL printed in the terminal (default http://127.0.0.1:5000 or your PORT). Register a user, sign in, connect wallet as needed.
These steps fit a VPS (Ubuntu), bare metal, or any host that can run Node + PostgreSQL + Python. There is no Dockerfile in-repo; add your own if you prefer containers.
- Create a database and user.
- Note the connection string:
postgresql://USER:PASSWORD@HOST:5432/DATABASE
- Node 20+ installed (
node -v). - Python 3.12+ and either
uvorpythonwithcvxpy/numpyinstalled. - Clone the repo to
/opt/polyopt(or similar).
On the server:
cd /opt/polyopt
cp .env.example .envEdit .env:
DATABASE_URL— production Postgres URL.SESSION_SECRET— cryptographically strong secret (32+ random bytes).NODE_ENV=production— usually set by your process manager /npm start(see below).POLYMARKET_WALLET_ADDRESS— wallet to analyze.PORT/HOST— e.g.PORT=5000,HOST=0.0.0.0behind a reverse proxy.- Pro (optional):
APP_TIER=proorPRO_MODE=1- Required in production Pro:
SESSION_SECRETmust not be the dev default (polyopt-dev-session-secret). The app exits on boot if that check fails. - Optional:
POLY_*headers for server-side CLOB relay (see.env.example).
- Required in production Pro:
- Frontend build-time: set
VITE_WALLETCONNECT_PROJECT_ID(and anyVITE_*vars) beforenpm run build— they are baked into the client bundle.
npm ci
npm run db:push(Or run SQL migrations manually if you use a migration runner.)
With uv (recommended):
uv syncDefault optimizer command in code paths is effectively uv run python server/optimize.py. To use system Python instead:
OPTIMIZER_CMD=python
OPTIMIZER_ARGS=server/optimize.pyEnsure cvxpy and numpy are importable.
npm run buildThis produces:
dist/public/— static SPA (Vite)dist/index.cjs— bundled Node server entry
npm startnpm start runs NODE_ENV=production node dist/index.cjs. The server serves the API and static files from dist/public.
- Put Nginx, Caddy, or Traefik in front.
- Terminate HTTPS, proxy to
http://127.0.0.1:PORT. - With Pro,
trust proxyis enabled so secure cookies and client IPs work correctly behind the proxy.
Use systemd, PM2, or Docker Compose (your own file) to:
- Restart on failure
- Set env vars or point to
.env - Log stdout/stderr
Example PM2:
npm install -g pm2
cd /opt/polyopt
pm2 start dist/index.cjs --name polyopt --interpreter node
pm2 save(Ensure NODE_ENV=production and the same env as in .env.)
curl https://your-domain/api/health— JSON withok, Polymarket reachability flags,proMode, etc.- Open the site, register/login, confirm Live Markets / Portfolio load.
- Run RUN ALGORITHM once — confirms Python optimizer path on the server.
| Standard | Pro (APP_TIER=pro / PRO_MODE=1) |
|
|---|---|---|
| NODE_ENV=production | Normal startup | Requires non-default SESSION_SECRET |
| Alerts | Browser localStorage |
Synced to user_alert_state table |
| API | No app rate limits | Per-IP rate limits on auth + API |
| Headers | Baseline security | Extra production security headers |
| Feed | Markets list | Envelope with lineage / fingerprint metadata |
| Risk | UI attribution | GET /api/pro/risk-report |
| Symptom | Likely cause |
|---|---|
npm start exits immediately with SESSION_SECRET error |
Pro + NODE_ENV=production + default dev secret. Set a real SESSION_SECRET. |
| DB error on boot | Missing or wrong DATABASE_URL. |
| Optimizer / RUN ALGORITHM fails | Python or cvxpy not installed; set OPTIMIZER_CMD / OPTIMIZER_ARGS; check server logs. |
| Empty portfolio / markets | POLYMARKET_WALLET_ADDRESS unset or wrong; Polymarket API blocked from server; check /api/health. |
| 502 / static not found | Forgot npm run build or dist/public missing. |
| Wallet works in dev, not prod | Rebuild with correct VITE_WALLETCONNECT_PROJECT_ID; use HTTPS origin; check browser console. |
| Command | Description |
|---|---|
npm run dev |
Dev server + Vite HMR (NODE_ENV=development). |
npm run build |
Client → dist/public, server → dist/index.cjs. |
npm start |
Production server (NODE_ENV=production). |
npm run check |
TypeScript check. |
npm run db:push |
Push Drizzle schema to Postgres. |
MIT — see package.json. Polymarket is a third-party service; this project is not affiliated with Polymarket.
Issues and PRs welcome: clearer copy for traders, deployment templates (Dockerfile, compose), and hardened production defaults are especially valuable.