A platform that lets users build and trade leveraged baskets of Polymarket prediction markets. The core insight: an uncorrelated basket of prediction markets has lower portfolio variance than any single market, which justifies offering leverage on the basket — the same principle behind portfolio margin in equities.
The platform acts as the lender. Users deposit collateral, the platform lends additional capital, and an AI-powered risk engine determines how much leverage is safe based on the basket's correlation structure and real-time market data.
- Search & Select — Browse trending Polymarket markets or search by topic. Add markets to your basket with YES/NO directional bets.
- Risk Calculation — The LLM Oracle (Claude) analyzes each market's resolution timing, shock events, and semantic correlations. A five-layer risk pipeline computes portfolio volatility, jump risk, and max safe leverage.
- Leverage & Execute — Choose your leverage (bounded by the risk engine), deposit collateral, and execute. The platform lends the rest. Positions are opened at live CLOB ask prices.
- Rebalance — Existing positions appear in the basket builder. Adjust weights to rebalance: the system automatically buys more of increased positions and partially sells reduced ones, with VWAP cost basis tracking.
- Monitor — The portfolio screen shows real-time margin health, effective leverage, collateral vs notional exposure, and distance to liquidation.
- Liquidation — If a market resolves adversely and equity drops below maintenance margin, all positions are force-closed. A detailed post-mortem explains what triggered the liquidation.
Hackathon_AI/
├── main-app/ # Expo React Native frontend (TypeScript)
│ ├── app/(tabs)/
│ │ ├── index.tsx # Basket Builder — search, market picker, risk engine, rebalance
│ │ └── explore.tsx # Portfolio — equity, margin health, positions, liquidation post-mortem
│ ├── components/
│ │ └── ensamble-header.tsx # Shared "Ensamble" branding header
│ └── lib/backend.ts # Typed API client for all backend endpoints
│
├── backend/ # Python FastAPI backend
│ ├── server.py # Main server — trading, portfolio, risk, rebalance, admin
│ ├── oracle.py # LLM Oracle (Layer 0): Claude API + web search for market intelligence
│ └── correlation_engine.py # Correlation matrix builder (empirical + category + tag blend)
│
└── risk_management/ # Five-layer risk engine library
├── models.py # Pydantic data models
├── llm_oracle.py # Alternative LLM oracle with web search tool
├── risk_params.py # Layer 1: per-position vol, jump intensity/magnitude
├── portfolio_risk.py # Layer 2: portfolio VaR, jump risk, resolution clustering
├── correlation.py # Correlation matrix (3-source blend)
├── liquidation.py # Layer 3: liquidation cost model
├── margin.py # Layer 4: margin thresholds, max leverage
├── monitoring.py # Layer 5: continuous monitoring, stress tests
└── config.py # Tunable risk parameters
- Collateral-based accounting — Only the user's collateral is deducted from cash, not the full leveraged notional. The platform lends the difference.
- Combined margin validation — When extending an existing portfolio, the system validates that the combined portfolio (existing + new positions) satisfies margin requirements before executing.
- Proper bid/ask pricing — Entry prices use the CLOB ask (what you pay to buy), mark-to-market uses the CLOB bid (what you'd receive selling). Positions show a realistic spread cost immediately after opening.
- Existing positions are pre-loaded in the basket builder with current weights (shown in amber)
- Adjust weights to rebalance, add new markets, or remove positions to sell
- The backend computes deltas (target vs current) and executes the minimal set of buys/sells
- Partial sells return proportional collateral + PnL; buys merge with VWAP cost basis
- Pure rebalance (no new capital) supported by setting additional collateral to $0
The risk pipeline uses Claude (Sonnet 4.6) with web search to assess each market:
| Layer | Module | What It Does |
|---|---|---|
| 0 | oracle.py |
Calls Claude API with web search to assess resolution timing, shock events, correlation tags, volatility regime |
| 1 | risk_params.py |
Per-position: diffusive volatility (σ), jump intensity (λ), jump magnitude, resolution proximity |
| 2 | portfolio_risk.py |
Portfolio VaR, jump risk with correlation multiplier, resolution clustering penalty |
| 3 | liquidation.py |
Liquidation cost (spread + market impact + urgency), execution time estimate |
| 4 | margin.py |
Initial/maintenance/liquidation margin thresholds, max leverage = 1/initial_margin |
| 5 | monitoring.py |
Continuous margin status checks, stress test scenarios |
Correlation matrix blends three sources: empirical price correlation (Ledoit-Wolf shrinkage), category priors, and LLM-derived semantic tag overlap (Jaccard similarity, capped at 0.6).
Max leverage formula:
total_risk = risk_diffusive + risk_jump + resolution_clustering_penalty + liquidation_cost
safety_buffer = BASE_SAFETY_BUFFER * (1 + model_uncertainty)
initial_margin = (total_risk + safety_buffer) * 1.5
max_leverage = clamp(1 / initial_margin, 1.0, 10.0)
- Admin webapp at
http://localhost:8000/admin— inject fake market resolutions to test liquidation mechanics - Resolving a position at an adverse price triggers a margin check on the remaining portfolio
- If equity/notional drops below maintenance margin, all positions are force-closed
- A detailed post-mortem is stored and displayed on the portfolio screen, explaining what triggered the liquidation, the margin ratios involved, and total PnL impact
| Method | Endpoint | Description |
|---|---|---|
| GET | /health |
Status check, cash balance, open position count |
| GET | /markets/search?q=<query> |
Search live Polymarket markets via Gamma API |
| GET | /markets/trending |
Top markets by 24h volume (60s cache) |
| GET | /markets/{condition_id} |
Single market with live CLOB price |
| POST | /basket/execute |
Execute basket (buy-only or full rebalance mode) |
| POST | /basket/risk |
Compute risk metrics for proposed basket (with optional portfolio merge) |
| POST | /trade/buy |
Buy a single position |
| POST | /trade/sell |
Sell an open position |
| GET | /portfolio |
Open positions with live prices, margin health, liquidation events |
| GET | /portfolio/history |
Closed trades with realized PnL |
| GET | /portfolio/pnl |
Aggregated P&L scoreboard |
| POST | /portfolio/close-all |
Close all open positions |
| POST | /portfolio/check-close |
Check if closing one position would violate margin |
| POST | /portfolio/reset |
Wipe everything, restore $10,000 |
| GET | /admin |
Admin webapp for force-resolving positions |
| POST | /admin/inject-resolution |
Force-resolve a position at a given price |
| GET | /admin/liquidation-events |
Liquidation event history |
pip install fastapi uvicorn httpx aiosqlite pydantic numpy anthropic
export ANTHROPIC_API_KEY='sk-ant-...'
python backend/server.py
# Runs on http://0.0.0.0:8000
# API docs at http://localhost:8000/docs
# Admin panel at http://localhost:8000/admincd main-app
npm install
npx expo start
# Press 'i' for iOS simulator, or scan QR with Expo Go on a phone (same WiFi)For mobile testing, the phone needs the computer's local WiFi IP instead of localhost:
EXPO_PUBLIC_API_BASE_URL=http://192.168.x.x:8000 npx expo startTwo separate APIs are used:
- Gamma API (
https://gamma-api.polymarket.com) — market discovery and search - CLOB API (
https://clob.polymarket.com) — live order book prices
Every market has three IDs:
- Gamma ID — numeric, only for Gamma API
- Condition ID — hex string, used as the primary market identifier
- Token ID — large integer, used for CLOB price/book/midpoint queries
The CLOB /price endpoint's side parameter refers to the order book side, not the action:
side=SELL→ ask price (what you pay to buy)side=BUY→ bid price (what you receive selling)
- Frontend: React Native (Expo 54), TypeScript, expo-router
- Backend: Python, FastAPI, aiosqlite, httpx
- Risk Engine: NumPy, Pydantic, Claude API (Sonnet 4.6) with web search
- Data: Polymarket Gamma + CLOB APIs, SQLite persistence