Commit Graph

58 Commits

Author SHA1 Message Date
Adriano b5b96f959c Hardening round 2: healthcheck, audit anchor, return_4h, exec config, signals
Sei interventi MEDIA priorità sul sistema. 323 test pass, mypy strict
pulito, ruff clean.

1. Docker HEALTHCHECK + cerbero-bite healthcheck:
   - nuovo subcommand che esce 0 se kill_switch=0 e last_health_check
     entro --max-staleness-s (default 600s);
   - HEALTHCHECK direttiva nel Dockerfile (60s interval, 5s timeout,
     start_period 120s, retries 3);
   - healthcheck definition nel docker-compose.yml.

2. Audit hash chain anti-truncation:
   - migration 0002: nuova colonna system_state.last_audit_hash;
   - AuditLog accetta callback on_append, dependencies.py la wire al
     repository.set_last_audit_hash;
   - Orchestrator.boot verifica che il tail file matcha l'anchor
     persistito; mismatch → kill switch CRITICAL.

3. return_4h bootstrap da deribit get_historical:
   - quando dvol_history è vuoto _fetch_return_4h cade su
     deribit.historical_close (1h candle 4h fa);
   - alert LOW se anche il fallback fallisce.

4. execution.environment + execution.eur_to_usd in strategy.yaml:
   - ExecutionConfig promosso a typed schema con i due campi
     consumati al boot;
   - CLI start preferisce i valori da config; CLI flag overridano
     solo quando differenti dai default.

5. Cycle correlation ID:
   - structlog.contextvars.bind_contextvars in run_entry/run_monitor/
     run_health propaga cycle_id e cycle nei log strutturati.

6. SIGTERM/SIGINT clean shutdown:
   - run_forever installa loop.add_signal_handler per SIGTERM e
     SIGINT; il segnale set()ta un asyncio.Event che termina il
     blocco principale, scheduler.shutdown e ctx.aclose finalizzano.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 00:37:39 +02:00
Adriano 411b747e93 Phase 4 hardening: status CLI, lock file, backup job, hash enforce, pooling, real bias
Sei interventi mirati sui rischi operativi rilevati nell'audit
post-Fase 4. 317 test pass, mypy strict pulito, ruff clean.

1. status CLI: legge SQLite reale e mostra kill_switch, posizioni
   aperte, environment, config_version, last_health_check, started_at.
   Sostituisce il placeholder "phase 0 skeleton".

2. Lock file single-instance: runtime/lockfile.py acquisisce
   data/.lockfile via fcntl.flock al boot di run_forever; un secondo
   container fallisce subito con LockError.

3. Backup orario nello scheduler: nuovo job APScheduler 0 * * * *
   chiama scripts.backup.backup_database + prune_backups.

4. config_hash enforce su start: il CLI start verifica l'integrità
   del file (enforce_hash=True). Mismatch → exit 1 prima di toccare
   stato. dry-run resta enforce_hash=False per debug.

5. Connection pooling MCP: RuntimeContext espone un httpx.AsyncClient
   long-lived condiviso da tutti i wrapper (limits 20/10
   connections/keepalive). aclose() chiamato in run_forever finale.

6. Bias direzionale reale: deribit.historical_close +
   deribit.adx_14 popolano TrendContext con spot a 30 giorni e
   ADX(14) effettivi. Sblocca bull_put e bear_call. Quando i dati
   storici mancano l'engine emette alert MEDIUM e cade su no_entry
   in modo deterministico.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 00:15:28 +02:00
Adriano ca1e6379df chore(deps): bump greenlet, hypothesis, pathspec, virtualenv
Routine upgrade dei pacchetti minor/patch. 311 test pass, mypy
strict pulito, ruff clean.

- greenlet 3.4.0 → 3.5.0
- hypothesis 6.152.3 → 6.152.4
- pathspec 1.1.0 → 1.1.1
- virtualenv 21.2.4 → 21.3.0

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 00:04:51 +02:00
Adriano 42b0fbe1ab Phase 4: orchestrator + cycles auto-execute
Componente runtime/ che cabla core+clients+state+safety in un engine
autonomo notify-only: nessuna conferma manuale, ordini combo
piazzati direttamente quando le regole passano. 311 test pass,
copertura totale 94%, runtime/ 90%, mypy strict pulito, ruff clean.

