This project was built during October–November 2025 as a portfolio piece demonstrating multi-exchange delta-neutral trading infrastructure. It is published as-is for reference. No active development, bug fixes, or maintenance are planned. See Project Status and
docs/known-issues.mdfor the honest state of the codebase.
Delta-neutral trading dashboard for perpetual futures across Hyperliquid, Paradex, and Lighter.
A delta-neutral position is a market-neutral trade: take the same notional exposure in opposite directions on two correlated assets (typically spot vs. perpetual, or perp vs. perp on different venues) so the portfolio's net delta is zero. The trade then earns from funding-rate spreads and small price dislocations rather than from directional price movement.
This project is a working dashboard for that workflow. It aggregates funding rates, market data, positions, and order books across three perpetual-futures exchanges, surfaces funding-spread opportunities, and executes paired trades through a FastAPI backend with a React/TypeScript front end.
The goal was to demonstrate full-stack trading infrastructure — exchange connectors, a real-time WebSocket layer, position/PnL analytics, and a deployable UI — end to end. It is not a production trading system and it never traded with real capital.
This section is the part that matters. The project is unfinished, and the README would be doing a disservice by pretending otherwise.
| Exchange | Status | Notes |
|---|---|---|
| Hyperliquid | ✅ Complete | Market data, account, orders, position close, leverage. Asset-specific size precision. |
| Paradex | ✅ Complete | Market data, account, orders, position close. Leverage setting not supported by exchange API (leverage is auto-determined; default testnet is 50x). Requires Python 3.12 for the SDK. |
| Lighter | Market data, orders, position close, balance, history work. modify_order() and set_leverage() are stubs that raise NotImplementedError. Batch orders are a sequential loop, not a native batch. |
- Delta-neutral execution. Simultaneous market orders across two exchanges, with automatic rollback (cancels the filled leg if the counterpart fails).
- Real-time position management. Live positions, unrealized PnL, position close (full and partial) across exchanges.
- Funding rate analysis. Cross-exchange funding comparison, spread identification, opportunity ranking, execution from the opportunity view.
- PnL & volume analytics. Net / realized / unrealized PnL, funding received/paid, fees, volume by exchange / pair / side / time period, win rate, average profit per trade, best/worst trade.
- Opportunity discovery. Funding-spread scanner and price-arbitrage signals with a click-through path to execution.
- WebSocket updates. Live position, PnL, and execution notifications over a custom WebSocket manager.
- Funding & History tab in the front end is a placeholder. The UI components exist, but the backend never writes historical trade or funding data to the database (SQLModel models and Alembic migrations are defined, no write path), so the tab has no data to render.
- Leverage selection is unreliable. The UI slider may be silently ignored or the backend call may fail.
- Rapid trade execution can leave the front end out of sync with exchange state — there is no queuing or debouncing of state updates.
- WebSocket reconnection is not implemented. If a connection drops, real-time updates stop until a manual page refresh.
- Paradex token refresh has unhandled edge cases near JWT expiry.
- Number formatting in PnL, trade profit, and fee displays has sign and precision bugs in several components (
PnLTab,TransactionNotification,TradeExecutionDropdown). - Database persistence is effectively absent. Models exist; writes do not.
The full bug list, incomplete features, design debt, and "not implemented" backlog are documented in docs/known-issues.md.
┌──────────────────────────┐ ┌──────────────────────────────────────┐
│ React 18 + TypeScript │ HTTP │ FastAPI Backend │
│ (Vite, Recharts, Axios) │ ──────▶ │ (Python 3.12, SQLModel, Alembic) │
│ │ │ │
│ Dashboard tabs: │ WS │ Routers: │
│ • Opportunities │ ◀───── │ • /exchanges/hyperliquid/* │
│ • Positions & Orders │ │ • /exchanges/paradex/* │
│ • PnL │ │ • /exchanges/lighter/* │
│ • Funding & History ⚠ │ │ • /opportunities/funding/{pair} │
│ │ │ • /history/* │
└──────────────────────────┘ │ • /ws (WebSocket manager) │
│ │
│ Connectors: │
│ • hyperliquid-python-sdk ✅ │
│ • paradex-py ✅ │
│ • lighter-sdk ⚠ │
│ │
│ Storage: │
│ • SQLite (schema only, no writes) │
└──────────────────────────────────────┘
The back end exposes a versioned REST API per exchange plus a single WebSocket stream that fans out position, PnL, and execution events to subscribed clients. Each exchange has its own connector module that implements a shared ExchangeConnector interface, which is what made adding Lighter tractable.
The front end is a tabbed dashboard. Tabs render live data through Axios (HTTP) and a custom WebSocket client (push), with Recharts powering the analytics visualizations under a single terminal-style theme.
| Layer | Technology |
|---|---|
| Backend language | Python 3.12 (Paradex SDK paradex-py does not support 3.13) |
| Backend framework | FastAPI 0.115 |
| ASGI server | Uvicorn |
| ORM / migrations | SQLModel 0.0.21 + SQLAlchemy 2.0 + Alembic 1.13 |
| Logging | structlog 24.4 (JSON logs, automatic secret redaction) |
| Exchange SDKs | hyperliquid-python-sdk 0.20, paradex-py (Python 3.12 only), lighter-sdk (via lighter-python) |
| Frontend framework | React 18.3 + TypeScript 5.5 |
| Build tool | Vite 5.4 |
| Charts | Recharts 2.12 |
| HTTP client | Axios 1.7 |
| Database | SQLite (schema defined, write path not implemented) |
Tested on macOS with Python 3.12 and Node.js 18+.
- Python 3.12 (required for
paradex-py; the Paradex connector will not work on 3.13) - Node.js 18+ and npm
- Homebrew (for
brew install python@3.12on macOS)
git clone <repo-url> delta-hedge
cd delta-hedge# Install Python 3.12 if you don't have it
brew install python@3.12
# Create a Python 3.12 virtual environment
cd backend
python3.12 -m venv .venv312
source .venv312/bin/activate
# Install dependencies
pip install -r requirements.txt
# Copy the environment template and fill in your real credentials
cp .env.example .env
# Edit .env with your wallet keys and exchange settings.
# The .env.example file lists every variable with placeholder values.
# Run database migrations
alembic upgrade head
# Start the API server
uvicorn app.main:app --reloadThe API will be available at http://127.0.0.1:8000 and the auto-generated
docs at http://127.0.0.1:8000/docs.
Why .venv312? The backend repo also has a .venv (Python 3.13) for the
general path. The paradex-py SDK does not support Python 3.13, so the
Paradex connector needs .venv312. Use .venv312 for everything to keep
things simple — that is the supported configuration.
In a separate terminal:
cd frontend
npm install
npm run devThe dashboard will be available at http://localhost:3000. The Vite dev
server is configured to proxy /api requests to the FastAPI backend, so no
extra configuration is needed for local development.
Both .env.example files are the source of truth for which variables to set:
backend/.env.example— database path, log level, Hyperliquid wallet key, Paradex L1/L2 addresses and key, Lighter credentials, slippage and leverage limits..env.example(project root) — Lighter-specific credentials, kept separately because they are added in a different setup step.
Never commit real keys. The .gitignore excludes .env, *.bak, and
similar files. Use only the .env.example files as a template.
delta-hedge/
├── backend/
│ ├── app/
│ │ ├── connectors/ # Exchange connectors
│ │ │ ├── base/ # ExchangeConnector interface
│ │ │ ├── hyperliquid/ # ✅ Full coverage
│ │ │ ├── paradex/ # ✅ Full coverage
│ │ │ └── lighter/ # ⚠ ~50% — 2 NotImplementedError stubs
│ │ ├── routers/ # FastAPI route handlers
│ │ │ ├── hyperliquid.py
│ │ │ ├── paradex.py
│ │ │ ├── lighter.py
│ │ │ ├── strategies.py # Delta-neutral execution
│ │ │ ├── history.py # Historical / volume queries
│ │ │ ├── opportunities.py
│ │ │ └── websocket.py
│ │ ├── services/ # Exchange manager, data aggregator, persistence
│ │ ├── models.py # SQLModel database models
│ │ └── main.py # FastAPI app entry point
│ ├── alembic/ # Database migrations
│ ├── tests/ # Pytest suite
│ ├── scripts/ # Diagnostic and helper scripts
│ ├── requirements.txt
│ └── README.md # Backend-specific documentation
├── frontend/
│ ├── src/
│ │ ├── components/ # React components (Dashboard, PnLTab, …)
│ │ ├── services/ # API + WebSocket clients
│ │ └── styles/ # Theme and component styles
│ ├── package.json
│ └── README.md # Frontend-specific documentation
├── docs/
│ └── known-issues.md # Full bug list + design debt + "not implemented" backlog
├── .env.example # Lighter env template
├── PROJECT_SUMMARY.md # Original project write-up (Oct–Nov 2025)
├── SETUP_INSTRUCTIONS.md # Detailed Lighter onboarding steps
├── ADDING_NEW_EXCHANGES.md # Connector authoring guide
├── WEBSOCKET_COMPARISON.md # Per-exchange WebSocket behavior notes
└── README.md # ← you are here
The full list lives in docs/known-issues.md. The highlights:
Bugs (medium severity):
- WebSocket reconnection is not implemented
- Paradex token refresh has unhandled expiry edge cases
- Rapid trade execution can desync the front end
- PnL / fee / slippage number formatting has sign and precision bugs in
PnLTab,TransactionNotification,TradeExecutionDropdown - Leverage selection in the UI is not reliably applied before order placement (high severity)
Incomplete features:
- Lighter connector is ~50% complete (modify_order and set_leverage are stubs)
- Funding & History tab is a placeholder (UI is there, no data is written to the database)
- Paradex has no programmatic leverage API — leverage is always exchange-determined (50x on testnet)
Design debt:
- 5
NotImplementedErrorstubs across Paradex and Lighter - 8 raw
print()statements in the Paradex connector that bypass the structured logger - SQLModel schemas defined but no write path — the database is effectively empty
- Inconsistent error formatting between Python tracebacks, generic 500s, and exchange-specific messages
Not implemented (scoped but never built):
- Database persistence (would unblock the Funding & History tab and CSV export)
- Full WebSocket push coverage across all three exchanges
- Automated delta-neutral strategies (funding-rate and price-arbitrage bots)
- Historical backtesting
- Docker / CI-CD
- Mobile responsiveness, dark/light theme toggle, alerting
See the linked doc for the prioritized list and source citations.
This project is a portfolio piece, not a trading system. It was built for educational and demonstration purposes, was never used with real funds, and is published as-is. Nothing in this repository constitutes financial advice or a recommendation to trade on any of the integrated venues. Trading perpetual futures carries substantial risk of loss.