research(capitale): 3k o 5k -> ~3.7 mesi su 11.5 anni, non e' una decisione importante
r0727_3k_vs_5k.py. Domanda dell'operatore, poi ristretta a "fregatene del fuori": quanto versare su Deribit dei 6.043 EUR fermi in XEON. Tutto su Deribit, 500 EUR/mese, bersaglio 272.061$: 3.000 EUR -> 11.73 anni 4.000 -> 11.58 5.000 -> 11.42 6.043 -> 11.28 Ogni 1.000 EUR in piu' all'inizio vale ~1.8 MESI. P(entro 20a) 100% in tutti i casi. Il motivo strutturale: fino al traguardo entrano ~69.000 EUR di versamenti, quindi il versamento iniziale e' il 4-9% del flusso totale. La decisione che conta e' la SOSTENIBILITA' dei 500/mese (26/07: smettere al 5o anno porta P(muro) dal 90% al 53% = venti volte l'effetto misurato qui). Aggiunto anche il taglio con il venue dentro (quota fuori 46% vs 16%) e il fatto che con i versamenti su Deribit quella quota si DILUISCE: 4.0 anni di copertura versando 3k, 0.7 anni versando 5k -> la differenza fra i due e' temporanea, non una postura permanente. simulate() accetta dep_to (dove vanno i versamenti); replica del 26/07 preservata. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,158 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
"""r0727_3k_vs_5k.py — "ma quindi 3k o 5k?": la scelta e' a TOTALE FISSO, e ha una vita utile.
|
||||||
|
|
||||||
|
LA DOMANDA, RIFORMULATA. Non e' "quanto capitale metto a lavorare" ma **come divido un importo
|
||||||
|
gia' esistente**: il pozzo e' €6.043 (XEON) + il conto Deribit di oggi. Versarne 3k o 5k non
|
||||||
|
cambia il totale, cambia la QUOTA che resta fuori dall'exchange:
|
||||||
|
|
||||||
|
versare €3.000 -> dentro €3.550 (54%) · fuori €3.043 (46%)
|
||||||
|
versare €5.000 -> dentro €5.550 (84%) · fuori €1.043 (16%)
|
||||||
|
|
||||||
|
IL FATTO CHE DECIDE, E CHE MANCAVA. Con **€500/mese** in ingresso il pozzo iniziale viene
|
||||||
|
sommerso: dopo due anni sono entrati €12.000, il doppio dell'intero capitale di partenza. Se i
|
||||||
|
versamenti vanno su Deribit — che e' cio' che succede, perche' e' li' che sta il book — **la
|
||||||
|
quota tenuta fuori si diluisce da sola**, e la protezione comprata oggi ha una vita utile finita.
|
||||||
|
Misurare 3k-vs-5k assumendo che la quota resti costante (convenzione del 26/07) risponderebbe a
|
||||||
|
una domanda che nessuno sta facendo.
|
||||||
|
|
||||||
|
Si misurano quindi ENTRAMBE le convenzioni, perche' la differenza fra loro E' la risposta:
|
||||||
|
[MANTENUTA] i versamenti si ripartiscono per peso -> la quota fuori resta quella scelta oggi
|
||||||
|
[DILUITA] i versamenti vanno tutti su Deribit -> la quota fuori tende a zero
|
||||||
|
|
||||||
|
uv run python scripts/research/r0727_3k_vs_5k.py
|
||||||
|
"""
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
ROOT = Path(__file__).resolve().parents[2]
|
||||||
|
sys.path.insert(0, str(ROOT))
|
||||||
|
sys.path.insert(0, str(ROOT / "scripts" / "research"))
|
||||||
|
|
||||||
|
import r0725_capcurve as CC # noqa: E402
|
||||||
|
import r0726_venue_risk as VR # noqa: E402
|
||||||
|
import r0727_lumpsum_split as LS # noqa: E402
|
||||||
|
|
||||||
|
POZZO_EUR = 6_043.0 # XEON su Revolut
|
||||||
|
DEP_EUR = 500.0 # il piano dichiarato in config/live.json (26/07)
|
||||||
|
OPZIONI = (3_000.0, 5_000.0)
|
||||||
|
P_GRID = (0.0, 0.005, 0.01, 0.02, 0.05)
|
||||||
|
|
||||||
|
|
||||||
|
def quota_fuori(versato_eur: float) -> float:
|
||||||
|
dentro = LS.START + versato_eur * CC.EURUSD
|
||||||
|
fuori = (POZZO_EUR - versato_eur) * CC.EURUSD
|
||||||
|
return fuori / (dentro + fuori)
|
||||||
|
|
||||||
|
|
||||||
|
def anni_di_copertura(share0: float, dep_eur: float = DEP_EUR) -> float:
|
||||||
|
"""Quanti anni prima che la quota fuori scenda sotto il 10% (la soglia sotto cui, dalla
|
||||||
|
misura del 27/07, il salvataggio diventa marginale) se i versamenti vanno su Deribit.
|
||||||
|
Solo aritmetica dei flussi: ignora i rendimenti, che accelerano la diluizione."""
|
||||||
|
totale = LS.START + POZZO_EUR * CC.EURUSD
|
||||||
|
fuori = share0 * totale
|
||||||
|
dep = dep_eur * CC.EURUSD
|
||||||
|
for m in range(1, 601):
|
||||||
|
tot = totale + dep * m
|
||||||
|
if fuori / tot < 0.10:
|
||||||
|
return m / 12.0
|
||||||
|
return float("inf")
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
series = VR.venue_series()
|
||||||
|
zero = {**series, "IB": series["IB"] * 0.0} # seconda gamba = liquidita' ferma
|
||||||
|
totale = LS.START + POZZO_EUR * CC.EURUSD
|
||||||
|
|
||||||
|
print("=" * 100)
|
||||||
|
print(" r0727 — 3k o 5k? La scelta e' a TOTALE FISSO: cambia solo la quota fuori dall'exchange")
|
||||||
|
print("=" * 100)
|
||||||
|
print(f" pozzo €{POZZO_EUR:,.0f} (XEON) + conto ${LS.START:,.0f} = ${totale:,.0f} totali · "
|
||||||
|
f"versamento €{DEP_EUR:,.0f}/mese · orizzonte {LS.YEARS} anni")
|
||||||
|
print(f" bersaglio ${LS.TARGET:,.0f} · book live de-luckato ×{LS.DELUCK}")
|
||||||
|
|
||||||
|
print("\n " + "-" * 96)
|
||||||
|
print(f" {'versi':>8}{'dentro':>12}{'fuori':>12}{'quota fuori':>14}"
|
||||||
|
f"{'anni prima che scenda sotto il 10%':>38}")
|
||||||
|
for v in OPZIONI:
|
||||||
|
q = quota_fuori(v)
|
||||||
|
print(f" €{v:>7,.0f}{LS.START + v * CC.EURUSD:>11,.0f}${(POZZO_EUR - v) * CC.EURUSD:>11,.0f}$"
|
||||||
|
f"{q:>13.0%}{anni_di_copertura(q):>36.1f}")
|
||||||
|
print("\n ⚠️ Con i versamenti su Deribit la quota fuori si DILUISCE: e' cio' che rende la")
|
||||||
|
print(" differenza fra 3k e 5k un fatto temporaneo, non una postura permanente.")
|
||||||
|
|
||||||
|
for dep_to, etichetta in ((None, "MANTENUTA (versamenti ripartiti: la quota resta quella di oggi)"),
|
||||||
|
("Deribit", "DILUITA (versamenti su Deribit: la quota fuori tende a zero)")):
|
||||||
|
print("\n" + "=" * 100)
|
||||||
|
print(f" QUOTA {etichetta}")
|
||||||
|
print("=" * 100)
|
||||||
|
print(f"\n {'p annua':>8}", end="")
|
||||||
|
for v in OPZIONI:
|
||||||
|
print(f"{f'--- versi €{v:,.0f} ---':>34}", end="")
|
||||||
|
print()
|
||||||
|
print(f" {'':>8}", end="")
|
||||||
|
for _ in OPZIONI:
|
||||||
|
print(f"{'P(arriv)':>11}{'anni':>8}{'P(0) banca':>15}", end="")
|
||||||
|
print()
|
||||||
|
for p in P_GRID:
|
||||||
|
print(f" {p:>7.1%}", end="")
|
||||||
|
for v in OPZIONI:
|
||||||
|
q = quota_fuori(v)
|
||||||
|
cfg = {"Deribit": 1.0 - q, "IB": q}
|
||||||
|
r = LS.simulate(cfg, zero, {"Deribit": p, "IB": 0.0},
|
||||||
|
lump_usd=totale - LS.START, dep_eur=DEP_EUR, dep_to=dep_to)
|
||||||
|
yrs = f"{r['median_yrs']:.1f}a" if not np.isnan(r["median_yrs"]) else "mai"
|
||||||
|
print(f"{r['p_reach']:>11.1%}{yrs:>8}{r['p_all_dead']:>15.1%}", end="")
|
||||||
|
print()
|
||||||
|
|
||||||
|
print("\n" + "=" * 100)
|
||||||
|
print(" COSA COSTA DAVVERO LA DIFFERENZA")
|
||||||
|
print("=" * 100)
|
||||||
|
for p in (0.01, 0.02):
|
||||||
|
out = []
|
||||||
|
for v in OPZIONI:
|
||||||
|
q = quota_fuori(v)
|
||||||
|
cfg = {"Deribit": 1.0 - q, "IB": q}
|
||||||
|
out.append(LS.simulate(cfg, zero, {"Deribit": p, "IB": 0.0},
|
||||||
|
lump_usd=totale - LS.START, dep_eur=DEP_EUR, dep_to="Deribit"))
|
||||||
|
d_reach = (out[1]["p_reach"] - out[0]["p_reach"]) * 100
|
||||||
|
d_yrs = out[0]["median_yrs"] - out[1]["median_yrs"]
|
||||||
|
d_salv = out[0]["median_salvage"] - out[1]["median_salvage"]
|
||||||
|
print(f"\n p={p:.0%}: versare 5k invece di 3k -> P(arrivare) {d_reach:+.1f}pp, "
|
||||||
|
f"traguardo {d_yrs:+.2f} anni prima,")
|
||||||
|
print(f" salvataggio mediano ${out[1]['median_salvage']:,.0f} invece di "
|
||||||
|
f"${out[0]['median_salvage']:,.0f} (−${d_salv:,.0f})")
|
||||||
|
|
||||||
|
|
||||||
|
def solo_deribit() -> None:
|
||||||
|
"""La domanda spogliata dal venue: se tutto va su Deribit, quanto conta versare di piu'?
|
||||||
|
|
||||||
|
E' la lettura che l'operatore ha chiesto esplicitamente ("fregatene del fuori"), ed e' anche
|
||||||
|
quella che mostra il vero ordine di grandezza: con €500/mese il pozzo iniziale e' il 3-8%
|
||||||
|
del flusso totale, quindi la scelta fra 3k e 5k vale MESI, non anni.
|
||||||
|
"""
|
||||||
|
series = VR.venue_series()
|
||||||
|
print("\n" + "=" * 100)
|
||||||
|
print(" SENZA IL VENUE: tutto su Deribit, quanto vale versare di piu' all'inizio?")
|
||||||
|
print("=" * 100)
|
||||||
|
print(f"\n {'versi':>9}{'capitale iniziale':>20}{'anni al muro':>15}{'P(entro 20a)':>15}"
|
||||||
|
f"{'cap. mediano 20a':>20}")
|
||||||
|
base = None
|
||||||
|
for v in (3_000.0, 4_000.0, 5_000.0, POZZO_EUR):
|
||||||
|
r = LS.simulate({"Deribit": 1.0}, series, 0.0, lump_usd=v * CC.EURUSD, dep_eur=DEP_EUR)
|
||||||
|
base = base if base is not None else r["median_yrs"]
|
||||||
|
print(f" €{v:>8,.0f}{LS.START + v * CC.EURUSD:>19,.0f}${r['median_yrs']:>14.2f}a"
|
||||||
|
f"{r['p_reach']:>15.1%}{r['median_end']:>19,.0f}$")
|
||||||
|
print(f"\n Ogni €1.000 in piu' all'inizio vale ~1.8 MESI sul traguardo mediano.")
|
||||||
|
print(f" Fino al traguardo (~11.5 anni) a €{DEP_EUR:,.0f}/mese entrano "
|
||||||
|
f"€{DEP_EUR * 12 * 11.5:,.0f}: il versamento iniziale e' una frazione del flusso,")
|
||||||
|
print(" e la decisione che conta resta la SOSTENIBILITA' dei €500/mese (26/07: smettere")
|
||||||
|
print(" al 5° anno porta P(muro) dal 90% al 53% — venti volte l'effetto misurato qui).")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
solo_deribit()
|
||||||
@@ -80,7 +80,7 @@ IB_HAIRCUT_YR = 0.008 + 0.001
|
|||||||
|
|
||||||
def simulate(cfg: dict, series: dict, p_annual: float | dict, lump_usd: float = 0.0,
|
def simulate(cfg: dict, series: dict, p_annual: float | dict, lump_usd: float = 0.0,
|
||||||
dep_eur: float = 250.0, n_paths: int = N_PATHS, years: int = YEARS,
|
dep_eur: float = 250.0, n_paths: int = N_PATHS, years: int = YEARS,
|
||||||
seed: int = SEED) -> dict:
|
seed: int = SEED, dep_to: str | None = None) -> dict:
|
||||||
"""Accumulo con capitale iniziale `START + lump_usd` e jump di venue.
|
"""Accumulo con capitale iniziale `START + lump_usd` e jump di venue.
|
||||||
|
|
||||||
Generalizza `r0726_venue_risk.simulate` sul capitale iniziale, sul deposito e sul rischio
|
Generalizza `r0726_venue_risk.simulate` sul capitale iniziale, sul deposito e sul rischio
|
||||||
@@ -90,6 +90,11 @@ def simulate(cfg: dict, series: dict, p_annual: float | dict, lump_usd: float =
|
|||||||
`p_annual` puo' essere un dict {venue: p}: un conto bancario/liquidita' NON fallisce come un
|
`p_annual` puo' essere un dict {venue: p}: un conto bancario/liquidita' NON fallisce come un
|
||||||
exchange (tutela dei depositi fino a €100k), e attribuirgli lo stesso hazard e' una scelta
|
exchange (tutela dei depositi fino a €100k), e attribuirgli lo stesso hazard e' una scelta
|
||||||
CONSERVATIVA contro lo split — che va poi misurata, non assunta.
|
CONSERVATIVA contro lo split — che va poi misurata, non assunta.
|
||||||
|
|
||||||
|
`dep_to`: dove vanno i VERSAMENTI. None = ripartiti per peso fra i superstiti (convenzione
|
||||||
|
del 26/07, mantiene la quota costante); un nome di venue = tutti li'. La differenza non e'
|
||||||
|
cosmetica: con versamenti concentrati su un venue la quota tenuta fuori si DILUISCE nel
|
||||||
|
tempo, e la protezione iniziale ha una vita utile finita.
|
||||||
"""
|
"""
|
||||||
rng = np.random.default_rng(seed)
|
rng = np.random.default_rng(seed)
|
||||||
n_days = years * 365
|
n_days = years * 365
|
||||||
@@ -119,7 +124,12 @@ def simulate(cfg: dict, series: dict, p_annual: float | dict, lump_usd: float =
|
|||||||
if jm.any():
|
if jm.any():
|
||||||
salvage[jm] = cap[jm].sum(axis=1)
|
salvage[jm] = cap[jm].sum(axis=1)
|
||||||
if t % 30 == 0 and t > 0 and dep > 0:
|
if t % 30 == 0 and t > 0 and dep > 0:
|
||||||
wa = alive * w0
|
if dep_to is None:
|
||||||
|
wa = alive * w0
|
||||||
|
else: # tutti i versamenti su un venue solo
|
||||||
|
wa = np.zeros_like(cap)
|
||||||
|
wa[:, names.index(dep_to)] = 1.0
|
||||||
|
wa = wa * alive
|
||||||
tot = wa.sum(axis=1, keepdims=True)
|
tot = wa.sum(axis=1, keepdims=True)
|
||||||
share = np.divide(wa, tot, out=np.zeros_like(wa), where=tot > 0)
|
share = np.divide(wa, tot, out=np.zeros_like(wa), where=tot > 0)
|
||||||
cap += dep * share
|
cap += dep * share
|
||||||
|
|||||||
Reference in New Issue
Block a user