Files
Cerbero-Bite/docker-compose.yml
T
root 21e865ffb0 feat(gui+infra): pagina Strategia, P/L parametrico, profili Conservativa/Aggressiva, dashboard via Traefik
Espone la GUI Streamlit su https://cerbero-bite.tielogic.xyz tramite il
Traefik già attivo sull'host (label allineate al pattern di cerbero-mcp,
TLS via Let's Encrypt, websocket pass-through). Aggiunge:

- nuova tab `📚 Strategia` con stato live dei gate §2 confrontati con
  l'ultimo tick di market_snapshots, pannello P/L parametrico
  affiancato Conservativa vs Aggressiva, tabella di sensibilità
  win-rate → APR e rendering del documento canonico esteso.
- doc `13-strategia-spiegata.md` che lega ogni regola §2-§9 al campo di
  market_snapshots che la alimenta, con sezioni §4-bis (P/L atteso
  realistico, win-rate empirico, drawdown, Sharpe) e §4-ter (confronto
  fra i due profili e quando passare dall'uno all'altro).
- `strategy.conservativa.yaml` (golden config v1.0.0 esplicita) e
  `strategy.aggressiva.yaml` (cap_per_trade 4×, max_concurrent 2×,
  max_contracts 4×, deroga §11 documentata) con config_hash validi.
