Environment Isolation Architecture

CRITICAL: This document describes mandatory patterns for environment handling. Violating these patterns can cause staging to use production data or vice versa.

Core Principle: FAIL-FAST, NO DEFAULTS

The PQAP application follows a strict "fail-fast" pattern for environment configuration:

  1. No hardcoded defaults - Components must receive explicit configuration
  2. Fail loudly - Missing configuration raises clear errors at startup
  3. Validate early - Environment validation runs before any business logic

Valid Environments

Environment Database Config File Purpose
dev data/pqap_dev.db configs/dev.yaml Local development
staging data/pqap_staging.db configs/staging.yaml Pre-production testing
prod data/pqap.db configs/prod.yaml Production

Startup Validation

At startup, validate_environment() checks: 1. config.env is set and valid 2. config.db_path is set 3. Database filename matches expected pattern for environment

Code Patterns

WRONG (Don't do this)

# Hardcoded fallback - NEVER DO THIS
def __init__(self, env: str = "dev"):
    self.db_path = f"data/pqap_{env}.db"

CORRECT (Do this)

# Explicit requirement - ALWAYS DO THIS
def __init__(self, env: str):
    if env is None:
        raise ValueError("Environment is required")
    if env not in VALID_ENVIRONMENTS:
        raise ValueError(f"Invalid environment: {env}")
    self.env = env

Environment-Specific Database Configuration

The DatabaseExplorer class uses environment-specific database mappings:

DATABASES_BY_ENV = {
    "dev": {
        "pqap": {"path": "data/pqap_dev.db", ...},
        "market_history": {"path": "data/market_history.db", ...},
    },
    "staging": {
        "pqap": {"path": "data/pqap_staging.db", ...},
        "market_history": {"path": "data/market_history.db", ...},
    },
    "prod": {
        "pqap": {"path": "data/pqap.db", ...},
        "market_history": {"path": "data/market_history.db", ...},
    },
}

Adding New Environment-Aware Components

  1. Accept env or config as required parameter (no defaults)
  2. Validate the environment is valid
  3. Use environment-specific paths from configuration
  4. Add tests in tests/unit/test_env_isolation.py

Example Implementation

from core.env_validator import VALID_ENVIRONMENTS

class MyNewComponent:
    def __init__(self, env: str):
        """
        Initialize component.

        Args:
            env: Environment name (dev, staging, prod) - REQUIRED

        Raises:
            ValueError: If env is not provided or not valid
        """
        if env is None:
            raise ValueError(
                "FATAL: env parameter is required. "
                "Cannot initialize without explicit environment."
            )

        if env not in VALID_ENVIRONMENTS:
            raise ValueError(
                f"FATAL: Unknown environment '{env}'. "
                f"Must be one of: {list(VALID_ENVIRONMENTS)}"
            )

        self.env = env
        # ... rest of initialization

Testing

Run Environment Isolation Tests

python -m pytest tests/unit/test_env_isolation.py -v

What the Tests Verify

  1. Valid configurations pass - Dev/staging/prod with correct db paths work
  2. Missing configuration fails - Missing env or db_path raises ValueError
  3. Invalid environment fails - Typos like "production" instead of "prod" fail
  4. Cross-environment access fails - Dev using prod database raises error
  5. Components require explicit env - DatabaseExplorer and MetricsStorage fail without env
  6. Database mapping is correct - Each environment maps to its expected database

These tests MUST pass before any deployment.

Troubleshooting

Error: "config.env is not set"

Cause: Application started without environment configuration.

Fix: Ensure environment is specified via: - --env command line argument - PQAP_ENV environment variable - Configuration file

Error: "Database path mismatch"

Cause: Environment and database path don't match (e.g., staging trying to use dev database).

Fix: Check configuration files and ensure database paths match the environment.

Error: "env parameter is required"

Cause: Component instantiated without explicit environment.

Fix: Pass environment explicitly when creating component instances:

# Wrong
explorer = DatabaseExplorer()

# Correct
explorer = DatabaseExplorer(env="dev")

Security Implications

Environment isolation prevents:

  1. Accidental data corruption - Dev changes won't affect prod data
  2. Data leakage - Production data won't be exposed in dev environments
  3. Configuration drift - Each environment uses validated, environment-specific config
  4. Silent failures - Misconfigurations fail immediately with clear error messages
File Purpose
src/core/env_validator.py Environment validation logic
src/admin/database_explorer.py Environment-aware database browsing
src/tracking/storage.py Environment-aware metrics storage
tests/unit/test_env_isolation.py Environment isolation test suite

System Overview

Polymarket API

Market data source

Data Collector

Every 5 minutes

SQLite Database

Price history + trades

Strategy Engine

Signal generation

ML Model

XGBoost (72% acc)

Execution Engine

Paper trading

Dashboard

You are here!

Telegram

Alerts & updates

Trading Strategies

Each strategy looks for different market inefficiencies:

Dual Arbitrage Active

Finds when YES + NO prices don't add to 100%. Risk-free profit.

Mean Reversion Active

Buys when price drops too far from average, sells when it recovers.

Market Maker Active

Places bid/ask orders to capture the spread.

Time Arbitrage Active

Exploits predictable price patterns at certain hours.

ML Prediction Active

Uses machine learning to predict 6-hour price direction.

Value Betting Disabled

Finds underpriced outcomes based on implied probability.

Data Storage (Single Source of Truth)

All data lives on EC2. Local machines are for development only. The EC2 instance is the authoritative source for all market data, trades, and positions.
Database Purpose Location
market_history.db Price snapshots every 5 minutes (8.2 MB) EC2 (primary)
pqap_staging.db Trades, positions, P&L history EC2 (primary)
paper_trading_state.json Current portfolio state EC2 (primary)

Environment Architecture

EC2 (Production)

  • Runs 24/7
  • All databases live here
  • Executes all trades
  • Single source of truth

Local (Development)

  • For code changes only
  • Syncs code to EC2
  • No production data
  • Can be turned off

Environment Details

Component Details
Dashboard URL https://pqap.tailwindtech.ai
Server AWS EC2 (us-east-1)
SSL Let's Encrypt via Traefik
Mode Paper Trading (simulated)

How It Works (Simple Version)

1. Data Collection: Every 5 minutes, we fetch prices from Polymarket for 50 markets and save them to our database.

2. Analysis: Our strategies analyze this data looking for patterns - like prices that moved too far from normal, or markets where the math doesn't add up.

3. Signals: When a strategy finds an opportunity, it generates a "signal" - a recommendation to buy or sell.

4. Execution: The execution engine takes these signals and simulates trades (paper trading). Eventually, this will place real orders.

5. Monitoring: This dashboard shows you what's happening. Telegram sends alerts for important events.