diff --git a/CLAUDE.md b/CLAUDE.md index 3f94295..992c29a 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -17,7 +17,7 @@ chi la riapre deve battere il motivo, non ripetere la misura. | `docs/memory/40-produzione-e-deploy.md` | esecutore, tripwire, monitor, libro di bordo, PRIIPs/UCITS | tocchi cio' che gira con soldi veri | | `docs/memory/50-dati-e-feed.md` | difetti del dato trovati e riparati, catena opzioni | tocchi i feed | | `docs/memory/60-metodo-e-gate.md` | i gate codificati in `altlib.py` | valuti un candidato | -| `docs/research/RESULTS-0822.md` | registro per filone §1-71 | vuoi il dettaglio di un filone | +| `docs/research/RESULTS-0822.md` | registro per filone §1-72 | vuoi il dettaglio di un filone | | `docs/diary/` (123 voci) | la sessione originale, per data | vuoi il contesto completo | --- @@ -173,7 +173,10 @@ sempre, bit-exact** (T7, `max|diff| = 0.0`) — `config/live.json` **non e' stat tetto nello stesso file della chiave sarebbe un lucchetto con la chiave attaccata: il gradino a 1,50 richiede una modifica di codice, quindi una review); il tetto e' **sul PRODOTTO** `n_asset · frac · scala` e l'invariante del disaster-SL e' `n_asset · frac · scala · disaster_sl_pct -≤ 0,50` (la guardia che morde per **prima**: da' scala ≤ 1,67x e scatta se qualcuno allarga lo stop); +≤ 0,50` (la guardia che morde per **prima**: da' scala ≤ 1,67x e scatta se qualcuno allarga lo stop — +🚨 e **`disaster_sl_pct` NON si sostituisce con la distanza di un pavimento di put**: darebbe 2,28x +sulla carta, ma la put limita UNA finestra e i drawdown di BTC sono grind di 290-818 giorni, su 8 +finestre −33,6% → 77% dell'equity a 2,28x. Misurato in §72, scritto qui prima che sia comodo); una scala fuori scaletta o fuori tetto **NON viene tagliata** — `book_execute` si ferma, non invia e allerta (`ScalaNonAutorizzata`); e **la scala vive solo sul percorso fidato** (equity reale illeggibile ⇒ 1,00, cosi' "il fallback non e' piu' permissivo" e' vero per costruzione). diff --git a/docs/diary/2026-09-01-collar-btc.md b/docs/diary/2026-09-01-collar-btc.md index 4b9695c..adec948 100644 --- a/docs/diary/2026-09-01-collar-btc.md +++ b/docs/diary/2026-09-01-collar-btc.md @@ -1,4 +1,7 @@ -# 2026-09-01 — COLLAR01: il pavimento funziona, il tetto lo paga troppo, e ciò che vince è VRP01 travestito +# 2026-09-01 — COLLAR01: il collar riduce il DD, il tetto lo paga troppo, e ciò che vince è VRP01 travestito + +> ⚠️ **Titolo corretto lo stesso giorno.** Diceva *«il pavimento funziona»*: la riduzione di DD è del +> **collar**, non del pavimento — la put da sola lo peggiora in 16/16 celle (§72, sezione A1 sotto). *Scritto il 2026-09-01. Ogni numero è riprodotto da `scripts/research/r0901_btc_collar.py`. **Libro, pesi, cron, config INVARIATI. Nessun ordine.*** @@ -70,10 +73,20 @@ Lente lunga 2021-03-24 → 2026-09-01 (1.988 giorni, 5,44 anni). BTC buy&hold nu maxDD 76,73% · drift +7,82%/a. Griglia dichiarata prima: 3 δput × 3 δcall × 2 tenor × 2 gate = **48 celle**, più 12 varianti zero-cost dichiarate a parte. -### ✅ A1 CONFERMATA — il pavimento funziona davvero (e §46 è battuto sul suo motivo) +### ✅ A1 CONFERMATA — il COLLAR riduce il maxDD (36/48) — ⚠️ ma NON è il pavimento a farlo **maxDD scende in 36/48 celle.** Con beta 1,0 la put para davvero: è il risultato che §46 non -poteva ottenere. *Questa metà della domanda dell'operatore ha risposta positiva.* +poteva ottenere. + +🚨 **CORREZIONE (stesso giorno, `r0901c_pavimento_leva.py`, §72).** Questa riga diceva *«il +pavimento funziona davvero»* e attribuiva la riduzione al pavimento. **È il COLLAR a ridurre il DD, +non il pavimento**: la put **da sola**, a premio reale, **peggiora il maxDD in 16/16 celle** +(FORTE 51,83% → 55,4-75,8%, LARGO 71,94% → 74,8-81,7%). Nel collar la riduzione viene dal **tetto** +— il suo premio compensa il bleed della put, e cappare l'upside **abbassa il picco** da cui il DD si +misura. Il pavimento pareggerebbe il DD nudo solo se le put costassero il **36-79% del reale**. +Quindi: *il motivo di §46 (beta) non si applica, ma il suo verdetto — il maxDD SALE — si riproduce +a beta 1,0 per un motivo diverso:* **i drawdown di BTC sono grind di 290-818 giorni, e una put a +≤15 giorni copre una finestra.** Dettaglio in `2026-09-01c-pavimento-leva.md`. ### ❌ A3 CONFERMATA — ma il de-levering lo fa meglio in 45/48 celle diff --git a/docs/diary/2026-09-01c-pavimento-leva.md b/docs/diary/2026-09-01c-pavimento-leva.md new file mode 100644 index 0000000..464a2c4 --- /dev/null +++ b/docs/diary/2026-09-01c-pavimento-leva.md @@ -0,0 +1,137 @@ +# 2026-09-01 — PAVIMENTO-LEVA: il pavimento non licenzia taglia, e corregge quanto scritto stamattina + +*Scritto il 2026-09-01. Ogni numero è riprodotto da `scripts/research/r0901c_pavimento_leva.py`, +che riusa il motore di `r0901_btc_collar.py`. **Libro, pesi, cron, config INVARIATI. Nessun ordine.*** + +## 0. La domanda + +> *«possiamo usare quanto conosciamo del pavimento per studiare una strategia»* + +Cosa sapevamo, da COLLAR01 (§71, poche ore prima): il collar riduce il maxDD in 36/48 celle; a +premio **zero** il pavimento vale moltissimo (maxDD 51,83% → 36,76%, drift +10,04% → +35,69%); ciò +che uccise il collar fu il **tetto**, non il pavimento (C9); la put è l'ala cara. + +**L'inversione.** COLLAR01 chiese *«quanto DD mi risparmia il pavimento a taglia fissa?»* e perse +contro il de-levering. La domanda speculare è *«quanta TAGLIA mi autorizza il pavimento a DD +fisso?»*. Non è la stessa, per due ragioni misurabili: + +1. de-levare riduce taglia e rischio **in proporzione**; un pavimento cambia la **forma** — se taglia + la coda sinistra più di quanto costi, scalare *in su* la struttura protetta può battere la base + nuda alla stessa DD. È l'unica cosa che il de-levering **non può** comprare; +2. il tetto di leva del progetto non è fissato dallo Sharpe ma dal **costo di un episodio** di + disaster-SL (`n · frac · scala · sl ≤ 0,50` ⇒ k ≤ 1,67x). Il disaster-SL è **rotolante** e non + limita la perdita (peggior DD dall'ingresso misurato −60,6%). Una put la limita per costruzione — + *dentro la sua finestra*. + +Quattro attese scritte prima di misurare (B1-B4). **Tutte e quattro confermate.** + +## 1. Il risultato: 0 celle su 16 + +Griglia dichiarata: 4 δput × 2 tenor × 2 gate. Struttura: hold gated + **sola put**, premio reale +(DVOL × skew × termine dalla catena — realistico per chi *compra*: M29 corregge chi vende a +modello, non chi compra). + +| gate | base nuda | pavimento a premio reale (16 celle) | +|---|---|---| +| FORTE | maxDD **51,83%** · drift +10,04% | maxDD **55,4% → 75,8%** · drift +3,8% → −17,0% | +| LARGO | maxDD **71,94%** · drift +17,37% | maxDD **74,8% → 81,7%** · drift +9,9% → −13,9% | + +**Il pavimento peggiora il maxDD in 16 celle su 16.** Quindi `k_f = 1,000` ovunque: non c'è taglia +da licenziare, perché non c'è DD da spendere. Il null M5 classico concorda (0/16). Monotono nella +protezione: più la put è vicina, peggio va — il bleed del premio *è* il drawdown. + +## 2. 🚨 La correzione a COLLAR01 + +Stamattina ho scritto, in A1: *«il pavimento funziona davvero (e §46 è battuto sul suo motivo)»*. +**La prima metà è sbagliata nell'attribuzione.** Il DD lo riduce **il collar**, non il pavimento: + +- la put da sola, a premio reale, **peggiora** il DD (questo filone); +- a premio zero lo riduce (il controllo del pranzo gratis) — quindi **tutto il beneficio del + pavimento è mangiato dal suo premio, e oltre**; +- nel collar la riduzione viene dal **tetto**: il suo premio compensa il bleed della put, e cappare + l'upside **abbassa il picco** da cui il DD si misura — che non è protezione, è un picco più basso. + +**Il premio di pareggio** lo quantifica: il pavimento inizia a ridurre il DD nudo solo se le put +costano il **36-79% del reale** (secondo la cella). Il DVOL sta 1,32× sopra la vol realizzata, quindi +un prezzo *equo* sarebbe ~76% del reale: **anche a prezzo equo il pareggio si sfiora nelle celle +migliori e si manca nelle altre**. E il mercato non vende a prezzo equo. + +La seconda metà della frase regge, ma va detta con precisione: **il motivo di §46 non si applica** +(a beta 1,0 la put paga davvero: para nel 2-20% dei cicli), **ma il verdetto di §46 — *il maxDD +SALE* — si riproduce a beta 1,0 per un motivo diverso.** Il motivo è la sezione seguente. + +Corretti stesso giorno: il diario di COLLAR01 (titolo e A1), RESULTS §71, la memoria. M28: +*quando due affermazioni della stessa memoria si contraddicono, la contraddizione è informazione* — +qui erano due mie affermazioni a poche ore di distanza, e la seconda ha corretto la prima. + +## 3. B2 — Il meccanismo: la put copre una finestra, BTC scende in grind + +| gate | maxDD della base | da → a | durata | +|---|---|---|---| +| FORTE | −51,83% | 2021-07-20 → 2022-05-06 | **290 giorni** | +| LARGO | −71,94% | 2021-07-20 → 2023-10-16 | **818 giorni** | + +Una put a 7-14 giorni copre **una** finestra. Il drawdown che conta è lungo **20-60 finestre**. In +un grind la put scade OTM settimana dopo settimana — il pavimento para nel **0-9%** dei cicli col +gate FORTE — mentre il premio sanguina. E non protegge nemmeno la finestra peggiore: peggior 14 +giorni FORTE **−22,9% nudo → −23,6% col pavimento**, perché la put a 5 delta sta a ~22% dallo spot, +cioè esattamente al bordo di ciò che è successo, e il premio la rende netta negativa. + +**Su BTC il pavimento compra protezione contro la cosa sbagliata**: i crolli veloci dentro una +finestra, mentre le perdite che definiscono il maxDD sono grind di mesi. Questo è ciò che §46 non +poteva vedere (a beta 0,076 il libro non aveva né crolli né grind da proteggere) e che a beta 1,0 +diventa il fatto dominante. + +## 4. B3 — La licenza del disaster-SL è di carta + +L'invariante `n · frac · scala · sl ≤ 0,50` con `sl = 0,30` dà **1,67x**. Con la put a 5δ/14g il +pavimento sta a **21,9%** dallo spot: sostituire `sl` con quella distanza darebbe **2,28x** — +*1,4× in più*. È la proposta che qualcuno farà, e va uccisa ora: + +| finestre consecutive | giorni | peggior perdita col pavimento | la put… | +|---|---|---|---| +| 1 | 14 | −23,6% | copre | +| 2 | 28 | −25,9% | **non copre** | +| 4 | 56 | −28,8% | **non copre** | +| 8 | 112 | **−33,6%** | **non copre** | + +L'invariante limita **un episodio**; la put limita **una finestra**; il massimo su finestre +consecutive **non è limitato da nulla**. A 2,28x un grind di 112 giorni costerebbe il **77% +dell'equity**. ⇒ **`disaster_sl_pct` non si sostituisce con la distanza di un pavimento**, e va +scritto prima che sia comodo per qualcuno. + +## 5. B4 — Il pavimento gated sull'IV: migliora, non basta + +§46 dichiarava *«nessuna copertura dinamica gated su regime è stata provata»*. Provata: put ON solo +quando DVOL/RV trailing sta sotto il 25° o 50° percentile dell'anno (il premio di varianza è +sottile). + +| gate | soglia | ON (giorni a mercato) | drift | vs base | +|---|---|---|---|---| +| FORTE | 25° pctl | 27% | **+8,39%** | +10,04% → **perde** | +| FORTE | 50° pctl | 47% | +6,77% | perde | +| LARGO | 25° pctl | 25% | **+15,31%** | +17,37% → **perde** | +| LARGO | 50° pctl | 50% | +13,93% | perde | + +Migliora molto rispetto al pavimento sempre acceso (+3,8% → +8,4% col gate FORTE) e il DD resta +≥ della base (k_f = 1,000). ⚠️ L'incollatura ignora lo spread delle transizioni ON/OFF, **a favore** +del gated: se perde così, perde a maggior ragione. + +## 6. Cosa NON ho fatto, dichiarato + +- Nessun DSR, nessun `study_family_honest`: il filone cade al primo gate, 0/16. +- Nessuna lente reale (123 giorni, ~8 cicli): stessa ragione di COLLAR01. +- Non ho provato il pavimento **a scadenza lunga** (30-90 giorni), che coprirebbe più di una + finestra di grind — perché l'operatore ha vincolato la scadenza a **≤15 giorni**. È l'unica + variante che B2 lascia aperta, e sta fuori dal vincolo dichiarato. Va detto: se il vincolo cadesse, + sarebbe la prima cosa da misurare, e la memoria di §46 ha già l'apparato (tenor 30). + +## 7. Verdetto + +> **`IL PAVIMENTO NON LICENZIA TAGLIA A PREMIO REALE: 0/16. Ciò che il de-levering non può comprare, +> la put lo vende a un prezzo che nessuna cella ripaga — e su BTC compra protezione contro i crolli +> mentre le perdite sono grind.`** — REFUTATO. + +**Cosa lo riapre:** una scadenza che copra il grind (fuori dal vincolo ≤15g), o un mercato che venda +la put al 36-79% del prezzo attuale — cioè un premio di varianza *negativo*, che su BTC non si è +mai misurato. Non lo riaprono delta, tenor ≤15 o gate sull'IV: sono misurati. diff --git a/docs/memory/20-ondate-e-scartati.md b/docs/memory/20-ondate-e-scartati.md index 13fd8f1..c2abf4e 100644 --- a/docs/memory/20-ondate-e-scartati.md +++ b/docs/memory/20-ondate-e-scartati.md @@ -1467,8 +1467,10 @@ una maschera a caso della stessa frequenza**. **L'entrata non ha aggiunto un solo parametro:** `tsmom_blend` media tre `np.sign()` su (30,90,180) ⇒ valori in {−1,−1/3,+1/3,+1}, quindi *"forte bull"* = `|blend|==1` (52,5% dei giorni) contro il confronto dichiarato `|blend|>=1/3` (97,1%); il segno da' long **e** short. - ✅ **A1 CONFERMATA — il pavimento FUNZIONA: maxDD scende in 36/48 celle** (§46: saliva in 162/162). - *La meta' della domanda dell'operatore ha risposta positiva.* + ✅ **A1 CONFERMATA — il COLLAR riduce il maxDD: 36/48 celle** (§46: saliva in 162/162). + 🚨 **Corretto lo stesso giorno da PAVIMENTO-LEVA (§72): NON e' il pavimento a farlo.** La put da + sola, a premio reale, **peggiora il DD in 16/16 celle**; nel collar la riduzione viene dal TETTO + (compensa il bleed, e cappare l'upside abbassa il picco da cui il DD si misura). ❌ **Ma il de-levering lo fa meglio in 45/48**, e il baratto costa **2-8 punti di drift per punto di DD** (Δdrift/ΔmaxDD **7,90** gate forte, **1,98** largo). 🚨 **C9 in forma pura: il tetto taglia il 46,2% dei cicli VINCENTI, il pavimento para il 6,7% dei @@ -1503,3 +1505,19 @@ una maschera a caso della stessa frequenza**. **Cosa lo riapre:** un **f di stress su un crash catturato** (la condizione che §3 pone allo short-vol), o un sottostante **senza coda destra grassa**. **Non** lo riaprono tenor, delta o griglie piu' fini: la pendenza e' monotona verso l'angolo, e l'angolo e' gia' misurato. + +- **PAVIMENTO-LEVA "il pavimento come licenza di taglia" — REFUTATO 0/16 (2026-09-01)** — + `r0901c_pavimento_leva.py`, diario `2026-09-01c-pavimento-leva.md`, registro §72. L'inverso di + COLLAR01: non *quanto DD risparmia* ma *quanta TAGLIA autorizza a iso-DD*, l'unica cosa che il + de-levering non puo' comprare. **La sola put a premio reale PEGGIORA il maxDD in 16/16 celle** + ⇒ `k_f = 1,000`, niente da licenziare. 🚨 **Corregge COLLAR01 lo stesso giorno**: il DD lo + riduceva il **tetto**, non il pavimento (compensa il bleed e abbassa il picco). Pareggio del DD + solo a **36-79% del premio reale**; prezzo equo ≈76%: non basta. + 📌 **Il meccanismo, trasferibile: i drawdown di BTC sono GRIND (290-818 giorni), la put copre + UNA finestra** e para nel 0-9% dei cicli: compra protezione contro la cosa sbagliata. + 🚨 **La licenza del disaster-SL e' di CARTA**: sostituire `sl` con la distanza del pavimento + darebbe 2,28x, ma su 8 finestre consecutive la perdita e' −33,6% → **77% dell'equity**. + `disaster_sl_pct` NON si sostituisce con la distanza di un pavimento. + **Gated sull'IV sottile** (la copertura dinamica che §46 non aveva provato): migliora, perde. + **Cosa lo riapre:** scadenza lunga che copra il grind (fuori dal vincolo ≤15g dell'operatore), + o un premio di varianza negativo su BTC. Non delta, tenor ≤15, gate IV: misurati. diff --git a/docs/research/RESULTS-0822.md b/docs/research/RESULTS-0822.md index 3a87e63..c9ed510 100644 --- a/docs/research/RESULTS-0822.md +++ b/docs/research/RESULTS-0822.md @@ -18,6 +18,7 @@ null de-levering superato + eseguibilita' al capitale dichiarato. | — | **XSR-REPRO** (integrita') | 🚨 **DIFETTO DI PRODUZIONE** | il numero 1.82 e' SPIEGATO e non era sbagliato (era su una **terza** lente, e su una barra non ancora chiusa) — ma cercandone la causa e' emerso che **`paper_xsr` registra ~41 minuti di mercato al giorno**, non un giorno. Tre gate pre-registrati leggono serie costruite cosi' | | 70 | **XSR-RENDITA** | **SCARTATO sotto la lente RENDITA** (non come sleeve) | il muro scende del 20,6% a iso-rischio, ma **mescolare i rendimenti di XSR01 da' lo stesso muro** (il meccanismo vale 0,8%, dentro la risoluzione MC) e un **conto remunerato allo stesso tasso lo eguaglia a vol 0 e senza secondo venue**. A drift zero il muro **sale**: si compra un drift scorrelato, non la scorrelazione. E l'haircut non pareggia un conto al 4% **nemmeno a haircut ZERO** | | 71 | **COLLAR01** | hold BTC gated dal trend, coperto da un collar (pavimento comprato, tetto venduto) a scadenza <=15g: "ridurre la vincita, bloccare la perdita" batte il de-levering? | **REFUTATO** — ✅ il pavimento FUNZIONA (maxDD scende in **36/48**, §46 battuto sul suo motivo: qui beta=1,0) ❌ ma costa **2-8 punti di drift per punto di DD** e il de-levering vince **45/48**. 🚨 Le 3 celle vincenti stanno sul **bordo**: estesa la famiglia vince 35/36 **nell'angolo covered-call**, e **il 72-100% di quell'edge e' il PREMIO DI VARIANZA** (DVOL sta **32% sopra** la RV-forward): riprezzato alla vol vera l'angolo cade da Sharpe **1,471 a 0,511** — che e' VRP01 (0,47), non una scoperta | +| 72 | **PAVIMENTO-LEVA** | il pavimento (sola put, ≤15g) come LICENZA DI TAGLIA a iso-DD — l'inverso di §71 | **REFUTATO 0/16**, e **corregge §71**: la put da sola a premio reale **peggiora il maxDD in 16/16** (FORTE 51,8% → 55-76%; LARGO 71,9% → 75-82%) — nel collar il DD lo riduceva il **TETTO**, non il pavimento. Meccanismo (B2): **i drawdown di BTC sono grind di 290-818 giorni**, la put copre una finestra e para nel 0-9% dei cicli. Pareggio del DD solo a **36-79% del premio reale** (prezzo equo ≈76%: non basta). **La licenza del disaster-SL e' di carta** (B3): sostituire `sl` con la distanza del pavimento darebbe 2,28x, ma su 8 finestre la perdita e' −33,6% → **77% dell'equity**. Gated su IV sottile: migliora (+3,8 → +8,4%) ma **perde** ancora | | 5 | SKEW | **SCARTATO** (Q1, Q2) + **LEAD** (Q3, gate 2027-02-22) | il prezzo muove lo skew (t 3,1-9,4 su 8/8 test), **non il contrario** (max |t| in avanti 2,35 contro 2,08 atteso dal rumore). Ma Q3 e' grosso: **il f=0,73 di VRP01 e' per il 42% STRUTTURA A TERMINE e solo per il 25% skew** | | — | **HL-EXEC** (audit di fatto) | **3 falsificazioni misurate** | il pavimento vero e' **$10 (non $5)** e il taker **4,50 bps (non 5,0)** — ma il *"XS01 serve ~$20k"* e' **refutato del tutto** (nessuna soglia da min-order), il *"XSR01 ~$5.000"* e' **conservativo di 1,7x** (vero ~$3.000), e lo **slippage "rischio #1" di XSR01 e' refutato** con margine **21x** | | — | **SLIP-AUDIT** (audit di fatto) | **SCARTATO** = nessun costo nascosto a questa taglia | i backtest a 10 bps RT restano **conservativi di ~1,5 bps/lato**; nessuna evidenza di impatto sopravvive al null (p=0,274; estremi avversi **1/18 contro 4,7 attesi**). **Ma la misura ha una data di scadenza** | @@ -3828,7 +3829,7 @@ famiglia **USDC**; la catena che raccogliamo e' **100% inverse** ⇒ **quel muro | esito | misura | |---|---| -| ✅ **A1 — il pavimento FUNZIONA** | maxDD scende in **36/48** celle (§46: saliva in 162/162) | +| ✅ **A1 — il COLLAR riduce il maxDD** | scende in **36/48** celle (§46: saliva in 162/162). 🚨 **Corretto da §72 lo stesso giorno: NON e' il pavimento** — la put da sola, a premio reale, **peggiora il DD in 16/16**; la riduzione viene dal TETTO (compensa il bleed e abbassa il picco) | | ❌ **A3 — ma il de-levering lo fa meglio** | il collar batte il null a iso-maxDD in **3/48** | | ❌ **A2 — il prezzo del baratto** | Δdrift/ΔmaxDD mediano **7,90** (gate forte) / **1,98** (largo) | | 🚨 **C9 — troncatura, non protezione** | il tetto taglia il **46,2%** dei cicli **vincenti**, il pavimento para il **6,7%** dei **perdenti**: 7x piu' spesso sui vincenti | @@ -3887,3 +3888,56 @@ NON E' LA PROTEZIONE, E' IL PREMIO DI VARIANZA (VRP01)`** — REFUTATO. pone allo short-vol), o un sottostante **senza coda destra grassa** — il tetto costa perche' BTC vive li'. **Non** lo riaprono tenor, delta o griglie piu' fini: la pendenza e' monotona verso l'angolo, e l'angolo e' gia' misurato. + +--- + +## 72 — PAVIMENTO-LEVA (il pavimento come licenza di taglia) + +`scripts/research/r0901c_pavimento_leva.py` (riusa il motore di §71). **Libro, pesi, cron, config +INVARIATI. Nessun ordine.** Domanda dell'operatore: *"possiamo usare quanto conosciamo del pavimento +per studiare una strategia?"*. L'inversione di §71: non *quanto DD mi risparmia* ma *quanta TAGLIA +mi autorizza a iso-DD* — l'unica cosa che il de-levering non puo' comprare, e la grandezza su cui +vive il tetto di leva del progetto (`n · frac · scala · sl ≤ 0,50` ⇒ 1,67x). + +❌ **0/16.** Sola put a premio reale, 4 δ × 2 tenor × 2 gate: **il maxDD SALE in 16/16 celle** +(FORTE 51,83% → 55,4-75,8%, LARGO 71,94% → 74,8-81,7%), quindi `k_f = 1,000` ovunque e non c'e' taglia +da licenziare. Monotono: piu' la put e' vicina, peggio va — **il bleed del premio E' il drawdown**. + +🚨 **CORREGGE §71.** Stamattina A1 diceva *"il pavimento funziona"*. **E' il COLLAR a ridurre il DD, +non il pavimento**: a premio zero la put lo riduce (51,83 → 36,76), a premio reale lo peggiora ⇒ +tutto il beneficio e' mangiato dal premio, e oltre. Nel collar la riduzione viene dal **tetto** (il +suo premio compensa il bleed, e cappare l'upside **abbassa il picco** da cui il DD si misura). +**Premio di pareggio: 36-79% del reale** (secondo la cella); il DVOL sta 1,32× sopra la RV, quindi +un prezzo equo (~76%) sfiora il pareggio nelle celle migliori e lo manca nelle altre. *Il motivo di +§46 (beta) non si applica a beta 1,0 — la put paga davvero — ma il verdetto di §46, il maxDD SALE, +si riproduce per un motivo diverso.* Corretti §71, il suo diario e la memoria. + +📌 **B2, IL MECCANISMO — e' il risultato trasferibile:** **i drawdown di BTC sono GRIND**, non +crolli. maxDD FORTE da 2021-07-20 a 2022-05-06 (**290 giorni**), LARGO fino al 2023-10-16 (**818**). +Una put a 7-14g copre UNA finestra; il DD che conta dura 20-60 finestre; la put scade OTM ogni +settimana (para nel **0-9%** dei cicli, gate FORTE) mentre il premio sanguina. E non protegge +nemmeno la finestra peggiore (14g FORTE: −22,9% nudo → **−23,6%** col pavimento: la put a 5δ sta a +~22% dallo spot, al bordo esatto di cio' che e' successo). **Su BTC il pavimento compra protezione +contro la cosa sbagliata.** + +🚨 **B3 — LA LICENZA DEL DISASTER-SL E' DI CARTA, e va scritto prima che sia comodo.** Con la put a +5δ/14g a **21,9%** dallo spot, sostituire `sl` con quella distanza nell'invariante darebbe **2,28x** +(1,4× in piu'). Ma l'invariante limita UN episodio, la put limita UNA finestra, e il massimo su +finestre consecutive **non e' limitato da nulla**: 1 finestra −23,6% (coperta), 2 −25,9%, 4 −28,8%, +**8 finestre −33,6%** (non coperte). A 2,28x un grind di 112 giorni costerebbe il **77% +dell'equity**. ⇒ **`disaster_sl_pct` NON si sostituisce con la distanza di un pavimento.** + +**B4 — gated sull'IV** (§46: *"nessuna copertura dinamica e' stata provata"* — ora lo e'): put ON solo +sotto il 25°/50° pctl di DVOL/RV. Migliora molto (FORTE +3,8% → **+8,4%**; LARGO +9,9% → +15,3%), +**ma resta sotto la base** (+10,04% / +17,37%) e il DD resta ≥. L'incollatura ignora lo spread delle +transizioni **a favore** del gated. + +⚠️ **Non misurato, dichiarato:** nessun DSR (cade al primo gate); nessuna lente reale; **nessun +pavimento a scadenza lunga** (30-90g, che coprirebbe piu' finestre di grind) perche' l'operatore ha +vincolato la scadenza a **≤15 giorni** — e' l'unica variante che B2 lascia aperta, e sta fuori dal +vincolo. Se il vincolo cadesse, sarebbe la prima misura da fare. + +**VERDETTO: `IL PAVIMENTO NON LICENZIA TAGLIA: 0/16 — SU BTC COMPRA PROTEZIONE CONTRO I CROLLI, E +LE PERDITE SONO GRIND`** — REFUTATO. **Cosa lo riapre:** una scadenza che copra il grind (fuori dal +vincolo), o un premio di varianza *negativo* su BTC (mai misurato). Non lo riaprono delta, tenor ≤15 +o gate sull'IV. diff --git a/scripts/research/r0901c_pavimento_leva.py b/scripts/research/r0901c_pavimento_leva.py new file mode 100644 index 0000000..e1ceb11 --- /dev/null +++ b/scripts/research/r0901c_pavimento_leva.py @@ -0,0 +1,263 @@ +"""PAVIMENTO-LEVA — il pavimento come LICENZA DI TAGLIA, non come sconto sul drawdown. + +DOMANDA (operatore, 2026-09-01): "possiamo usare quanto conosciamo del pavimento per studiare +una strategia?" + +COSA SAPPIAMO DEL PAVIMENTO (COLLAR01, §71, stesso giorno): + - FUNZIONA: con beta 1,0 il maxDD scende in 36/48 celle (§46 lo negava per un libro a beta 0,076); + - a premio ZERO vale moltissimo: maxDD 51,83% -> 36,76%, drift +10,04% -> +35,69% (il pranzo gratis); + - cio' che uccise il collar fu il TETTO, non il pavimento (C9: il tetto tagliava il 46% dei cicli + vincenti, il pavimento parava il 6,7% dei perdenti); + - la put e' l'ala CARA (skew: IV_put/ATM 1,25 a d0,10) e il DVOL sta il 32% sopra la RV: comprare + il pavimento significa pagare il premio di varianza. Qui il prezzo a DVOL e' REALISTICO (e' + cio' che il mercato chiede): M29 corregge chi VENDE a modello, non chi compra. + +L'INVERSIONE. COLLAR01 chiese "quanto DD mi risparmia il pavimento a taglia fissa?" e perse contro il +de-levering. La domanda speculare e' "quanta TAGLIA mi autorizza il pavimento a DD fisso?". Sembra +la stessa (a iso-DD e' un solo confronto), ma non lo e' per due ragioni misurabili: + (1) il de-levering riduce taglia e rischio IN PROPORZIONE; un pavimento cambia la FORMA — se la + forma taglia la coda sinistra piu' di quanto costi, scalare in su la struttura protetta puo' + battere la base nuda alla stessa DD. E' l'unica cosa che il de-levering NON puo' comprare; + (2) il tetto di leva del progetto NON e' fissato dallo Sharpe ma dal COSTO DI UN EPISODIO di + disaster-SL: n_asset * frac * scala * sl_pct <= 0,50 => k <= 1,67x (GATE SCALA-01, §4.5). + Il disaster-SL e' ROTOLANTE e non limita la perdita (peggior DD dall'ingresso misurato + -60,6%). Una put limita la perdita PER COSTRUZIONE — dentro la sua finestra. + +ATTESE A PRIORI (scritte prima di misurare): + B1 A premio reale il pavimento LICENZIA taglia (k_f > 1) ma il drift della struttura scalata + resta SOTTO quello della base nuda: il premio costa piu' di quanto la licenza renda. Previsione + centrale: il pavimento perde il test della licenza nella maggioranza delle celle. + B2 La riduzione di DD viene dai crolli VELOCI (dentro una finestra di opzione), non dai declini + LENTI: in un grind di settimane la put scade OTM ogni volta e si paga premio E perdita. + Il maxDD di BTC 2021-2026 e' il 2022, che fu un grind => il pavimento lo protegge poco. + B3 La "licenza" del disaster-SL e' di CARTA: l'invariante limita UN episodio, la put limita UNA + finestra, e il vero massimo su finestre consecutive NON e' limitato. Sostituire sl_pct con la + distanza del pavimento nell'invariante sarebbe un errore — e va scritto ora, prima che + qualcuno lo proponga. + B4 Il pavimento gated su IV a buon mercato (DVOL/RV basso) migliora ma non basta a passare. + +NESSUN ORDINE. Libro, pesi, cron, config INVARIATI. +""" +from __future__ import annotations + +import math +import sys +from pathlib import Path + +import numpy as np +import pandas as pd + +ROOT = Path(__file__).resolve().parents[2] +sys.path.insert(0, str(ROOT)) +sys.path.insert(0, str(ROOT / "scripts" / "research")) + +import r0901_btc_collar as C # noqa: E402 — il motore, riusato e non riscritto + +DPY = C.DPY + +G_DPUT = (0.05, 0.10, 0.20, 0.30) +G_TENOR = (7, 14) + + +def k_up_for_same_dd(r: np.ndarray, target_dd: float, kmax: float = 6.0) -> float: + """La scala >=1 che porta il maxDD della struttura PROTETTA esattamente a quello della base NUDA. + E' il null M5 letto al contrario: invece di ridurre la base al DD del protetto, si ALZA il + protetto al DD della base. maxDD(k*r) e' crescente in k: bisezione.""" + if C._dd(r) >= target_dd: + return 1.0 + lo, hi = 1.0, kmax + if C._dd(hi * r) < target_dd: + return kmax + for _ in range(60): + mid = 0.5 * (lo + hi) + if C._dd(mid * r) > target_dd: + hi = mid + else: + lo = mid + return 0.5 * (lo + hi) + + +def peggior_finestra(nav: pd.Series, giorni: int) -> float: + """La peggior perdita su una finestra di `giorni` (quella che UNA put puo' coprire).""" + r = nav / nav.shift(giorni) - 1.0 + return float(r.min()) + + +def main() -> None: + print("=" * 96) + print(" PAVIMENTO-LEVA — il pavimento come licenza di taglia") + print("=" * 96) + print(__doc__.split("ATTESE A PRIORI")[1].split("NESSUN ORDINE")[0]) + + cal = C.calibra_catena() + P = C.serie_giornaliera() + print(f" LENTE LUNGA {P.index[0].date()} -> {P.index[-1].date()} ({len(P)/DPY:.2f} anni). " + f"Prezzo a DVOL x skew x termine misurati sulla catena (realistico per chi COMPRA).") + + righe = [] + for forte in (True, False): + dirs = C.gate_trend(P, forte) + nm = "FORTE" if forte else "LARGO" + base = C.collar(P, cal, dput=0.2, dcall=0.2, tenor=7, dirs=dirs, senza_opzioni=True) + rb, nb = base["ret"], base["nav"] + dd_b, dr_b, sh_b = C._dd(rb), C._drift(rb), C._sh(rb) + print(f"\n ── gate {nm}: BASE nuda Sharpe {sh_b:.3f} · maxDD {100*dd_b:.2f}% · drift {100*dr_b:+.2f}%/a" + f" · peggior 7g {100*peggior_finestra(nb,7):.1f}% · peggior 14g {100*peggior_finestra(nb,14):.1f}%") + print(f" {'ten':>4}{'dput':>6}{'Sharpe':>8}{'maxDD':>8}{'drift':>9} | " + f"{'k_f':>6}{'drift@k_f':>11}{'vs base':>9} | {'k null':>7}{'drift null':>11}{'vs':>4} | " + f"{'pegg7':>7}{'pegg14':>7}{'pav.para':>9}") + for tenor in G_TENOR: + for dp in G_DPUT: + o = C.collar(P, cal, dput=dp, dcall=0.2, tenor=tenor, dirs=dirs, solo_pavimento=True) + r, nav = o["ret"], o["nav"] + dd, dr, sh = C._dd(r), C._drift(r), C._sh(r) + # (a) LICENZA: alzo il protetto fino al DD della base + kf = k_up_for_same_dd(r.values, dd_b) + dr_kf = C._drift(kf * r.values) + lic = dr_kf > dr_b + # (b) NULL M5 classico: abbasso la base fino al DD del protetto + kn = C.k_for_same_dd(rb.values, dd) + dr_n = C._drift(kn * rb.values) + m5 = dr > dr_n and dd < dd_b + cic = pd.DataFrame(o["cicli"]) + para = 100.0 * cic["floor"].mean() if len(cic) else float("nan") + righe.append(dict(gate=nm, forte=forte, tenor=tenor, dp=dp, sh=sh, dd=dd, drift=dr, + kf=kf, drift_kf=dr_kf, licenza=lic, kn=kn, drift_null=dr_n, m5=m5, + pegg7=peggior_finestra(nav, 7), pegg14=peggior_finestra(nav, 14), + para=para, ret=r, nav=nav)) + print(f" {tenor:>4}{dp:>6.2f}{sh:>8.3f}{100*dd:>7.2f}%{100*dr:>8.2f}% | " + f"{kf:>6.3f}{100*dr_kf:>10.2f}%{('VINCE' if lic else 'perde'):>9} | " + f"{kn:>7.3f}{100*dr_n:>10.2f}%{('V' if m5 else 'p'):>4} | " + f"{100*peggior_finestra(nav,7):>6.1f}%{100*peggior_finestra(nav,14):>6.1f}%{para:>8.1f}%") + + R = pd.DataFrame(righe) + n_lic = int(R["licenza"].sum()) + print("\n" + "=" * 96) + print(f" B1 il pavimento a premio reale VINCE il test della LICENZA in {n_lic}/{len(R)} celle " + f"({'REFUTATA' if n_lic > len(R)//2 else 'CONFERMATA'})") + print(f" (e il null M5 classico in {int(R['m5'].sum())}/{len(R)}: le due letture " + f"{'concordano' if abs(n_lic-int(R['m5'].sum()))<=2 else 'DIVERGONO — va capito perche'}) ") + + # ---- B2: da dove viene la riduzione di DD? crolli veloci o grind? ------------------------ + print("\n B2 MECCANISMO — la put copre UNA finestra: protegge i crolli veloci, non i grind.") + for forte in (True, False): + dirs = C.gate_trend(P, forte) + nm = "FORTE" if forte else "LARGO" + base = C.collar(P, cal, dput=0.2, dcall=0.2, tenor=7, dirs=dirs, senza_opzioni=True) + nb = base["nav"] + best = R[(R["forte"] == forte)].sort_values("sh", ascending=False).iloc[0] + nf = best["nav"] + # il maxDD: quando, e quanto e' durato + for lbl, nav in (("base", nb), ("pavimento", nf)): + pk = nav.cummax() + ddser = nav / pk - 1.0 + i_min = ddser.idxmin() + i_pk = nav[:i_min].idxmax() + durata = (i_min - i_pk).days + print(f" {nm} {lbl:>9}: maxDD {100*ddser.min():.2f}% da {i_pk.date()} a {i_min.date()} " + f"— {durata} giorni ({'GRIND' if durata > 3*best['tenor'] else 'crollo dentro ~1 finestra'})") + # perdita "dentro finestra" contro "fra finestre": quanto del DD e' coperto dalla put + pegg_b = peggior_finestra(nb, best["tenor"]) + pegg_f = peggior_finestra(nf, best["tenor"]) + print(f" {nm} peggior finestra di {best['tenor']}g: base {100*pegg_b:.1f}% -> " + f"pavimento {100*pegg_f:.1f}% (la put fa QUESTO); il maxDD invece " + f"{100*C._dd(nb/nb.shift(1)-1):.1f}% -> {100*best['dd']:.1f}% (i grind restano)") + + # ---- B3: l'invariante del disaster-SL con un pavimento: licenza di carta ------------------ + print("\n B3 L'INVARIANTE DEL DISASTER-SL con un pavimento — licenza di CARTA.") + frac, sl = 0.50, 0.30 + k_inv = 0.50 / (2 * frac * sl) + print(f" oggi: n_asset 2 x frac {frac} x scala x sl {sl} <= 0,50 => scala <= {k_inv:.2f}x") + for forte in (True,): + best = R[R["forte"] == forte].sort_values("sh", ascending=False).iloc[0] + cic = pd.DataFrame(best["cicli"] if "cicli" in best else []) + dirs = C.gate_trend(P, forte) + o = C.collar(P, cal, dput=best["dp"], dcall=0.2, tenor=best["tenor"], dirs=dirs, solo_pavimento=True) + cic = pd.DataFrame(o["cicli"]) + # distanza mediana del pavimento dallo spot all'apertura + cic["dist"] = (cic["S0"] - cic["Kl"]) / cic["S0"] * cic["dirn"] + dist = float(cic["dist"].abs().median()) + k_carta = 0.50 / (2 * frac * dist) + print(f" con la put a d{best['dp']:.2f}/{best['tenor']}g il pavimento sta a {100*dist:.1f}% " + f"dallo spot: sostituire sl con la distanza darebbe scala <= {k_carta:.2f}x ({k_carta/k_inv:.1f}x in piu')") + # ma la perdita su finestre CONSECUTIVE non e' limitata: la misuro + nf = best["nav"] + for n_fin in (1, 2, 4, 8): + g = n_fin * best["tenor"] + print(f" peggior perdita su {n_fin} finestre consecutive ({g:>3}g): " + f"{100*peggior_finestra(nf, g):.1f}% " + f"{'<= una finestra: la put copre' if n_fin == 1 else '-> la put NON copre: e'' un grind'}") + print(f" ⇒ la licenza {k_carta:.2f}x vale per UN crollo dentro UNA finestra; su un grind di " + f"{8*best['tenor']} giorni la perdita e' {100*abs(peggior_finestra(nf, 8*best['tenor'])):.0f}%, " + f"e a {k_carta:.1f}x farebbe {100*k_carta*abs(peggior_finestra(nf, 8*best['tenor'])):.0f}% dell'equity.") + + # ---- B4: pavimento GATED su IV a buon mercato ------------------------------------------- + print("\n B4 PAVIMENTO GATED sull'IV — compro la put solo quando il premio di varianza e' sottile.") + print(" (§46: 'nessuna copertura dinamica gated su regime e'' stata provata' — qui lo e'.)") + lr = np.log(P["px"] / P["px"].shift(1)) + rv30 = (lr.rolling(30).std() * math.sqrt(DPY)) + ratio = (P["iv"] / rv30) # DVOL / RV trailing: quanto e' cara la vol OGGI + pct = ratio.rolling(365, min_periods=90).rank(pct=True) + for forte in (True, False): + dirs = C.gate_trend(P, forte) + nm = "FORTE" if forte else "LARGO" + base = C.collar(P, cal, dput=0.2, dcall=0.2, tenor=7, dirs=dirs, senza_opzioni=True) + rb = base["ret"]; dd_b, dr_b = C._dd(rb), C._drift(rb) + best = R[R["forte"] == forte].sort_values("sh", ascending=False).iloc[0] + for soglia in (0.25, 0.50): + # NOTA: il gate di IV si applica alla PUT, non alla posizione. Lo simulo con due + # strutture (protetta / nuda) e le incollo giorno per giorno sul segnale di IV, pagando + # lo spread alle transizioni tramite il motore stesso (ricalcolo con dirs modulati). + economico = (pct.shift(1) <= soglia).reindex(P.index).fillna(False).values + r_prot = best["ret"].reindex(P.index) + r_nuda = rb.reindex(P.index) + r_mix = pd.Series(np.where(economico, r_prot, r_nuda), index=P.index).dropna() + dd, dr = C._dd(r_mix), C._drift(r_mix) + kf = k_up_for_same_dd(r_mix.values, dd_b) + dr_kf = C._drift(kf * r_mix.values) + quota = 100.0 * np.mean(economico[np.asarray(dirs) != 0]) if np.any(np.asarray(dirs) != 0) else 0.0 + print(f" {nm} put ON se DVOL/RV sotto il {100*soglia:.0f}° pctl (ON il {quota:.0f}% dei giorni a mercato): " + f"Sh {C._sh(r_mix):.3f} DD {100*dd:.2f}% drift {100*dr:+.2f}% | licenza k_f {kf:.3f} " + f"-> drift {100*dr_kf:+.2f}% vs base {100*dr_b:+.2f}% {'VINCE' if dr_kf > dr_b else 'perde'}") + print(" ⚠️ approssimazione dichiarata: l'incollatura ignora lo spread delle transizioni ON/OFF " + "della put (a favore del gated). Se perde COSI', perde a maggior ragione.") + + # ---- IL PREMIO DI PAREGGIO: quanto dovrebbe costare la put perche' il pavimento protegga? -- + print("\n PREMIO DI PAREGGIO — a quale frazione del premio REALE il pavimento pareggia il maxDD nudo.") + print(" (Il DVOL sta 1,32x sopra la RV-forward: un prezzo 'equo' sarebbe ~76% del reale.)") + pareggi = [] + for forte in (True, False): + dirs = C.gate_trend(P, forte) + nm = "FORTE" if forte else "LARGO" + base = C.collar(P, cal, dput=0.2, dcall=0.2, tenor=7, dirs=dirs, senza_opzioni=True)["ret"] + ddb = C._dd(base) + for tenor, dp in ((14, 0.05), (14, 0.10), (7, 0.10), (14, 0.20)): + lo, hi = 0.0, 1.0 + for _ in range(25): + md = 0.5 * (lo + hi) + r = C.collar(P, cal, dput=dp, dcall=0.2, tenor=tenor, dirs=dirs, + solo_pavimento=True, prem_scale=md)["ret"] + if C._dd(r) < ddb: + lo = md + else: + hi = md + pareggi.append(0.5 * (lo + hi)) + print(f" {nm} d{dp:.2f}/{tenor}g: pareggio del maxDD a **{100*0.5*(lo+hi):.0f}%** del premio reale") + print(f" ⇒ banda {100*min(pareggi):.0f}-{100*max(pareggi):.0f}%: il mercato dovrebbe scontare la put del " + f"{100*(1-max(pareggi)):.0f}-{100*(1-min(pareggi)):.0f}% perche' il pavimento INIZI a proteggere.") + + # ---- VERDETTO A RUNTIME ----------------------------------------------------------------- + print("\n" + "=" * 96) + if n_lic == 0: + v = ("IL PAVIMENTO NON LICENZIA TAGLIA A PREMIO REALE: 0 celle. Cio' che il de-levering non " + "puo' comprare, la put lo vende a un prezzo che nessuna cella ripaga") + elif n_lic <= len(R) // 4: + v = f"MARGINALE: {n_lic}/{len(R)} celle — dentro il rumore di griglia, e sul bordo" + else: + v = f"IL PAVIMENTO LICENZIA TAGLIA in {n_lic}/{len(R)} celle — serve M2/DSR e il null di permutazione" + print(f" VERDETTO (calcolato a runtime): {v}") + print("=" * 96) + + +if __name__ == "__main__": + main()