- nel compose: servizio dedicato `cerbero-bite-gui` (Streamlit su
  0.0.0.0:8765, healthcheck su /_stcore/health, label Traefik), env
  condivisi via anchor YAML `x-bite-env`, `--environment mainnet`
  passato a `start` per allineare il boot check al token del .env (era
  testnet vs mainnet → kill switch armato all'avvio).
- Dockerfile installa anche l'extra `gui` (streamlit) e copia
  `docs/` + i due nuovi profili nell'immagine; `.dockerignore` non
  esclude più `docs/` (causa del primo build silenzioso).

Fix bonus: `_try_load` nella pagina ritornava `LoadedConfig` ma la GUI
leggeva `.sizing.*` direttamente — l'`except: pass` mascherava
l'AttributeError facendo cadere sui default conservativi sia nel
pannello P/L sia nello stato gate (stesso pattern presente nella
Calibrazione). Ora ritorna `.config`.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-01 18:20:23 +00:00

133 lines
5.1 KiB
YAML

# docker-compose.yml — Cerbero Bite
#
# Bite runs in its own Compose project but joins the same Docker
# network used by Cerbero MCP V2 and Traefik (`traefik`) so it can
# either resolve the in-cluster service name (`cerbero-mcp:9000`)
# or reach the public gateway (`https://cerbero-mcp.tielogic.xyz`)
# transparently.
#
# The reverse-proxy network (`traefik`) is declared as external
# here. It is created by the Traefik stack at /opt/docker/traefik
# and shared by every web-facing service on the host.
#
# Authentication: a single bearer token is passed through from the
# host `.env` file via `CERBERO_BITE_MCP_TOKEN`. The Cerbero MCP V2
# server uses the token to decide whether the upstream environment
# is testnet or mainnet; switching environment = switching token.
#
# Two services are defined:
# * `cerbero-bite` — the trading engine / CLI worker
# * `cerbero-bite-gui` — the Streamlit dashboard, exposed by
# Traefik at https://cerbero-bite.<DOMAIN>
networks:
traefik:
external: true
volumes:
bite-data:
x-bite-env: &bite-env
CERBERO_BITE_MCP_TOKEN: ${CERBERO_BITE_MCP_TOKEN:?missing CERBERO_BITE_MCP_TOKEN}
CERBERO_BITE_MCP_BOT_TAG: ${CERBERO_BITE_MCP_BOT_TAG:-BOT__CERBERO_BITE}
# Two independent runtime flags that decide what each cycle does.
# Initial period ("data-only"): DATA_ANALYSIS=true, STRATEGY=false.
CERBERO_BITE_ENABLE_DATA_ANALYSIS: ${CERBERO_BITE_ENABLE_DATA_ANALYSIS:-true}
CERBERO_BITE_ENABLE_STRATEGY: ${CERBERO_BITE_ENABLE_STRATEGY:-false}
# Service URLs — defaults below match the in-cluster Traefik network
# DNS (V2 unified image listening on port 9000). Override any of
# them via .env to point at the public gateway, a custom host, or
# localhost for dev work.
CERBERO_BITE_MCP_DERIBIT_URL: ${CERBERO_BITE_MCP_DERIBIT_URL:-http://cerbero-mcp:9000/mcp-deribit}
CERBERO_BITE_MCP_HYPERLIQUID_URL: ${CERBERO_BITE_MCP_HYPERLIQUID_URL:-http://cerbero-mcp:9000/mcp-hyperliquid}
CERBERO_BITE_MCP_MACRO_URL: ${CERBERO_BITE_MCP_MACRO_URL:-http://cerbero-mcp:9000/mcp-macro}
CERBERO_BITE_MCP_SENTIMENT_URL: ${CERBERO_BITE_MCP_SENTIMENT_URL:-http://cerbero-mcp:9000/mcp-sentiment}
services:
cerbero-bite:
build:
context: .
dockerfile: Dockerfile
image: cerbero-bite:dev
restart: unless-stopped
networks: [traefik]
cap_drop: [ALL]
security_opt:
- no-new-privileges:true
environment:
<<: *bite-env
# Telegram and Portfolio are no longer shared MCP services. The
# bot now calls the Telegram Bot API directly and aggregates
# portfolio in-process from Deribit + Hyperliquid + Macro.
# Set the two env vars below to enable Telegram notifications.
# CERBERO_BITE_TELEGRAM_BOT_TOKEN: ...
# CERBERO_BITE_TELEGRAM_CHAT_ID: ...
volumes:
- bite-data:/app/data
healthcheck:
test:
["CMD", "cerbero-bite", "healthcheck", "--db", "/app/data/state.sqlite"]
interval: 60s
timeout: 5s
retries: 3
start_period: 120s
# Engine main loop (scheduler + monitoring). Switch to `status`,
# `ping`, `dry-run`, ... for one-shot diagnostics. The MCP token in
# `.env` decides the upstream environment server-side; the `start`
# flag below tells the local boot check what to expect (must match,
# otherwise the engine arms the kill switch).
command: ["start", "--environment", "mainnet"]
# Streamlit dashboard published by Traefik on
# https://cerbero-bite.${DOMAIN_NAME:-tielogic.xyz}
#
# The CLI sub-command `cerbero-bite gui` hard-codes the listen
# address to 127.0.0.1, so we bypass the entrypoint and invoke
# Streamlit directly. The two `CERBERO_BITE_GUI_*` env vars match
# what the CLI normally injects (see src/cerbero_bite/cli.py).
cerbero-bite-gui:
image: cerbero-bite:dev
restart: unless-stopped
depends_on:
- cerbero-bite
networks: [traefik]
cap_drop: [ALL]
security_opt:
- no-new-privileges:true
environment:
<<: *bite-env
CERBERO_BITE_GUI_DB: /app/data/state.sqlite
CERBERO_BITE_GUI_AUDIT: /app/data/log/audit.jsonl
volumes:
- bite-data:/app/data
entrypoint:
- python
- -m
- streamlit
- run
- /app/src/cerbero_bite/gui/main.py
- --server.address=0.0.0.0
- --server.port=8765
- --server.headless=true
- --browser.gatherUsageStats=false
command: []
healthcheck:
test:
- "CMD"
- "python"
- "-c"
- "import urllib.request; urllib.request.urlopen('http://127.0.0.1:8765/_stcore/health', timeout=3).close()"
interval: 30s
timeout: 5s
retries: 3
start_period: 30s
labels:
- traefik.enable=true
- traefik.docker.network=traefik
- "traefik.http.routers.cerbero-bite.rule=Host(`cerbero-bite.${DOMAIN_NAME:-tielogic.xyz}`)"
- traefik.http.routers.cerbero-bite.tls=true
- traefik.http.routers.cerbero-bite.entrypoints=websecure
- traefik.http.routers.cerbero-bite.tls.certresolver=mytlschallenge
- traefik.http.services.cerbero-bite.loadbalancer.server.port=8765
- com.centurylinklabs.watchtower.enable=true