Skip to content

Tyler-Irving/kalshi-weather-arbitrage-dashboard

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

4 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Kalshi Weather Trading Dashboard

A professional, real-time monitoring and analytics platform for automated weather prediction market trading on Kalshi. Built with React 19, Django 4.2, and WebSockets for seamless live updates.

This dashboard provides comprehensive visibility into trading performance, position management, P&L analytics, and reliability metrics—all through a clean, responsive interface powered by the Frost design system.

Overview

The Kalshi Weather Trading Dashboard is designed to monitor and analyze automated trading activity from the Kalshi Weather Arbitrage Bot. It reads structured data files (JSON, JSONL, and text logs) generated by the trading daemon and presents them through an intuitive web interface with real-time updates via WebSockets.

Key Capabilities:

  • Live Position Tracking: Monitor all active positions with ensemble forecast details, edge calculations, and settlement dates
  • P&L Analytics: Daily, weekly, and total profit/loss tracking with interactive charts and city-level breakdowns
  • Backtest Analysis: Review every trade opportunity the bot evaluated—what was traded, what was skipped, and why
  • Reliability Metrics: 27 analytics endpoints measuring win rates, edge calibration, provider accuracy, and cost efficiency
  • Paper Trading Monitor: Track simulated trades separately from live positions
  • WebSocket Log Streaming: Real-time log tailing with color-coded formatting and automatic scroll
  • Health Monitoring: Daemon status indicators, staleness detection, and circuit breaker alerts

Features

Core Dashboard

  • Real-time Status Panel: Balance, daily P&L, position count, daemon health indicator
  • Position Table: All active positions with city, side, strike, edge, confidence, cost, and settlement date
  • P&L Chart: Interactive time-series visualization of daily profit/loss with hover details
  • City Heatmap: Geographical performance breakdown showing which cities are most profitable
  • Backtest Log Viewer: Paginated table of all evaluated opportunities with filters for date, city, and action

Analytics Suite (27 Endpoints)

  • Win Rate Analysis: Breakdown by city, side (yes/no), confidence bucket, and edge bracket
  • Edge Calibration: Verify that predicted edges match actual win rates (calibration curve)
  • Confidence Calibration: Assess whether forecast confidence scores are well-calibrated
  • Bias Detection: Measure systematic over/under-estimation of edges
  • Provider Accuracy: Compare performance across NOAA, GFS, ICON, ECMWF, and GEM forecast providers
  • Staleness Impact: Quantify win rate degradation when NOAA forecasts are stale
  • Dropout Analysis: Performance when provider count drops (missing data scenarios)
  • Cost Efficiency: ROI by edge bucket, average profit per trade, break-even win rate
  • Streak Tracking: Current and longest winning/losing streaks

Paper Trading Integration

  • Separate Tab: Dedicated view for paper trades (simulated positions)
  • Trade History: All paper trades with timestamps, edge, confidence, and cost
  • Summary Metrics: Total paper trades, total cost, cities traded, average edge/confidence
  • Side Distribution: Breakdown of yes/no paper trades

User Experience

  • Frost Design System: Clean, modern UI with Tailwind CSS v4 and consistent color palette
  • Responsive Layout: Optimized for desktop (1920px+), laptop (1440px), and tablet (1024px+)
  • Dark Mode Ready: Color scheme designed for low-light environments (future enhancement)
  • Toast Notifications: Non-intrusive alerts for daemon status changes and data refresh events
  • Settings Drawer: Configure API endpoint, enable/disable WebSocket logs, adjust refresh intervals

Tech Stack

Frontend

  • React 19.0: Latest React with Concurrent Mode and automatic batching
  • TypeScript 5.6: Full type safety across components, stores, and API calls
  • Vite 6.0: Lightning-fast HMR (Hot Module Replacement) and optimized production builds
  • Tailwind CSS 4.0: Utility-first styling with custom Frost theme configuration
  • Zustand 5.0: Lightweight state management for dashboard data and UI state
  • Recharts 3.7: Declarative charting library for P&L and analytics visualizations
  • Axios 1.7: Promise-based HTTP client with interceptors for error handling

Backend

  • Django 4.2: Robust Python web framework with ORM and middleware support
  • Django REST Framework 3.14: RESTful API toolkit with serializers and viewsets
  • Django Channels 4.0: WebSocket support with ASGI protocol server (Daphne)
  • Daphne 4.0: HTTP/WebSocket ASGI server for production deployment
  • Python 3.10+: Modern Python with async/await and type hints

Real-time Communication

  • WebSockets: Bi-directional communication for log streaming
  • ASGI Protocol: Async server gateway interface for handling HTTP and WebSocket connections
  • Redis (optional): Channel layer backend for horizontal scaling (future enhancement)

Data Sources

  • File-based Architecture: No database required—reads directly from daemon output files
  • JSONL Format: Append-only log files for backtests, settlements, and paper trades
  • JSON State Files: kalshi_unified_state.json, kalshi_pnl.json for current status
  • Text Logs: kalshi_unified_log.txt for real-time log streaming

Screenshots

Main Dashboard

The primary view displays live positions in a sortable table with ensemble forecast details, a P&L chart showing daily performance trends, and a city heatmap highlighting geographic profitability. The status panel at the top shows current balance, today's P&L, active position count, and daemon health indicator (green dot when running, red when stale).

Backtest Analysis

The backtest tab presents a paginated log of all evaluated trading opportunities. Each row shows the timestamp, city, action (trade/skip), skip reason, edge, confidence, market price, and ensemble forecast. Filters allow narrowing by date, city, or action type. Summary stats display the funnel: opportunities scanned → traded → skipped (with reason breakdown).

Paper Trading Monitor

A dedicated view for simulated trades shows all paper positions with normalized schema (compatible with two historical formats). The summary panel displays total paper trades, aggregate cost, cities traded, and average edge/confidence. A side distribution chart shows yes/no trade balance.

Analytics Dashboard (Future)

A planned enhancement will add a visual analytics suite displaying calibration curves, provider accuracy comparisons, and reliability metrics in chart form. Currently, these 27 endpoints are accessible via REST API.

Settings Drawer

A slide-out panel allows configuring the backend API URL (useful for remote daemon monitoring), enabling/disabling WebSocket log streaming, and adjusting auto-refresh intervals for position and P&L data.

Quick Start

Prerequisites

  • Python 3.10+ (3.11 or 3.12 recommended)
  • Node.js 18+ (20.x LTS recommended)
  • Trading Daemon: The Kalshi Weather Bot must be running and generating data files

1. Clone Repository

git clone https://github.com/Tyler-Irving/kalshi-dashboard.git
cd kalshi-dashboard

2. Backend Setup

cd backend

# Create virtual environment
python3 -m venv venv
source venv/bin/activate  # On Windows: venv\Scripts\activate

# Install dependencies
pip install -r requirements.txt

# Create .env file
cp .env.example .env
nano .env  # Edit configuration (see below)

# Generate SECRET_KEY
python manage.py generate_secret_key

# Run migrations (optional, no DB required but good practice)
python manage.py migrate

# Start development server
python manage.py runserver 0.0.0.0:8000

Backend .env Configuration:

SECRET_KEY=your-generated-secret-key-here
DEBUG=false
ALLOWED_HOSTS=localhost,127.0.0.1
CORS_ALLOWED_ORIGINS=http://localhost:5173,http://127.0.0.1:5173

# Path to daemon data files
TRADING_DIR=../../kalshi-weather-bot

# Path to daemon codebase (for optional integrations)
KALSHI_DAEMON_DIR=../../kalshi-weather-bot

# API credentials directory (optional, for future enhancements)
KALSHI_SECRETS_DIR=~/.openclaw/.secrets

Important: TRADING_DIR must point to the directory containing:

  • kalshi_unified_state.json
  • kalshi_pnl.json
  • kalshi_unified_log.txt
  • kalshi_backtest_log.jsonl
  • kalshi_settlement_log.jsonl
  • paper_trades.jsonl

3. Frontend Setup

cd ../frontend

# Install dependencies
npm install

# Start development server
npm run dev

The frontend will open at http://localhost:5173 and automatically proxy API requests to http://localhost:8000.

4. Access Dashboard

Open your browser to:

http://localhost:5173

You should see:

  • Status Panel: Balance, P&L, position count (data from kalshi_unified_state.json)
  • Position Table: Active positions (may be empty if no trades are open)
  • P&L Chart: Daily performance (populated if daemon has been running)
  • Logs Tab: Real-time log streaming via WebSocket

