Skip to content
oxyboron25Public

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Repository files navigation

TradeSim — Virtual Stock Trading & Portfolio Analytics Platform

A full-stack virtual stock trading platform with a transaction-safe trading engine, Redis-cached live market data, Celery background workers, and REST APIs. Built for scale — the architecture supports thousands of concurrent users in simulated trading competitions.

Architecture

                Browser (HTML/Bootstrap/Chart.js)
                         │
                  Fetch / REST APIs
                         │
              ┌─────────────────────┐
              │  Django REST Framework │
              └──────────┬──────────┘
                         │
      ┌──────────────────┼──────────────────┐
      │                  │                   │
 Auth Service    Trading Engine      Portfolio Engine
 (JWT/Session)   (ACID trades)     (Real-time value)
      │                  │                   │
      └──────────────────┼───────────────────┘
                         │
              ┌──────────┴──────────┐
              │   Analytics Engine   │
              │  (returns, sectors,  │
              │   leaderboard)       │
              └──────────┬──────────┘
                         │
              ┌──────────┴──────────┐
              │  Stock Price Service │
              │  (Redis cache layer) │
              └──────────┬──────────┘
                         │
              ┌──────────┴──────────┐
              │    PostgreSQL DB     │
              └──────────┬──────────┘
                         │
              ┌──────────┴──────────┐
              │  Redis + Celery     │
              │  (cache + workers)  │
              └──────────┬──────────┘
                         │
              ┌──────────┴──────────┐
              │  Yahoo Finance API  │
              │  (live market data) │
              └─────────────────────┘

Database Schema

┌─────────────┐    ┌──────────────┐    ┌──────────────────┐
│    users     │    │   stocks     │    │    holdings       │
├─────────────┤    ├──────────────┤    ├──────────────────┤
│ id (PK)     │◄──┐│ id (PK)      │◄──┐│ id (PK)          │
│ username    │   ││ symbol (UQ)  │   ││ user_id (FK)     │
│ email       │   ││ company      │   ││ stock_id (FK)    │
│ cash_balance│   ││ sector       │   ││ quantity         │
└─────────────┘   ││ exchange     │   ││ avg_buy_price    │
                  │└──────────────┘   │└──────────────────┘
┌─────────────────┐                  │                     
│  transactions   │                  │    ┌──────────────────┐
├─────────────────┤                  │    │ portfolio_snapshots│
│ id (PK)         │                  │    ├──────────────────┤
│ user_id (FK)    │◄─────────────────┘    │ id (PK)          │
│ stock_id (FK)   │◄──────────────────────┤ user_id (FK)     │
│ type (BUY/SELL) │                       │ date             │
│ price           │                       │ portfolio_value  │
│ quantity        │                       │ cash_balance     │
│ timestamp (idx) │                       │ holdings_value   │
└─────────────────┘                       └──────────────────┘

Project Structure

TradeSim/
├── accounts/          # User model, registration, JWT auth
├── stocks/            # Stock model, search, price endpoints
├── portfolio/         # Holdings, portfolio snapshots
├── transactions/      # Buy/sell execution, trade history
├── watchlist/         # User watchlist management
├── leaderboard/       # Rankings by portfolio value
├── news/              # Market news from Yahoo Finance
├── alerts/            # Price threshold alerts
├── services/          # Business logic layer
│   ├── trading.py     #   ACID trade execution
│   ├── portfolio.py   #   Portfolio valuation & allocation
│   ├── stock.py       #   Price fetching with Redis cache
│   ├── analytics.py   #   Dashboard & leaderboard
│   └── tasks.py       #   Celery background workers
├── api/               # URL routing for all endpoints
├── core/              # Django settings, Celery config, WSGI
├── docker/            # Nginx config
├── Dockerfile
├── docker-compose.yml
└── requirements.txt

API Endpoints

Authentication

Method Endpoint Description
POST /api/auth/register/ Create account
POST /api/auth/login/ Get JWT tokens
POST /api/auth/refresh/ Refresh access token
GET /api/auth/profile/ Get user profile

Stocks

Method Endpoint Description
GET /api/stocks/ List known stocks
GET /api/stocks/search/?q=APP Search by symbol/name
GET /api/stocks/{symbol}/price/ Get current price

Trading

Method Endpoint Description
POST /api/transactions/buy/ Buy stocks (ACID)
POST /api/transactions/sell/ Sell stocks (ACID)
GET /api/transactions/ Trade history

Portfolio

Method Endpoint Description
GET /api/portfolio/ Holdings + performance + allocation
GET /api/portfolio/history/?days=30 Daily portfolio snapshots
GET /api/dashboard/ Aggregated dashboard data

Other

Method Endpoint Description
GET/POST/DELETE /api/watchlist/ Manage watchlist
GET /api/leaderboard/ Top 100 users
GET /api/news/ Latest market news
GET/POST /api/alerts/ Price alerts

Interesting Engineering Decisions

ACID-Compliant Trades

Buy/sell operations use transaction.atomic() with select_for_update() on holdings to prevent race conditions. A buy never partially succeeds.

with db_transaction.atomic():
    self.user.cash_balance -= total_cost
    self.user.save(update_fields=["cash_balance"])
    holding = Holding.objects.select_for_update().get_or_create(...)
    holding.quantity += quantity
    holding.avg_buy_price = recalculated_average
    holding.save()
    Transaction.objects.create(...)

Redis Caching Layer

Without caching, 1000 users checking their portfolio would trigger 1000 Yahoo Finance API calls. With Redis:

  • Stock prices cached for 60 seconds (configurable via STOCK_PRICE_CACHE_TTL)
  • Batch fetching: uncached symbols fetched once, served to all users
  • Search results cached for 1 hour
  • Rate-limited Yahoo Finance access (5 calls per 60 seconds)

Service Layer

Business logic lives in services/ — not in views. This means:

  • Views are thin: parse request → call service → return response
  • Services are testable independently
  • The same service can be reused in views, Celery tasks, or management commands

Celery Background Workers

  • sync_stock_prices (every 60s): Pre-warms Redis cache for all known stocks
  • take_portfolio_snapshots (midnight): Records daily portfolio value for historical charts
  • check_price_alerts (every 60s): Triggers user-defined price alerts

Database Indexing

Strategic indexes on user_id + timestamp (for trade history queries), symbol (for stock lookups), and user_id + stock_id (for portfolio queries) ensure sub-millisecond lookups even with millions of rows.

Quick Start

# Clone and enter
git clone <repo> && cd TradeSim

# Copy env and edit secrets
cp .env.example .env

# Start everything
docker compose up --build

# Run migrations
docker compose exec web python manage.py migrate

# Create a test user
docker compose exec web python manage.py shell -c "
from accounts.models import User
User.objects.create_user('demo', password='demo1234')
"

# Open browser
open http://localhost:8000/api/docs/

Deployment

# Production build
DJANGO_DEBUG=False docker compose -f docker-compose.yml up -d

# Scale workers
docker compose up -d --scale celery_worker=4

Future Work

  • WebSocket real-time price updates
  • Real-time leaderboard
  • Paper trading competitions with configurable start balances
  • Social features (follow traders, copy trades)
  • Advanced charting (moving averages, RSI, MACD)
  • CSV import/export for trade history
  • Rate limiting per user on API endpoints

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages