research(goal50): matematica onesta del target 50eur/g + gate deploy pre-registrato statarb
- r0724_goal50_math: muro capitale (73-228k), leva=rovina, Monte Carlo prop-firm sui ritorni reali del book (P(pass) 56-86%, funded 100k mediana 31-42eur/g), vault TVL 1-2M. Unica via 'da mesi' = moltiplicare nozionale gestito. - r0724_statarb_deploy_gate: regola di deploy PRE-REGISTRATA a fwd-day 25 (decisione 2026-09-27, Sh>=0.5, haircut<0.5pp, 1 proroga max) — anti selection-on-forward. - diario roadmap (sezioni web-research da completare). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
# 2026-07-24 — Goal "50 EUR/giorno in qualche mese": analisi onesta e roadmap
|
||||
|
||||
**Contesto.** Goal dichiarato: rendita aggiuntiva che arrivi a **50 EUR/giorno entro qualche
|
||||
mese**, senza precludere alcuna modalità. Branch `goal/50eur-day`. Questo diario è la sintesi
|
||||
di: matematica del target sui ritorni reali del book, Monte Carlo prop-firm, 3 ricerche web
|
||||
parallele (prop firm 2026, yield/basis a piccola scala, monetizzazione del track record),
|
||||
e audit delle migliorie interne possibili.
|
||||
|
||||
**Verdetto in una riga:** 50 EUR/g = **EUR 18.250/anno**; ai CAGR onesti del book (10-20%)
|
||||
servono **EUR 73k-183k di capitale**. Da $600 in "qualche mese" per via di trading sul
|
||||
capitale proprio **non esiste** — l'unica famiglia di vie compatibile con "mesi" è
|
||||
**moltiplicare il nozionale gestito** (conto funded / capitale di terzi), ognuna con
|
||||
probabilità e rischi quantificati sotto.
|
||||
|
||||
---
|
||||
|
||||
## A) Il muro del capitale (script `r0724_goal50_math.py`, parte A)
|
||||
|
||||
| CAGR netto | capitale per 50 EUR/g |
|
||||
|---|---|
|
||||
| 8% | ~EUR 228k |
|
||||
| 10% | ~EUR 182k |
|
||||
| 15% | ~EUR 122k |
|
||||
| 20% | ~EUR 91k |
|
||||
| 25% | ~EUR 73k |
|
||||
|
||||
Tempo da $600 (CAGR 15%, compounding + depositi mensili): **0/mese → 38.7 anni; 500/mese →
|
||||
9.6 anni; 1.000/mese → 6.3 anni; 2.000/mese → 3.8 anni; 5.000/mese → 1.8 anni.**
|
||||
|
||||
## B) La leva non è la scorciatoia (parte B)
|
||||
|
||||
Book Deribit live (TP01 .75 + SKH01 .25, modellato): Sharpe 1.77, **vol nativa ~11%**,
|
||||
CAGR 20.5%, maxDD 9.4%. Il target su capitale piccolo implica: $600 → 3.315%/anno
|
||||
(leva ~160x); $5k → 398%/anno (~19x, vol ~212%); $20k → 99%/anno (~4.8x, vol ~53%).
|
||||
Tutte fuori dalla zona di sopravvivenza (Kelly documentato: il book gira a ~0.01-0.27 Kelly).
|
||||
La frontiera 2026-07-03 ha già stabilito che il book gira alla sua vol nativa — alzare
|
||||
`target_vol` scala DD in proporzione, non crea rendimento.
|
||||
|
||||
## C) Prop-firm / conto funded — l'unica via "da mesi" quantificabile (parte C)
|
||||
|
||||
Monte Carlo (block bootstrap 20g dei ritorni giornalieri reali del book, 20k path,
|
||||
regole tipiche: target 8-10%, maxDD 10% statico/trailing, daily loss 4-5%):
|
||||
|
||||
| scenario | leva eval | P(pass entro 1a) | mediana giorni |
|
||||
|---|---|---|---|
|
||||
| book modellato | 1.0x | 81-86% | 111-132 g |
|
||||
| book modellato | 1.5x | 78-85% | **72-89 g** |
|
||||
| book modellato | 2.0x | 72-81% | 46-62 g |
|
||||
| de-luck ×0.6 | 1.0x | 63-72% | 113-137 g |
|
||||
| de-luck ×0.6 | 1.5x | 62-71% | **70-87 g** |
|
||||
| de-luck ×0.6 | 2.0x | 56-65% | 43-58 g |
|
||||
|
||||
Fase funded ($100k nozionale, split 80%, 1 anno): **modellato** P(conto vivo) 88.9%,
|
||||
payout p10/p50/p90 = EUR 8.9/42.3/93.4 al giorno; **de-luck ×0.6** P(vivo) 67.7%,
|
||||
p10/p50/p90 = EUR 1.3/**31.1**/77.9 al giorno. A $200k nozionale i payout raddoppiano
|
||||
(mediana de-luck ~EUR 62/g) — il target dei 50 EUR/g sta tra $150k e $200k funded.
|
||||
|
||||
**Caveat onesti:** (1) daily-loss simulato su barre daily → i wick intraday rendono le
|
||||
P(pass) OTTIMISTE; (2) le regole reali (consistency, min trading days, divieto bot/API,
|
||||
weekend) possono uccidere lo stile low-frequency → vedi ricerca firm 2026 sotto;
|
||||
(3) payout = reddito VOLATILE, non "rendita" (p10 de-luck ≈ EUR 1/g).
|
||||
|
||||
## D) Vault / copy-trading (parte D)
|
||||
|
||||
A perf-share 10% sopra HWM servono **$1-2M di TVL altrui** per 50 EUR/g → richiede anni
|
||||
di track record pubblico, non mesi. Vincolo legale per residente italiano (gestione di
|
||||
capitale altrui = art. 166 TUF) approfondito nella ricerca dedicata sotto.
|
||||
|
||||
---
|
||||
|
||||
## Migliorie interne implementate/decise oggi
|
||||
|
||||
1. **Gate di deploy PRE-REGISTRATO per STATARB-RESID** (`r0724_statarb_deploy_gate.py`).
|
||||
Forward a oggi: 25 barre, +4.42%, Sharpe fwd +5.84 (caldissimo → regredirà), DD 1.4%,
|
||||
haircut 0.01pp. Regola fissata OGGI (day 25) per evitare selection-on-forward:
|
||||
**decisione il 2026-09-27 (90g)**; Sh≥0.5 → candidato deploy (pesi {10,15,20}% via
|
||||
`weights_tilt_null`, maxDD combinato <15%); 0≤Sh<0.5 → UNA proroga di 90g; Sh<0 → ritiro.
|
||||
Guardie: haircut <0.5pp, config congelata (W=45, sgn=+1), DD fwd <10%.
|
||||
2. **Audit infra:** i messaggi "open/completed orders request timed out" nel cron daily sono
|
||||
warning benigni di `ib_async` al connect col Gateway IB (conto paper DU) — cosmetici,
|
||||
nessuna azione. Book live 743/743 giri completati; errori cerbero-mcp solo storici.
|
||||
3. **Conferme di sistema (non ri-litigate):** soffitto direzionale ~1.3 (10+ ondate);
|
||||
book già quasi-risk-parity; alzare vol = de-levering inverso (frontiera 2026-07-03);
|
||||
il vincolo binding è il CAPITALE, non la ricerca. Il cap dinamico equity/2 è già
|
||||
pronto ad assorbire depositi.
|
||||
|
||||
## Ricerche web (3 agenti paralleli) — RISULTATI
|
||||
|
||||
_(sezione completata sotto, dopo il rientro degli agenti)_
|
||||
|
||||
## Roadmap
|
||||
|
||||
_(sintesi finale dopo i risultati degli agenti)_
|
||||
@@ -0,0 +1,196 @@
|
||||
"""r0724_goal50_math — la matematica ONESTA del target 50 EUR/giorno (2026-07-24).
|
||||
|
||||
Domanda del goal: "rendita aggiuntiva che entro qualche mese arrivi a 50 EUR/giorno".
|
||||
Questo script NON cerca un edge nuovo: quantifica le vie possibili col book che ABBIAMO,
|
||||
usando i rendimenti giornalieri REALI del book Deribit (TP01 0.75 + SKH01 0.25) e
|
||||
scenari de-luckati. Quattro parti:
|
||||
|
||||
A) IL MURO — capitale richiesto per 50 EUR/g ai CAGR onesti; tempo da 600$ con depositi.
|
||||
B) LA LEVA NON E' LA SCORCIATOIA — vol/DD implicati dal target su capitale piccolo.
|
||||
C) PROP-FIRM EVAL — Monte Carlo (block bootstrap dei ritorni reali del book) di una
|
||||
evaluation tipo crypto-prop: P(pass), giorni mediani, poi fase funded su 100k$:
|
||||
distribuzione EUR/giorno e P(perdere il conto entro 1 anno).
|
||||
D) VAULT / COPY — TVL necessario per 50 EUR/g a perf-share 10%.
|
||||
|
||||
Onesta': i ritorni del book sono MODELLATI (il path live SKH01 e' peggiore: FULL 1.19/
|
||||
HOLD 1.15/DD~25% vs modellato ~1.4-1.6) -> ogni scenario gira anche con haircut sul
|
||||
drift (x0.6) per il de-luck. EURUSD assunto 1.09 (parametro).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
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))
|
||||
|
||||
from src.portfolio.portfolio import StrategyPortfolio, metrics # noqa: E402
|
||||
from src.portfolio.sleeves import deribit_book_sleeves # noqa: E402
|
||||
|
||||
EURUSD = 1.09 # 1 EUR = 1.09 USD (assunzione dichiarata)
|
||||
TARGET_EUR_DAY = 50.0
|
||||
TARGET_EUR_YR = TARGET_EUR_DAY * 365
|
||||
TARGET_USD_YR = TARGET_EUR_YR * EURUSD
|
||||
RNG = np.random.default_rng(724)
|
||||
|
||||
|
||||
def eur_day(usd_yr: float) -> float:
|
||||
return usd_yr / EURUSD / 365.0
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------- A
|
||||
def part_a() -> None:
|
||||
print("=" * 100)
|
||||
print(f" A) IL MURO — 50 EUR/g = {TARGET_EUR_YR:,.0f} EUR/anno = ${TARGET_USD_YR:,.0f}/anno")
|
||||
print("=" * 100)
|
||||
print(" capitale richiesto (rendita = capitale x CAGR netto):")
|
||||
for cagr in (0.08, 0.10, 0.15, 0.20, 0.25):
|
||||
cap = TARGET_USD_YR / cagr
|
||||
print(f" CAGR {cagr:>4.0%} -> capitale ${cap:>10,.0f} (~EUR {cap / EURUSD:,.0f})")
|
||||
print("\n tempo per arrivarci da $600 (compounding mensile + deposito mensile, CAGR 15%):")
|
||||
for dep in (0, 500, 1000, 2000, 5000):
|
||||
eq, months = 600.0, 0
|
||||
target_cap = TARGET_USD_YR / 0.15
|
||||
while eq < target_cap and months < 12 * 60:
|
||||
eq = eq * (1 + 0.15) ** (1 / 12) + dep * EURUSD
|
||||
months += 1
|
||||
yrs = months / 12
|
||||
lab = f"{yrs:.1f} anni" if months < 720 else ">60 anni"
|
||||
print(f" deposito EUR {dep:>5}/mese -> {lab}")
|
||||
print("\n VERDETTO A: da $600, 'qualche mese' per compounding NON esiste. Il capitale")
|
||||
print(" proprio arriva al target solo con depositi da migliaia/mese per molti anni.")
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------- B
|
||||
def part_b(book: pd.Series) -> None:
|
||||
m = metrics(book)
|
||||
print("\n" + "=" * 100)
|
||||
print(" B) LA LEVA NON E' LA SCORCIATOIA")
|
||||
print("=" * 100)
|
||||
sh = m["sharpe"]
|
||||
vol = book.std() * np.sqrt(365)
|
||||
cagr = (1 + book).prod() ** (365 / len(book)) - 1
|
||||
print(f" book Deribit (TP01 .75 + SKH01 .25) modellato: Sharpe {sh:.2f} vol {vol:.0%} CAGR {cagr:.1%}")
|
||||
for cap_usd in (600, 2000, 5000, 20000):
|
||||
need = TARGET_USD_YR / cap_usd # rendimento annuo richiesto
|
||||
lev = need / max(cagr, 1e-9) # multiplo di leva sul book
|
||||
vol_imp = vol * lev
|
||||
print(f" su ${cap_usd:>6,}: servono {need:>7.0%}/anno -> leva ~{lev:>5.1f}x il book "
|
||||
f"-> vol implicita ~{vol_imp:>6.0%} -> rovina quasi certa" if lev > 3 else
|
||||
f" su ${cap_usd:>6,}: servono {need:>7.0%}/anno -> leva ~{lev:>5.1f}x il book "
|
||||
f"-> vol implicita ~{vol_imp:>6.0%}")
|
||||
print(" VERDETTO B: il target su capitale piccolo implica vol a 3 cifre = rovina.")
|
||||
print(" (Kelly gia' documentato: il book gira a ~0.01-0.27 Kelly a seconda dello sleeve.)")
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------- C
|
||||
def _block_bootstrap_paths(r: np.ndarray, n_days: int, n_paths: int, block: int = 20,
|
||||
drift_scale: float = 1.0) -> np.ndarray:
|
||||
"""Percorsi bootstrap a blocchi dai ritorni giornalieri reali del book.
|
||||
|
||||
drift_scale < 1 = haircut de-luck: riduce la media conservando la vol
|
||||
(r' = (r - mu) + mu*scale).
|
||||
"""
|
||||
mu = r.mean()
|
||||
r_adj = (r - mu) + mu * drift_scale
|
||||
n = len(r_adj)
|
||||
n_blocks = int(np.ceil(n_days / block))
|
||||
starts = RNG.integers(0, n - block, size=(n_paths, n_blocks))
|
||||
idx = (starts[:, :, None] + np.arange(block)[None, None, :]).reshape(n_paths, -1)[:, :n_days]
|
||||
return r_adj[idx]
|
||||
|
||||
|
||||
def _simulate_eval(paths: np.ndarray, target: float, max_dd: float, daily_loss: float,
|
||||
trailing: bool, max_days: int) -> dict:
|
||||
"""Simula una evaluation: passa se equity tocca (1+target) prima di violare
|
||||
il max drawdown (statico da 1.0 o trailing dal max) o il daily loss limit."""
|
||||
n_paths, n_days = paths.shape
|
||||
eq = np.cumprod(1 + paths, axis=1)
|
||||
hwm = np.maximum.accumulate(np.maximum(eq, 1.0), axis=1) if trailing else 1.0
|
||||
dd_breach = eq < (hwm * (1 - max_dd) if trailing else (1 - max_dd))
|
||||
dl_breach = paths < -daily_loss
|
||||
fail = dd_breach | dl_breach
|
||||
passed = eq >= 1 + target
|
||||
|
||||
first_fail = np.where(fail.any(axis=1), fail.argmax(axis=1), max_days + 1)
|
||||
first_pass = np.where(passed.any(axis=1), passed.argmax(axis=1), max_days + 1)
|
||||
ok = first_pass < first_fail
|
||||
p_pass = ok.mean()
|
||||
days = np.median(first_pass[ok]) if ok.any() else np.nan
|
||||
return {"p_pass": p_pass, "median_days": days,
|
||||
"p_fail": (first_fail <= np.minimum(first_pass, max_days)).mean()}
|
||||
|
||||
|
||||
def part_c(book: pd.Series) -> None:
|
||||
print("\n" + "=" * 100)
|
||||
print(" C) PROP-FIRM EVALUATION — Monte Carlo sui ritorni REALI del book (block bootstrap 20g)")
|
||||
print("=" * 100)
|
||||
r = book.to_numpy()
|
||||
n_paths, max_days = 20_000, 365
|
||||
|
||||
rules = [
|
||||
("target 8% / DD 10% statico / daily 4%", 0.08, 0.10, 0.04, False),
|
||||
("target 10% / DD 10% statico / daily 5%", 0.10, 0.10, 0.05, False),
|
||||
("target 10% / DD 10% TRAILING / daily 5%", 0.10, 0.10, 0.05, True),
|
||||
]
|
||||
for drift_scale, lab in ((1.0, "book modellato"), (0.6, "de-luck x0.6 (onesto)")):
|
||||
base = _block_bootstrap_paths(r, max_days, n_paths, drift_scale=drift_scale)
|
||||
for lev in (1.0, 1.5, 2.0):
|
||||
paths = base * lev
|
||||
print(f"\n --- {lab}, leva eval x{lev:.1f} (vol ~{book.std() * np.sqrt(365) * lev:.0%}) ---")
|
||||
for name, tgt, dd, dl, tr in rules:
|
||||
res = _simulate_eval(paths, tgt, dd, dl, tr, max_days)
|
||||
d = f"{res['median_days']:.0f}g" if np.isfinite(res["median_days"]) else "n/a"
|
||||
print(f" {name:<44} P(pass entro 1a) {res['p_pass']:>5.1%} mediana {d}")
|
||||
|
||||
# fase funded: 100k, split 80%, anno di ritorni; conto perso se DD>10%
|
||||
print("\n --- fase FUNDED: $100k nozionale, split 80%, orizzonte 1 anno ---")
|
||||
for drift_scale, lab in ((1.0, "book modellato"), (0.6, "de-luck x0.6")):
|
||||
paths = _block_bootstrap_paths(r, 365, n_paths, drift_scale=drift_scale)
|
||||
eq = np.cumprod(1 + paths, axis=1)
|
||||
hwm = np.maximum.accumulate(np.maximum(eq, 1.0), axis=1)
|
||||
blown = (eq < hwm * 0.90) | (paths < -0.05)
|
||||
alive = ~blown.any(axis=1)
|
||||
pnl = (eq[:, -1] - 1) * 100_000 * 0.80
|
||||
pnl_alive = pnl[alive]
|
||||
q = np.percentile(pnl_alive, [10, 50, 90]) if alive.any() else [np.nan] * 3
|
||||
print(f" {lab:<24} P(conto vivo a 1a) {alive.mean():>5.1%} payout se vivo "
|
||||
f"p10/p50/p90: EUR {eur_day(q[0]) :>5.1f} / {eur_day(q[1]):>5.1f} / {eur_day(q[2]):>5.1f} al giorno")
|
||||
print("\n NB: regole reali (consistency, min trading days, no-bot) possono uccidere lo stile")
|
||||
print(" low-frequency — il verdetto finale dipende dalla ricerca web sulle firm 2026.")
|
||||
|
||||
|
||||
# ----------------------------------------------------------------------------- D
|
||||
def part_d() -> None:
|
||||
print("\n" + "=" * 100)
|
||||
print(" D) VAULT / COPY-TRADING — perf-share 10% sopra HWM")
|
||||
print("=" * 100)
|
||||
for cagr in (0.10, 0.15, 0.20):
|
||||
tvl = TARGET_USD_YR / (cagr * 0.10)
|
||||
print(f" CAGR {cagr:.0%}: per 50 EUR/g servono ${tvl / 1e6:,.1f}M di TVL altrui")
|
||||
print(" VERDETTO D: TVL a 7 cifre richiede anni di track record pubblico, non mesi.")
|
||||
|
||||
|
||||
def main() -> None:
|
||||
port = StrategyPortfolio(deribit_book_sleeves())
|
||||
book = port.combined_daily().dropna()
|
||||
book = book[book.index >= "2019-03-01"]
|
||||
m = metrics(book)
|
||||
print(f"book Deribit live (modellato): {len(book)} giorni {book.index[0].date()} -> "
|
||||
f"{book.index[-1].date()} Sharpe {m['sharpe']:.2f} maxDD {m['maxdd']:.1%}")
|
||||
part_a()
|
||||
part_b(book)
|
||||
part_c(book)
|
||||
part_d()
|
||||
print("\n" + "=" * 100)
|
||||
print(" SINTESI ONESTA: 50 EUR/g in qualche mese e' fuori portata del capitale proprio.")
|
||||
print(" L'unica via quantificabile in MESI e' moltiplicare il nozionale gestito (prop/")
|
||||
print(" funded), con P(successo) e regole da verificare; tutto il resto e' anni+capitale.")
|
||||
print("=" * 100)
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
@@ -0,0 +1,79 @@
|
||||
"""r0724_statarb_deploy_gate — gate di deploy PRE-REGISTRATO per STATARB-RESID (2026-07-24).
|
||||
|
||||
PERCHE' PRE-REGISTRATO: la regola si fissa a forward-day 25 (oggi), PRIMA di vedere
|
||||
il giorno 90. Decidere "a occhio" dopo aver visto il numero = selection-on-forward,
|
||||
lo stesso bias che il progetto ha gia' pagato (gate SELECTION-ON-HOLDOUT, 2026-06-29).
|
||||
|
||||
REGOLA (immutabile — ogni modifica va motivata nel diario come violazione):
|
||||
- Data decisione: 2026-09-27 (90 giorni forward dal 2026-06-29). Non prima.
|
||||
- Metrica: Sharpe annualizzato di net_modeled su TUTTA la finestra forward
|
||||
(nessuna sottofinestra), da data/paper_statarb/returns.jsonl.
|
||||
- Esiti:
|
||||
Sharpe >= 0.5 -> CANDIDATO AL DEPLOY: proporre peso {10,15,20}% del book
|
||||
Deribit, giudicato con weights_tilt_null + stima maxDD
|
||||
combinata < 15%. Deploy solo se il tilt-null passa.
|
||||
0 <= Sh < 0.5 -> ESTENDI una sola volta di altri 90g (decisione 2026-12-26).
|
||||
Alla seconda scadenza: o >=0.5 o RITIRO. Niente terza proroga.
|
||||
Sharpe < 0 -> RITIRO dal forward-monitor (l'edge DSR 0.929 non ha confermato).
|
||||
- Guardie accessorie (tutte richieste per il deploy):
|
||||
* fill-haircut cumulato |MODELED - REAL| < 0.5 pp (eseguibilita' reale a $600);
|
||||
* config invariata (W=45, sgn=+1) — ogni ritocco azzera la finestra;
|
||||
* maxDD forward < 10% (coerenza col profilo di ricerca, DD backtest ~11%).
|
||||
|
||||
Uso: `uv run python scripts/research/r0724_statarb_deploy_gate.py`
|
||||
(si puo' lanciare in qualsiasi momento: ricorda la data-decisione e valuta lo stato).
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
import json
|
||||
from datetime import date
|
||||
from pathlib import Path
|
||||
|
||||
import numpy as np
|
||||
|
||||
ROOT = Path(__file__).resolve().parents[2]
|
||||
RETURNS = ROOT / "data" / "paper_statarb" / "returns.jsonl"
|
||||
|
||||
START = date(2026, 6, 29) # inizio forward (config congelata)
|
||||
DECISION = date(2026, 9, 27) # 90g forward — PRIMA data utile di decisione
|
||||
DECISION_EXT = date(2026, 12, 26) # unica proroga ammessa
|
||||
SH_DEPLOY = 0.5
|
||||
HAIRCUT_MAX_PP = 0.5
|
||||
DD_MAX = 0.10
|
||||
|
||||
|
||||
def main() -> None:
|
||||
rows = [json.loads(x) for x in RETURNS.read_text().splitlines() if x.strip()]
|
||||
rm = np.array([r["net_modeled"] for r in rows])
|
||||
rr = np.array([r["net_real"] for r in rows])
|
||||
n = len(rm)
|
||||
sh = float(rm.mean() / rm.std() * np.sqrt(365)) if rm.std() > 0 else 0.0
|
||||
eq = np.cumprod(1 + rm)
|
||||
dd = float(np.max((np.maximum.accumulate(eq) - eq) / np.maximum.accumulate(eq)))
|
||||
haircut_pp = abs(float((np.prod(1 + rm) - np.prod(1 + rr)) * 100))
|
||||
today = date.today()
|
||||
|
||||
print("=" * 88)
|
||||
print(" STATARB-RESID — gate di deploy PRE-REGISTRATO (fissato 2026-07-24, forward-day 25)")
|
||||
print("=" * 88)
|
||||
print(f" finestra forward : {rows[0]['dt'][:10]} -> {rows[-1]['dt'][:10]} ({n} barre)")
|
||||
print(f" Sharpe fwd (mod) : {sh:+.2f} (soglia deploy >= {SH_DEPLOY})")
|
||||
print(f" maxDD fwd : {dd:.1%} (guardia < {DD_MAX:.0%})")
|
||||
print(f" fill-haircut cum : {haircut_pp:.2f} pp (guardia < {HAIRCUT_MAX_PP} pp)")
|
||||
print(f" data decisione : {DECISION} (proroga unica: {DECISION_EXT})")
|
||||
if today < DECISION:
|
||||
print(f"\n -> NESSUNA DECISIONE OGGI ({today}): mancano {(DECISION - today).days} giorni.")
|
||||
print(" Il numero corrente NON autorizza deploy anticipato (regola pre-registrata).")
|
||||
else:
|
||||
if sh >= SH_DEPLOY and dd < DD_MAX and haircut_pp < HAIRCUT_MAX_PP:
|
||||
print("\n -> GATE SUPERATO: procedere con weights_tilt_null sui pesi candidati "
|
||||
"{10,15,20}% e stima maxDD combinata (<15%) prima del deploy.")
|
||||
elif sh >= 0:
|
||||
print("\n -> SOTTO SOGLIA ma >=0: estensione unica fino al "
|
||||
f"{DECISION_EXT} (se gia' estesa: RITIRO).")
|
||||
else:
|
||||
print("\n -> Sharpe forward NEGATIVO: RITIRO dal forward-monitor.")
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
Reference in New Issue
Block a user