Server Config Generator

Fill in the form to generate server.json for your local trading engine. Save the output as scripts/server.json (or mount it into the Docker container at /cfg/server.json).

Server

Port
Auth cache TTL (s)
Backend URL (NestJS API)
SQLite DB path

For Docker, use /data/engine.db and mount -v engine-data:/data.

Symbols

NameIDMid price
Position cap
Position cap
Position cap
Position cap
Position cap
Position cap
Position cap
Position cap
Position cap
Position cap

IDs are internal — they must be unique positive integers. The engine spins up one matching shard per symbol. Position caps reject any external order whose worst-case fill would push the user past the configured limit; the in-process market maker is exempt.

In-process Market Maker

Posts symmetric Buy/Sell quotes around the configured mid for every symbol so the book has liquidity before any external bot connects.

Spread (bps)
Quote size
Refresh (ms)

News-driven bots

Gemini

Polls the backend's /news feed every poll_seconds, sends new headlines to Gemini for classification, and routes (symbol, direction, confidence) signals to one of three personas. Bots run in-process and are exempt from per-symbol position caps (same carve-out as the market maker).

Poll seconds
Gemini model
Gemini API key(or leave blank and set GEMINI_API_KEY env var)
momentum

Buys on bullish news, sells on bearish. Aggressive limit (50 bps cross) so the order takes liquidity from the MM book.

Size per signal
Confidence threshold (0.60)
Size jitter ±25%
Price jitter ±15 bps
Background trades every OFF
contrarian

Inverts the headline reaction — fades over-eager moves. Same execution profile as momentum, opposite side.

Size per signal
Confidence threshold (0.70)
Size jitter ±25%
Price jitter ±15 bps
Background trades every OFF
scalper

Same direction as momentum but passive (10 bps inside the spread) and half-size — sits on the book hoping to scalp a small revert.

Size per signal
Confidence threshold (0.65)
Size jitter ±30%
Price jitter ±8 bps
Background trades every OFF

server.json

{
  "server": {
    "port": 9090,
    "backend_url": "http://localhost:3010",
    "db_path": "./engine.db",
    "auth_cache_ttl_seconds": 300
  },
  "symbols": [
    {
      "name": "ES",
      "id": 1,
      "mid": 7400
    },
    {
      "name": "NKD",
      "id": 2,
      "mid": 67475
    },
    {
      "name": "NQ",
      "id": 3,
      "mid": 29678
    },
    {
      "name": "YM",
      "id": 4,
      "mid": 51608
    },
    {
      "name": "RTY",
      "id": 5,
      "mid": 2949
    },
    {
      "name": "SPY",
      "id": 6,
      "mid": 740
    },
    {
      "name": "EWJ",
      "id": 7,
      "mid": 92
    },
    {
      "name": "EWH",
      "id": 8,
      "mid": 22
    },
    {
      "name": "EWY",
      "id": 9,
      "mid": 197
    },
    {
      "name": "FEZ",
      "id": 10,
      "mid": 69
    }
  ],
  "market_maker": {
    "enabled": true,
    "spread_bps": 20,
    "size": 10,
    "refresh_ms": 5000,
    "track_trades": true
  },
  "news": {
    "poll_seconds": 30,
    "gemini_model": "gemini-2.5-flash",
    "gemini_api_key": "",
    "bots": [
      {
        "count": 0,
        "persona": "momentum",
        "size_per_signal": 5,
        "confidence_threshold": 0.6,
        "size_jitter_pct": 25,
        "price_offset_jitter_bps": 15,
        "noise_interval_seconds": 0
      },
      {
        "count": 0,
        "persona": "contrarian",
        "size_per_signal": 3,
        "confidence_threshold": 0.7,
        "size_jitter_pct": 25,
        "price_offset_jitter_bps": 15,
        "noise_interval_seconds": 0
      },
      {
        "count": 0,
        "persona": "scalper",
        "size_per_signal": 4,
        "confidence_threshold": 0.65,
        "size_jitter_pct": 30,
        "price_offset_jitter_bps": 8,
        "noise_interval_seconds": 0
      }
    ]
  }
}
Next steps
1. Save as server.json.
2a. Run bare: ./engine --config server.json
2b. Run via Docker: docker run -p 9090:9090 -v $(pwd)/server.json:/cfg/server.json:ro -v engine-data:/data bubbles-engine