A full-featured prediction market platform for Georgia Tech Intramural sports, built with FastAPI and Vue.js. Trade shares on game outcomes using our in-game currency "tokens" (πͺ).
FULLY OPERATIONAL - Complete prediction market platform:
- β Automated Market Maker (LMSR) for dynamic pricing
- β User wallets with 10,000 tokens starting balance
- β Real-time market updates from IMLeagues API
- β Portfolio tracking with open and settled positions
- β Markets auto-close at game start time
- β Automatic settlement based on final scores
- β 166 active markets (45 open, 40 closed, 81 settled)
- Binary Markets: Predict which team will win each game
- Dynamic Pricing: Logarithmic Market Scoring Rule (LMSR) adjusts prices based on trading activity
- Market States:
- π’ Open: Markets accepting predictions until game start
- π΄ Closed: Game started, awaiting final score
- β Settled: Final score recorded, payouts distributed
- Virtual Currency: "tokens" (πͺ) - GT-themed in-game currency
- Starting Balance: 10,000 tokens per user
- Share Pricing: 0-100Β’ per share based on market probability
- Settlement: Winning shares pay 100 tokens, losing shares pay 0
- Track open positions across multiple markets
- View settled positions and payouts
- Real-time portfolio valuation
- Detailed performance analytics
- Backend: FastAPI (Python 3.13), Pydantic
- Frontend: Vue.js 3 (Composition API)
- Market Maker: LMSR (Logarithmic Market Scoring Rule)
- Data Source: IMLeagues API with BeautifulSoup4 parsing
- HTTP Client: httpx for async API calls
- Server: Uvicorn ASGI
We use the Logarithmic Market Scoring Rule to provide liquidity:
- Prices automatically adjust based on share purchases
- More shares bought = higher price for that outcome
- Ensures prices always sum to 100Β’
- Parameter
b=100controls liquidity depth
- Created: When game data is fetched from IMLeagues
- Open: Users can buy shares on either team
- Closed: Game starts (based on scheduled time)
- Settled: Final score recorded, winning shares pay 100 tokens
- Each user gets a unique ID stored in cookies
- Starting balance: 10,000 tokens
- Buy shares in any open market
- Watch prices update in real-time
- Track positions in your portfolio
- Collect payouts when markets settle
-
Create/Activate Virtual Environment (already configured):
.\.venv\Scripts\Activate.ps1
-
Install Dependencies (already installed):
pip install -r requirements.txt -
Run the Server:
python main.py
Or using the venv directly:
.\.venv\Scripts\python.exe main.py
-
Start the server (runs on http://localhost:8000):
python main.py
-
Access the application:
- Main App: http://localhost:8000/
- API Docs: http://localhost:8000/docs
- Health Check: http://localhost:8000/api/health
-
Start Predicting:
- Browse open markets on the Markets tab
- Click "Buy" on your predicted winner
- Enter amount in tokens to spend
- Confirm prediction
- Track positions in Portfolio tab
-
API Endpoints:
GET /api/user- Get/create user and balanceGET /api/markets- Get all prediction marketsPOST /api/trade- Execute a prediction (buy shares)GET /api/portfolio- Get user's positionsGET /api/games- Get cached games dataGET /api/games/refresh- Fetch fresh data from IMLeagues
-
Trading Example:
# Place a prediction via API Invoke-RestMethod -Uri http://localhost:8000/api/trade -Method POST -Headers @{"Content-Type"="application/json"} -Body '{"market_id":"market_R23324077","outcome":"home","amount":500}'
PolyJacket/
βββ main.py # FastAPI backend with prediction market logic
β # - User management & wallets
β # - LMSR market maker
β # - Trade execution
β # - Market lifecycle management
βββ requirements.txt # Python dependencies
βββ games_cache.json # Cached games data from IMLeagues
βββ static/
β βββ index.html # Vue.js 3 SPA with prediction interface
βββ .venv/ # Virtual environment
βββ .gitignore # Git ignore rules
- Total Markets: 166 games
- Date Range: Last 3 days + Next 7 days from current date
- Sports: Basketball, Flag Football, Soccer, Volleyball, etc.
- Data Source: IMLeagues API for Georgia Tech
- Update Frequency: On-demand via
/api/games/refresh
To fetch the latest games and create/update markets:
curl http://localhost:8000/api/games/refresh# Get your user ID and balance
$user = Invoke-RestMethod -Uri http://localhost:8000/api/user
Write-Host "Balance: $($user.balance) tokens"
# View available markets
$markets = Invoke-RestMethod -Uri http://localhost:8000/api/markets
$markets.markets | Where-Object {$_.status -eq 'open'} | Select-Object -First 5
# Place a prediction
$trade = @{
market_id = "market_R23324077"
outcome = "home"
amount = 500
} | ConvertTo-Json
Invoke-RestMethod -Uri http://localhost:8000/api/trade -Method POST `
-Headers @{"Content-Type"="application/json"} -Body $trade
# Check portfolio
Invoke-RestMethod -Uri http://localhost:8000/api/portfolio- Prices range from 0-100Β’ (representing probability)
- 50Β’ = 50% implied probability
- Buying shares increases price
- YES and NO prices always sum to 100Β’
- Higher volume = more accurate prices
- User data, markets, and positions stored in dictionaries
- Production: Replace with PostgreSQL/MongoDB
- Persistence: Add database layer for user balances and positions
- Scalability: Current implementation supports demo/testing
- Algorithm: LMSR (Logarithmic Market Scoring Rule)
- Liquidity Parameter: b = 100 (adjustable)
- Price Calculation:
price = exp(shares/b) / (exp(yes/b) + exp(no/b)) - Cost Function: Binary search to determine shares for given amount
- Triggers when game score is finalized
- Winning shares worth 100 tokens
- Losing shares worth 0 tokens
- Automatic payout to user balance (future feature)
- The project uses
.venvfor the Python virtual environment - Port 8000 is the default - ensure it's not in use by other applications
- Markets automatically close at scheduled game start time
- All "betting" terminology has been removed per prediction market standards
- Currency: "tokens" (πͺ) - GT-themed virtual currency
- Frontend built with Vue 3 Composition API for reactive state management
All systems tested and operational:
- User creation with 10,000 token starting balance
- Market creation from IMLeagues game data
- LMSR pricing algorithm functioning correctly
- Trade execution and share calculations
- Portfolio tracking (open & settled positions)
- Market lifecycle (open β closed β settled)
- Automatic settlement based on final scores
- Frontend prediction interface
- Real-time price updates
- Mobile-responsive design
- Database persistence (PostgreSQL)
- User authentication & accounts
- Leaderboard system
- Historical performance tracking
- Mobile app (React Native)
- Push notifications for market settlements
- Live game updates integration
- Advanced charting for price history
- Social features (following users, sharing predictions)
- Tournament mode with prizes