Moduli:
- runtime/alert_manager.py: escalation tree
  LOW/MEDIUM/HIGH/CRITICAL → audit + Telegram + kill switch.
- runtime/dependencies.py: build_runtime() costruisce
  RuntimeContext con tutti i client MCP, repository, audit log,
  kill switch, alert manager.
- runtime/entry_cycle.py: flusso settimanale (snapshot parallelo
  spot/dvol/funding/macro/holdings/equity → validate_entry →
  compute_bias → options_chain → select_strikes →
  liquidity_gate → sizing_engine → combo_builder.build →
  place_combo_order → notify_position_opened).
- runtime/monitor_cycle.py: loop 12h con dvol_history per il
  return_4h, exit_decision.evaluate, close auto-execute.
- runtime/health_check.py: probe parallelo MCP + SQLite +
  environment match; 3 strikes consecutivi → kill switch HIGH.
- runtime/recovery.py: riconciliazione SQLite vs broker
  all'avvio; mismatch → kill switch CRITICAL.
- runtime/scheduler.py: AsyncIOScheduler builder con cron entry
  (lun 14:00), monitor (02/14), health (5min).
- runtime/orchestrator.py: façade boot() + run_entry/monitor/health
  + install_scheduler + run_forever, con env check vs strategy.

CLI:
- start: avvia engine bloccante (asyncio.run + scheduler).
- dry-run --cycle entry|monitor|health: esegue un singolo ciclo
  per debug/test in produzione.
- stop: documenta lo shutdown via SIGTERM al container.

Documentazione:
- docs/06-operational-flow.md riscritto per il modello
  notify-only auto-execute (no conferma manuale, no memory,
  no brain-bridge).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-28 00:03:45 +02:00
Adriano 466e63dc19 Phase 3: MCP HTTP clients + Dockerization
Wrapper async tipizzati sui sei servizi MCP HTTP che Cerbero Bite
consuma in autonomia. 277 test pass, copertura clients 93%, mypy
strict pulito, ruff clean.

Base layer:
- clients/_base.py: HttpToolClient con httpx + tenacity (retry
  esponenziale 3x, timeout 8s, mapping HTTP→eccezioni tipizzate).
- clients/_exceptions.py: McpAuthError, McpServerError, McpToolError,
  McpDataAnomalyError, McpNotFoundError, McpTimeoutError.
- config/mcp_endpoints.py: risoluzione URL via Docker DNS
  (mcp-deribit:9011, ...) con override per servizio via env var;
  caricamento bearer token da secrets/core.token o
  CERBERO_BITE_CORE_TOKEN_FILE.

Wrapper:
- clients/macro.py: next_high_severity_within() per filtro entry §2.5.
- clients/sentiment.py: funding_cross_median_annualized() con
  annualizzazione per period nativo per exchange (Binance/Bybit/OKX
  1095, Hyperliquid 8760).
- clients/hyperliquid.py: funding_rate_annualized() per filtro §2.6.
- clients/portfolio.py: total_equity_eur(), asset_pct_of_portfolio()
  per sizing engine + filtro §2.7.
- clients/telegram.py: notify-only (no callback queue, no
  conferme — Bite auto-execute).
- clients/deribit.py: environment_info, index_price_eth,
  latest_dvol, options_chain, get_tickers, orderbook_depth_top3,
  get_account_summary, get_positions, place_combo_order (combo
  atomico), cancel_order.

CLI:
- cerbero-bite ping: health-check parallelo di tutti gli MCP con
  tabella rich (OK/FAIL/SKIPPED).

Docker:
- Dockerfile multi-stage Python 3.13 + uv, user non-root.
- docker-compose.yml con rete external "cerbero-suite", secret
  core_token montato a /run/secrets/core_token, env per ogni MCP.