Troubleshooting Quick Start:

  • "API Error": Verify backend is running on port 8000 and CORS_ALLOWED_ORIGINS includes http://localhost:5173
  • "No Positions": This is normal if the trading bot hasn't opened any positions yet
  • "Daemon Offline": The health indicator shows red if kalshi_unified_log.txt hasn't been modified in 20+ minutes
  • "WebSocket Disconnected": Check that Daphne/Channels is running (not just Django runserver)

Architecture

System Overview

The dashboard follows a file-reader architecture where the backend acts as a REST API gateway to structured files generated by the trading daemon. There is no database—all data is read on-demand from JSON, JSONL, and text files.

Trading Daemon (kalshi_unified.py)
    ↓ Writes files every 15 minutes
[Data Files: JSON, JSONL, TXT]
    ↓ Read by Django views
Django REST API (7 core endpoints, 27 analytics)
    ↓ HTTP/WebSocket
React Frontend (Zustand state management)
    ↓ Renders
Browser (User)

Key Components:

  1. Trading Daemon: Autonomous bot running as a background process, polling Kalshi API and weather providers
  2. Data Files: Append-only logs (JSONL) and overwrite-on-update state files (JSON)
  3. Django Backend: Stateless API server reading files and serving REST endpoints
  4. WebSocket Server: Daphne/Channels for real-time log streaming
  5. React Frontend: SPA (Single Page Application) with client-side routing and Zustand stores

Data Flow

Daemon → Files → Backend → Frontend

  1. Daemon Writes: Every poll cycle (15 minutes), the daemon:

    • Updates kalshi_unified_state.json (positions, balance, daily trades)
    • Appends to kalshi_backtest_log.jsonl (all evaluated opportunities)
    • Appends to kalshi_settlement_log.jsonl (when positions settle)
    • Updates kalshi_pnl.json (daily/weekly P&L aggregations)
    • Appends to kalshi_unified_log.txt (timestamped log entries)
  2. Backend Reads: On each API request:

    • file_readers.py opens files, parses JSON/JSONL, and returns Python dicts
    • Views aggregate, filter, and format data into REST responses
    • No caching—always fresh data (appropriate for 15-minute update cycles)
  3. Frontend Fetches: React components:

    • Call Axios-wrapped API methods from src/config/api.ts
    • Store responses in Zustand stores (dashboardStore, paperStore)
    • Re-render components when store state changes
    • Poll critical endpoints (status, positions) every 10 seconds
  4. WebSocket Push: For log streaming:

    • Daphne opens WebSocket connection at /ws/logs/
    • Consumer (LogConsumer) tails kalshi_unified_log.txt and pushes new lines
    • Frontend receives and appends to scrollable log viewer

Backend Architecture

Django Apps:

  • config/: Project settings, ASGI/WSGI configuration, root URL routing
  • dashboard/: Core REST API views, file readers, analytics engine, WebSocket consumers
  • kalshi/: (Optional) Future integration for live Kalshi API calls

Key Modules:

  • dashboard/views.py: 20+ REST API endpoints (status, positions, P&L, backtest, analytics)
  • dashboard/file_readers.py: FileReader class with JSON/JSONL parsers, log tailing, mtime checks
  • dashboard/analytics.py: ReliabilityAnalytics class for 27 analytics endpoints (win rates, calibration, bias)
  • dashboard/consumers.py: LogConsumer WebSocket handler for real-time log streaming
  • dashboard/routing.py: WebSocket URL routing (separate from HTTP routes)

