14522262e6
Reset del progetto su fondamenta verificate dopo la scoperta che l'intera libreria "validata OOS" era artefatto di feed contaminato (print fantasma del feed Cerbero TESTNET + storico Binance/USDT). - Storico ricostruito da Deribit MAINNET (ccxt pubblico, tokenless) e CERTIFICATO (certify_feed.py): BTC/ETH puliti su TUTTA la storia (mediana 2-6 bps vs Coinbase USD), integrita' OHLC + coerenza resample (maxΔ 0.00) + cross-venue OK. Alt esclusi (illiquidi/divergenti: LTC/DOGE 50-82% barre flat; XRP/BNB non certificabili). - Verdetto sul feed pulito: FADE / PAIRS / XS01 / TSM01 morti (ogni portafoglio Sharpe -2.3..-3.0, DD ~40%); solo SH01 e frammenti HONEST con segnale residuo, da ri-validare in isolamento. - Cleanup "restart pulito": strategie, stack live (src/live, src/portfolio, runner/executor, yml, docker), ~100 script ricerca/gate, waste/games/ portfolios, dati non certificati + cache e 60+ diari -> archiviati in Old/ (preservati, non cancellati). Diario consolidato in un unico documento. - Skeleton ricerca tenuto: Strategy ABC + indicatori + src/fractal + src/backtest/engine + load_data; tool dati certificati (rebuild_history, certify_feed, audit_feed, multi_source_check). - Universo dati ATTIVO: solo BTC/ETH (5m/15m/1h); guardrail fisico (load_data su alt -> FileNotFoundError). Esecuzione DISABILITATA, conto flat. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
175 lines
5.0 KiB
Markdown
175 lines
5.0 KiB
Markdown
# Multi-Strategy Paper Trader — Design Spec
|
|
|
|
## Obiettivo
|
|
|
|
Eseguire N strategie di trading in parallelo su Deribit testnet (paper trading locale), ognuna con capitale virtuale indipendente di €1000 USDC. Lo storico trade di ogni strategia persiste tra restart. Nuove strategie aggiungibili in corso d'opera via config YAML senza perdere lo storico delle esistenti.
|
|
|
|
## Architettura
|
|
|
|
Un singolo container Docker esegue un orchestratore (`MultiStrategyRunner`) che gestisce N `StrategyWorker`. Ogni worker è indipendente: proprio capital, propri trade, proprio stato.
|
|
|
|
```
|
|
Docker Container
|
|
├── MultiStrategyRunner (orchestratore, loop principale)
|
|
│ ├── StrategyWorker[SQ02_BTC_15m] → paper trade → JSONL
|
|
│ ├── StrategyWorker[ML01_ETH_15m] → paper trade → JSONL
|
|
│ └── ...altri worker da YAML
|
|
├── CerberoClient (condiviso, fetch prezzi)
|
|
└── TelegramNotifier (condiviso)
|
|
```
|
|
|
|
## Componenti
|
|
|
|
### 1. `strategies.yml` — Configurazione
|
|
|
|
```yaml
|
|
defaults:
|
|
capital: 1000
|
|
position_size: 0.15
|
|
leverage: 3
|
|
hold_bars: 3
|
|
poll_seconds: 60
|
|
retrain_hours: 24
|
|
|
|
strategies:
|
|
- name: SQ02_antifake_vol
|
|
asset: BTC
|
|
tf: 15m
|
|
enabled: true
|
|
|
|
- name: SQ02_antifake_vol
|
|
asset: ETH
|
|
tf: 15m
|
|
enabled: true
|
|
|
|
- name: ML01_squeeze_gbm
|
|
asset: ETH
|
|
tf: 15m
|
|
enabled: true
|
|
position_size: 0.20
|
|
params:
|
|
ml_threshold: 0.70
|
|
bb_window: 14
|
|
sq_threshold: 0.8
|
|
```
|
|
|
|
Ogni entry eredita `defaults`. Override per-strategia possibile su tutti i campi. Il campo `params` passa kwargs a `generate_signals()` o al backtest ML.
|
|
|
|
### 2. `StrategyWorker` — Worker per singola strategia
|
|
|
|
Responsabilità:
|
|
- Importa la classe Strategy corrispondente da `scripts/strategies/`
|
|
- Mantiene stato: capital, posizione aperta, equity
|
|
- Al startup: ricarica `status.json` se esiste (resume), altrimenti inizia da zero
|
|
- Ad ogni tick: riceve DataFrame candele, genera segnali, paper-trade
|
|
- Logga ogni evento in `trades.jsonl` (append-only)
|
|
- Aggiorna `status.json` ad ogni tick
|
|
|
|
Stato persistente (`status.json`):
|
|
```json
|
|
{
|
|
"capital": 1023.45,
|
|
"in_position": true,
|
|
"direction": "long",
|
|
"entry_price": 2534.20,
|
|
"entry_time": "2026-05-27T14:30:00Z",
|
|
"bars_held": 1,
|
|
"total_trades": 15,
|
|
"total_wins": 12,
|
|
"started_at": "2026-05-27T10:00:00Z"
|
|
}
|
|
```
|
|
|
|
Trade log (`trades.jsonl`), append-only:
|
|
```json
|
|
{"ts": "2026-05-27T14:30:00Z", "event": "OPEN", "direction": "long", "price": 2534.20, "size": 0.18, "capital": 1023.45}
|
|
{"ts": "2026-05-27T15:15:00Z", "event": "CLOSE", "reason": "hold_limit", "entry": 2534.20, "exit": 2560.10, "pnl": 3.45, "fee": 0.92, "net_pnl": 2.53, "capital": 1025.98}
|
|
```
|
|
|
|
### 3. `MultiStrategyRunner` — Orchestratore
|
|
|
|
Loop principale:
|
|
1. Carica `strategies.yml`
|
|
2. Per ogni entry, crea `StrategyWorker` (o riprende se già esiste)
|
|
3. Ogni 60s:
|
|
a. Fetch candele live da Cerbero (una volta per asset/tf unico)
|
|
b. Passa DataFrame a ogni worker
|
|
c. Ogni worker valuta segnali e gestisce posizione
|
|
d. Worker ML: retrain ogni 24h
|
|
4. Notifica Telegram per ogni trade
|
|
|
|
Ottimizzazione: fetch candele raggruppato per (asset, tf). Se 3 strategie usano BTC 15m, fetch una volta sola.
|
|
|
|
### 4. Persistenza
|
|
|
|
```
|
|
data/paper_trades/
|
|
SQ02_antifake_vol__BTC__15m/
|
|
trades.jsonl
|
|
status.json
|
|
SQ02_antifake_vol__ETH__15m/
|
|
trades.jsonl
|
|
status.json
|
|
ML01_squeeze_gbm__ETH__15m/
|
|
trades.jsonl
|
|
status.json
|
|
```
|
|
|
|
Directory naming: `{strategy_name}__{asset}__{tf}` con double underscore separatore.
|
|
|
|
Volume Docker: `./data:/app/data` — persiste tra restart.
|
|
|
|
### 5. Aggiunta strategia in corso
|
|
|
|
1. Aggiungi entry in `strategies.yml`
|
|
2. `docker compose restart`
|
|
3. Runner carica YAML, trova nuova entry senza `status.json` → parte da €1000
|
|
4. Strategie esistenti riprendono da `status.json` → storico intatto
|
|
|
|
### 6. Docker
|
|
|
|
`Dockerfile` — invariato, aggiunge `strategies.yml` alla COPY.
|
|
|
|
`docker-compose.yml`:
|
|
```yaml
|
|
services:
|
|
paper-trader:
|
|
build: .
|
|
container_name: pythagoras-multi
|
|
restart: unless-stopped
|
|
volumes:
|
|
- ./data:/app/data
|
|
- ./strategies.yml:/app/strategies.yml:ro
|
|
env_file:
|
|
- .env
|
|
environment:
|
|
- PYTHONUNBUFFERED=1
|
|
```
|
|
|
|
`CMD` cambia a: `uv run python -m src.live.multi_runner`
|
|
|
|
### 7. Strategia-specifica: ML01
|
|
|
|
ML01 richiede training del modello GBM. Il worker ML01:
|
|
- Al primo avvio: train su storico (365 giorni via Cerbero)
|
|
- Ogni `retrain_hours`: retrain
|
|
- Usa `SignalEngine` esistente per check_signal()
|
|
- Le strategie SQ* non hanno training — solo regole deterministiche
|
|
|
|
### 8. File da creare/modificare
|
|
|
|
Nuovi:
|
|
- `src/live/multi_runner.py` — orchestratore
|
|
- `src/live/strategy_worker.py` — worker per singola strategia
|
|
- `strategies.yml` — config
|
|
- `src/live/strategy_loader.py` — import dinamico classi Strategy
|
|
|
|
Modifiche:
|
|
- `docker-compose.yml` — nuovo CMD, volume strategies.yml
|
|
- `Dockerfile` — COPY strategies.yml
|
|
|
|
Invariati:
|
|
- `src/live/cerbero_client.py`
|
|
- `src/live/telegram_notifier.py`
|
|
- `src/live/signal_engine.py` (usato da ML01 worker)
|