- secrets/README.md documenta il setup del token.

Documentazione di intervento:
- docs/12-mcp-deribit-changes.md: spec delle modifiche apportate
  al server mcp-deribit (place_combo_order + override testnet via
  DERIBIT_TESTNET).

Dipendenze:
- aggiunto pytest-httpx per i test HTTP.
- rimosso mcp>=1.0 (non usiamo l'SDK MCP, parliamo via HTTP REST).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 23:36:30 +02:00
Adriano 263470786d Phase 2: persistence + safety controls
Aggiunge la persistenza SQLite, l'audit log a hash chain, il kill
switch coordinato e i CLI di gestione documentati in
docs/05-data-model.md e docs/07-risk-controls.md. 197 test pass,
1 skipped (sqlite3 CLI mancante), copertura totale 97%.

State (`state/`):
- 0001_init.sql con positions, instructions, decisions, dvol_history,
  manual_actions, system_state.
- db.py: connect con WAL + foreign_keys + transaction ctx, runner
  forward-only basato su PRAGMA user_version.
- models.py: record Pydantic, Decimal preservato come TEXT.
- repository.py: CRUD typed con singola connessione passata, cache
  aware, posizioni concorrenti.

Safety (`safety/`):
- audit_log.py: AuditLog append-only con SHA-256 chain e fsync,
  verify_chain riconosce ogni manomissione (payload, prev_hash,
  hash, JSON, separatori).
- kill_switch.py: arm/disarm transazionali, idempotenti, accoppiati
  all'audit chain.

Config (`config/loader.py` + `strategy.yaml`):
- Loader YAML con deep-merge di strategy.local.yaml.
- Verifica config_hash SHA-256 (riga config_hash esclusa).
- File golden strategy.yaml + esempio override.

Scripts:
- dead_man.sh: watchdog shell indipendente da Python.
- backup.py: VACUUM INTO orario con retention 30 giorni.

CLI:
- audit verify (exit 2 su tampering).
- kill-switch arm/disarm/status su SQLite reale.
- state inspect con tabella posizioni aperte.
- config hash, config validate.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 13:35:35 +02:00
Adriano fbb7753cc6 Phase 1: core algorithms
Implementa i sette algoritmi puri di docs/03-algorithms.md con
disciplina TDD: 112 test, copertura statement+branch al 100% su
core/ e config/, mypy --strict pulito, ruff pulito.

Moduli:
- config/schema.py: StrategyConfig Pydantic v2 con validatori di
  consistenza (kelly, delta, OTM, spread width, profit/stop).
- core/types.py: OptionQuote e OptionLeg condivisi.
- core/entry_validator.py: validate_entry (accumula motivi) e
  compute_bias (bull_put/bear_call/iron_condor/None).
- core/liquidity_gate.py: check OI/volume/spread/depth + slippage
  stimato in % del credito.
- core/sizing_engine.py: Quarter Kelly con cap 200/1000 EUR e
  bande DVOL.
- core/combo_builder.py: select_strikes (DTE/OTM/delta/width/credit)
  e build (ComboProposal con credit/max_loss/breakeven).
- core/greeks_aggregator.py: somma firmata BUY/SELL, theta in USD.
- core/exit_decision.py: 6 trigger ordinati con eccezione skip-time
  vicino a profit (mark in (50%,70%] credito).
- core/kelly_recalibration.py: full/quarter Kelly, confidence per
  sample size, blend medio in fascia 30-99 trade.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-27 10:14:06 +02:00
Adriano 881bc8a1bf Phase 0: project skeleton
- pyproject.toml with uv, deps for runtime + gui + backtest + dev
- ruff/mypy strict config, pre-commit hooks for ruff/mypy/pytest
- src/cerbero_bite/ layout with empty modules ready for Phase 1+
- structlog JSONL logger with daily rotation
- click CLI with placeholder subcommands (status, start, kill-switch,
  gui, replay, config hash, audit verify)
- 6 smoke tests passing, mypy --strict clean, ruff clean

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-26 23:10:30 +02:00