File Reader Design:

  • Singleton Pattern: Single FileReader instance configured with TRADING_DIR from .env
  • On-demand Parsing: Files are read and parsed on each request (no caching)
  • Error Handling: Returns empty dicts/arrays if files missing or malformed
  • Performance: JSONL files filtered by date to limit memory usage (e.g., only today's backtests)

Frontend Architecture

Component Structure:

src/
├── main.tsx                 # Entry point, React root
├── App.tsx                  # Root component, routing logic
├── config/
│   └── api.ts               # Axios instance, API method wrappers
├── stores/
│   ├── dashboardStore.ts    # Zustand store for positions, P&L, status
│   └── paperStore.ts        # Zustand store for paper trades
├── components/
│   ├── layout/
│   │   ├── Header.tsx       # Top banner with app title
│   │   └── NavBar.tsx       # Tab navigation
│   ├── PositionsTable.tsx   # Sortable table of active positions
│   ├── PnLChart.tsx         # Recharts area chart for daily P&L
│   ├── PnLPanel.tsx         # Summary cards: balance, P&L, win rate
│   ├── CityHeatmap.tsx      # Color-coded city performance grid
│   ├── BacktestStats.tsx    # Funnel stats for backtest log
│   ├── HeroBanner.tsx       # Large status panel with daemon health
│   ├── SettingsDrawer.tsx   # Slide-out settings panel
│   ├── ErrorBanner.tsx      # Error notifications
│   └── AlertBanner.tsx      # Info/warning banners
└── types/
    ├── position.ts          # TypeScript interfaces for positions
    ├── pnl.ts               # P&L data types
    ├── backtest.ts          # Backtest entry types
    └── paper.ts             # Paper trade types

State Management:

  • Zustand Stores: Lightweight, hook-based state containers (no Context API overhead)
  • Store Pattern: Each store has:
    • State fields (e.g., positions, pnl, loading, error)
    • Actions (e.g., fetchPositions(), refreshPnL())
    • Computed selectors (e.g., getTotalPnL())
  • Polling Logic: useEffect hooks in components trigger fetch actions on mount and intervals

Routing:

  • Client-side Routing: Simple tab-based navigation (no React Router—just conditional rendering)
  • Tabs: Dashboard, Backtest, Paper Trades, Analytics (future), Settings
  • URL Sync: (Optional future enhancement) Sync tab state to URL hash

Real-time Communication

WebSocket Flow:

  1. Frontend connects: new WebSocket('ws://localhost:8000/ws/logs/')
  2. Daphne routes to LogConsumer.connect()
  3. Consumer spawns background task that tails kalshi_unified_log.txt
  4. On new lines detected (via mtime polling):
    • Consumer sends JSON message: {"type": "log_line", "line": "...", "timestamp": "..."}
  5. Frontend appends line to scrollable <div>, auto-scrolls to bottom
  6. Disconnect: Consumer cancels background task, closes file handle

WebSocket Reconnection:

  • Frontend implements exponential backoff reconnection (1s, 2s, 4s, 8s, max 30s)
  • Shows "Reconnecting..." indicator in log viewer
  • Automatically resumes streaming when connection restored

Configuration

Backend Environment Variables

All configuration is via .env file in backend/ directory.

Security:

SECRET_KEY=                  # REQUIRED: Generate with `python manage.py generate_secret_key`
DEBUG=false                  # Set to true only for local development (exposes stack traces)
ALLOWED_HOSTS=localhost,127.0.0.1  # Comma-separated hostnames (add your domain for production)

CORS (Cross-Origin Resource Sharing):

CORS_ALLOWED_ORIGINS=http://localhost:5173,http://127.0.0.1:5173
# Add production frontend URL:
# CORS_ALLOWED_ORIGINS=http://localhost:5173,https://dashboard.example.com

Data Source Paths:

TRADING_DIR=../../kalshi-weather-bot
# Absolute paths work too:
# TRADING_DIR=/home/user/trading/kalshi-weather-bot

KALSHI_DAEMON_DIR=../../kalshi-weather-bot
# Used for optional integrations (currently unused)

KALSHI_SECRETS_DIR=~/.openclaw/.secrets
# Path to kalshi.json and kalshi_private.pem (for future API features)

Logging:

LOG_LEVEL=INFO
# Options: DEBUG, INFO, WARNING, ERROR, CRITICAL
# DEBUG logs all SQL queries and API calls (verbose)

Database (Optional):

# Currently unused (file-based architecture)
# Future enhancement: cache analytics results in PostgreSQL
# DATABASE_URL=postgresql://user:pass@localhost:5432/kalshi_dashboard

Frontend Environment Variables

Frontend configuration is via src/config/api.ts (no .env file needed for development).

API Endpoint:

const API_BASE_URL = import.meta.env.VITE_API_URL || 'http://localhost:8000';

To override for production:

# In frontend/.env.production
VITE_API_URL=https://api.example.com

WebSocket URL:

const WS_BASE_URL = API_BASE_URL.replace('http', 'ws');
// Automatically converts http://localhost:8000 → ws://localhost:8000

File Reader Configuration

The FileReader class in backend/dashboard/file_readers.py is configured via TRADING_DIR environment variable.

Default File Locations:

TRADING_DIR = os.getenv('TRADING_DIR', '../trading')

FILES = {
    'kalshi_unified_state.json': f'{TRADING_DIR}/kalshi_unified_state.json',
    'kalshi_pnl.json': f'{TRADING_DIR}/kalshi_pnl.json',
    'kalshi_unified_log.txt': f'{TRADING_DIR}/kalshi_unified_log.txt',
    'kalshi_backtest_log.jsonl': f'{TRADING_DIR}/kalshi_backtest_log.jsonl',
    'kalshi_settlement_log.jsonl': f'{TRADING_DIR}/kalshi_settlement_log.jsonl',
    'paper_trades.jsonl': f'{TRADING_DIR}/paper_trades.jsonl',
}

Handling Missing Files:

  • Missing JSON files return {}
  • Missing JSONL files return []
  • Missing log files return [] (no crash—graceful degradation)

Development

Local Development Setup

Hot Reload (Both Servers):

# Terminal 1: Backend (Django auto-reloads on .py changes)
cd backend
source venv/bin/activate
python manage.py runserver

# Terminal 2: Frontend (Vite HMR on .tsx changes)
cd frontend
npm run dev

WebSocket Development: For WebSocket support in development, use Daphne instead of runserver:

cd backend
source venv/bin/activate
daphne -b 0.0.0.0 -p 8000 config.asgi:application

Code Style

Backend (Python):

  • Formatter: Black (line length 120)
  • Linter: Flake8
  • Type Hints: Encouraged but not enforced
# Format all Python files
black backend/

# Lint
flake8 backend/

Frontend (TypeScript/React):

  • Formatter: Prettier (2 spaces, single quotes)
  • Linter: ESLint (React hooks rules, TypeScript rules)
  • Style Guide: Airbnb React style guide (adapted)
# Lint
npm run lint

# Auto-fix
npm run lint -- --fix

Testing

Backend Tests:

cd backend
python manage.py test dashboard.tests

Test coverage includes:

  • File reader unit tests (mocked file I/O)
  • Analytics engine tests (edge calibration, win rate calculations)
  • API endpoint tests (response schema validation)

Frontend Tests: Currently no test suite (future enhancement: Vitest + React Testing Library).

Debugging

Backend Debugging:

# Enable DEBUG mode
echo "DEBUG=true" >> backend/.env

# View SQL queries (if using DB)
LOG_LEVEL=DEBUG python manage.py runserver

Frontend Debugging:

  • React DevTools extension (inspect component tree, props, state)
  • Zustand DevTools: Install zustand/middleware and enable Redux DevTools integration
import { devtools } from 'zustand/middleware';

export const useDashboardStore = create<DashboardState>()(
  devtools(
    (set) => ({
      // ...state and actions
    }),
    { name: 'DashboardStore' }
  )
);

WebSocket Debugging:

// In browser console
const ws = new WebSocket('ws://localhost:8000/ws/logs/');
ws.onmessage = (event) => console.log('WS:', JSON.parse(event.data));
ws.onerror = (error) => console.error('WS Error:', error);

Adding New Features

New REST Endpoint:

  1. Add view function to backend/dashboard/views.py:
@api_view(['GET'])
def my_new_view(request):
    data = file_reader.read_json('some_file.json')
    # Process data...
    return Response({'result': data})
  1. Add URL route to backend/dashboard/urls.py:
path('my-endpoint/', views.my_new_view, name='my-endpoint'),
  1. Add API call to frontend/src/config/api.ts:
export const fetchMyData = () => api.get('/api/v1/my-endpoint/');
  1. Use in component:
const [data, setData] = useState(null);

useEffect(() => {
  fetchMyData().then(response => setData(response.data));
}, []);

New WebSocket Consumer:

  1. Create consumer in backend/dashboard/consumers.py
  2. Add route to backend/dashboard/routing.py
  3. Connect from frontend:
const ws = new WebSocket('ws://localhost:8000/ws/my-channel/');
ws.onmessage = (event) => {
  const data = JSON.parse(event.data);
  // Handle message...
};

Deployment

Production Checklist

Before deploying to production:

  • Set DEBUG=false in backend/.env
  • Generate strong SECRET_KEY (64+ characters)
  • Configure ALLOWED_HOSTS with production domain
  • Set CORS_ALLOWED_ORIGINS to production frontend URL
  • Use HTTPS for both frontend and backend
  • Configure reverse proxy (Nginx or Caddy)
  • Set up systemd services for Daphne and Gunicorn
  • Configure log rotation for kalshi_unified_log.txt
  • Set up monitoring (health check endpoint at /api/v1/health/)
  • Build frontend with npm run build
  • Serve frontend static files via CDN or Nginx

Backend Deployment (Systemd + Nginx)

1. Install dependencies on server:

sudo apt update
sudo apt install python3.11 python3.11-venv nginx redis-server

2. Deploy backend code:

cd /opt
sudo git clone https://github.com/Tyler-Irving/kalshi-dashboard.git
cd kalshi-dashboard/backend
sudo python3.11 -m venv venv
sudo venv/bin/pip install -r requirements.txt

3. Configure .env:

sudo nano /opt/kalshi-dashboard/backend/.env
# Set production values (see Configuration section)

4. Create systemd service for Daphne:

# /etc/systemd/system/kalshi-dashboard.service
[Unit]
Description=Kalshi Dashboard (Daphne WebSocket Server)
After=network.target

[Service]
Type=simple
User=www-data
WorkingDirectory=/opt/kalshi-dashboard/backend
Environment="PATH=/opt/kalshi-dashboard/backend/venv/bin"
ExecStart=/opt/kalshi-dashboard/backend/venv/bin/daphne -b 127.0.0.1 -p 8000 config.asgi:application
Restart=always
RestartSec=10

[Install]
WantedBy=multi-user.target

5. Start and enable service:

sudo systemctl daemon-reload
sudo systemctl start kalshi-dashboard
sudo systemctl enable kalshi-dashboard
sudo systemctl status kalshi-dashboard

6. Configure Nginx reverse proxy:

# /etc/nginx/sites-available/kalshi-dashboard
upstream dashboard_backend {
    server 127.0.0.1:8000;
}

server {
    listen 80;
    server_name dashboard.example.com;

    # Redirect to HTTPS
    return 301 https://$host$request_uri;
}

server {
    listen 443 ssl http2;
    server_name dashboard.example.com;

    ssl_certificate /etc/letsencrypt/live/dashboard.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/dashboard.example.com/privkey.pem;

    # API and WebSocket proxy
    location /api/ {
        proxy_pass http://dashboard_backend;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location /ws/ {
        proxy_pass http://dashboard_backend;
        proxy_http_version 1.1;
        proxy_set_header Upgrade $http_upgrade;
        proxy_set_header Connection "upgrade";
        proxy_set_header Host $host;
        proxy_read_timeout 86400;  # 24 hours for long-lived WS connections
    }

    # Frontend static files
    location / {
        root /opt/kalshi-dashboard/frontend/dist;
        try_files $uri $uri/ /index.html;
    }
}

7. Enable site and reload Nginx:

sudo ln -s /etc/nginx/sites-available/kalshi-dashboard /etc/nginx/sites-enabled/
sudo nginx -t
sudo systemctl reload nginx

Frontend Deployment (Static Build)

1. Build production bundle:

cd /opt/kalshi-dashboard/frontend
VITE_API_URL=https://dashboard.example.com npm run build

2. Serve via Nginx (already configured above): The dist/ directory contains:

  • index.html (entry point)
  • assets/ (JS, CSS, images with hashed filenames)

3. Enable gzip compression:

# Add to nginx server block
gzip on;
gzip_types text/plain text/css application/json application/javascript text/xml application/xml+rss text/javascript;

Docker Deployment (Alternative)

docker-compose.yml:

version: '3.8'

services:
  backend:
    build: ./backend
    volumes:
      - ./backend/.env:/app/.env
      - /path/to/trading/data:/data
    ports:
      - "8000:8000"
    command: daphne -b 0.0.0.0 -p 8000 config.asgi:application

  frontend:
    build: ./frontend
    ports:
      - "80:80"
    depends_on:
      - backend

backend/Dockerfile:

FROM python:3.11-slim
WORKDIR /app
COPY requirements.txt .
RUN pip install --no-cache-dir -r requirements.txt
COPY . .
CMD ["daphne", "-b", "0.0.0.0", "-p", "8000", "config.asgi:application"]

frontend/Dockerfile:

FROM node:20 AS build
WORKDIR /app
COPY package*.json ./
RUN npm ci
COPY . .
RUN npm run build

FROM nginx:alpine
COPY --from=build /app/dist /usr/share/nginx/html
COPY nginx.conf /etc/nginx/conf.d/default.conf

Monitoring & Logging

Health Check Endpoint:

curl https://dashboard.example.com/api/v1/health/
# {"status": "ok", "timestamp": "2026-02-16T12:00:00"}

Systemd Logs:

sudo journalctl -u kalshi-dashboard -f

Nginx Access Logs:

tail -f /var/log/nginx/access.log

Application Logs: Django logs are sent to stdout (captured by systemd). To log to file:

# backend/config/settings.py
LOGGING = {
    'version': 1,
    'handlers': {
        'file': {
            'class': 'logging.FileHandler',
            'filename': '/var/log/kalshi-dashboard/app.log',
        },
    },
    'root': {
        'handlers': ['file'],
        'level': 'INFO',
    },
}

Security Considerations

Secret Key Rotation:

# Generate new SECRET_KEY
python manage.py generate_secret_key

# Update .env and restart
sudo systemctl restart kalshi-dashboard

HTTPS Enforcement:

  • Use Let's Encrypt for free SSL certificates: sudo certbot --nginx
  • Set SECURE_SSL_REDIRECT=True in Django settings for production
  • Enable HSTS headers in Nginx

CORS Restrictions:

  • Only whitelist your frontend domain in CORS_ALLOWED_ORIGINS
  • Do NOT use * wildcard in production

File Permissions:

  • Ensure TRADING_DIR files are readable by www-data user
  • Use chmod 640 for .env files (owner read/write, group read)

Troubleshooting

"API Error: Network Error"

Cause: Frontend cannot reach backend API.

Solutions:

  • Verify backend is running: curl http://localhost:8000/api/v1/health/
  • Check CORS_ALLOWED_ORIGINS includes frontend URL
  • Inspect browser console for CORS errors
  • Verify Nginx proxy configuration if using reverse proxy

"No Data Available"

Cause: Dashboard loads but shows empty tables/charts.

Solutions:

  • Check TRADING_DIR path in backend/.env points to daemon output directory
  • Verify daemon files exist: ls -la /path/to/trading/kalshi_unified_state.json
  • Check file permissions: sudo -u www-data cat /path/to/trading/kalshi_unified_state.json
  • Inspect backend logs: sudo journalctl -u kalshi-dashboard -n 50

"Daemon Offline" (Red Indicator)

Cause: kalshi_unified_log.txt mtime is >20 minutes old.

Solutions:

  • Verify daemon is running: ps aux | grep kalshi_unified
  • Check daemon logs for errors: tail -f /path/to/trading/kalshi_unified_log.txt
  • Restart daemon if crashed

"WebSocket Disconnected"

Cause: WebSocket connection to /ws/logs/ failed or dropped.

Solutions:

  • Verify Daphne is running (not Django runserver): systemctl status kalshi-dashboard
  • Check Nginx WebSocket proxy config (must include Upgrade and Connection headers)
  • Inspect browser console for WebSocket errors
  • Test WebSocket directly: wscat -c ws://localhost:8000/ws/logs/

"Position Table Shows Paper Trades"

Cause: Pre-TICK-020a bug where paper trades weren't filtered out.

Solution: This was fixed in TICK-020a. Update to latest version. If still occurring, verify paper_trade field exists in kalshi_unified_state.json position entries.

"Analytics Endpoints Return Empty Arrays"

Cause: No settlement data (trades haven't closed yet).

Solution: Analytics require settled trades logged in kalshi_settlement_log.jsonl. Wait for positions to settle (after market close on settlement date) and daemon to log settlements.

Frontend Build Fails

Cause: TypeScript type errors or missing dependencies.

Solutions:

# Clear node_modules and reinstall
rm -rf node_modules package-lock.json
npm install

# Check for type errors
npm run build

# If Tailwind CSS errors, verify tailwind.config.ts

High Memory Usage (Backend)

Cause: Large JSONL files being read into memory.

Solutions:

  • JSONL readers use date filters to limit rows (e.g., ?date=2026-02-16)
  • For very large logs (>100K lines), implement pagination in read_jsonl()
  • Archive old JSONL entries: split -l 10000 kalshi_backtest_log.jsonl backtest_archive_

Contributing

Contributions are welcome! Whether bug fixes, new features, documentation improvements, or analytics enhancements—your help is appreciated.

How to Contribute

1. Fork and Clone:

git clone https://github.com/YourUsername/kalshi-dashboard.git
cd kalshi-dashboard

2. Create Feature Branch:

git checkout -b feature/my-new-feature

3. Make Changes:

  • Follow code style guidelines (Black for Python, Prettier for TypeScript)
  • Add tests for new functionality
  • Update documentation if adding features

4. Test Locally:

# Backend tests
cd backend
python manage.py test

# Frontend lint
cd frontend
npm run lint

5. Commit with Clear Messages:

git add .
git commit -m "feat: Add city-level reliability metrics endpoint"

Follow Conventional Commits:

  • feat: New feature
  • fix: Bug fix
  • docs: Documentation changes
  • style: Code style (formatting, no logic change)
  • refactor: Code restructuring (no behavior change)
  • test: Adding tests
  • chore: Build process, dependencies

6. Push and Open PR:

git push origin feature/my-new-feature

Open a Pull Request on GitHub with:

  • Title: Brief description (e.g., "Add provider accuracy timeline chart")
  • Description: What changed, why, and any breaking changes
  • Screenshots: If UI changes
  • Testing: How you tested it

Bug Reports

Use the GitHub Issues page.

Good Bug Report Includes:

  • Title: Brief, specific (e.g., "P&L chart shows incorrect data for Feb 15")
  • Steps to Reproduce: Numbered list of actions leading to bug
  • Expected Behavior: What should happen
  • Actual Behavior: What actually happened
  • Environment: OS, Python version, Node version, browser
  • Screenshots/Logs: Error messages or console output

Feature Requests

Open an issue with [Feature Request] prefix.

Good Feature Request Includes:

  • Use Case: Why this feature is needed
  • Proposed Solution: How it might work
  • Alternatives Considered: Other approaches you thought about
  • Priority: How important is this to you?

Code Style

Python (Black + Flake8):

black backend/ --line-length 120
flake8 backend/ --max-line-length 120

TypeScript (Prettier + ESLint):

cd frontend
npm run lint -- --fix
npx prettier --write "src/**/*.{ts,tsx}"

Commit Hooks (Optional): Install pre-commit to auto-format on commit:

pip install pre-commit
pre-commit install

Pull Request Guidelines

  • One Feature Per PR: Easier to review and merge
  • Update CHANGELOG.md: Add entry under [Unreleased]
  • Add Tests: For new endpoints or components
  • Update Docs: If adding features, update README.md and API.md
  • Rebase on Main: Before opening PR, rebase to avoid merge conflicts
git fetch upstream
git rebase upstream/main

License

MIT License

Copyright (c) 2026 Tyler Irving

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.


Acknowledgments

  • Kalshi: Prediction market platform providing API access
  • Trading Daemon: This dashboard is designed to complement the Kalshi Weather Arbitrage Bot
  • Open Source Libraries: React, Django, Tailwind CSS, Recharts, Zustand, and the entire open source ecosystem

Project Status

Current Version: 1.0.0 (Initial Public Release)

Active Development: This project is actively maintained. Expect regular updates for:

  • New analytics visualizations
  • Performance optimizations
  • Additional WebSocket channels (position updates, P&L streaming)
  • Dark mode theme
  • Mobile responsive improvements

Roadmap (planned enhancements):

  • Dark mode toggle
  • Advanced filtering (date range picker, multi-city selection)
  • Export to CSV (positions, P&L, analytics)
  • Email/SMS alerts for trade events
  • Historical performance comparison (month-over-month)
  • Provider forecast accuracy timeline chart
  • Redis channel layer for horizontal scaling
  • PostgreSQL integration for analytics caching
  • Docker Compose production setup
  • Kubernetes deployment manifests

Support


Built with ❄️ by the Frost design system

Professional trading dashboard for Kalshi weather markets—real-time monitoring, analytics, and insights.

About

Dashboard that is used in tandem with the kalshi daemon to monitor results

Resources

License

Contributing

Stars

1 star

Watchers

0 watching

Forks

Releases

No releases published

Packages

 
 
 

Contributors