research(wave-0822): lo scettico RITIRA il difetto di contabilita' (non esiste, bit-exact) e chiude oggi il gate del 22/12 — il meccanismo e' un filtro di frequenza
This commit is contained in:
@@ -186,10 +186,41 @@ def _d(s: pd.Series) -> pd.Series:
|
||||
_CRY_CACHE: dict = {}
|
||||
|
||||
|
||||
def _crypto(w_tp: float, w_skh: float) -> pd.DataFrame:
|
||||
key = (round(w_tp, 6), round(w_skh, 6))
|
||||
def _crypto_stressed(w_tp: float, w_skh: float, m_tp: float, m_skh: float) -> pd.DataFrame:
|
||||
"""Come `pc.crypto_daily_tuples` (minimo ESATTO sul path orario condiviso) ma con un taglio
|
||||
del DRIFT applicato alla singola gamba PRIMA di comporre il path. Serve perche' il minimo
|
||||
giornaliero non e' separabile per gamba: non si puo' tagliare il drift a valle."""
|
||||
(J,) = pc._hourly_legs()
|
||||
legs = {}
|
||||
for nm, (rc, wc, mult) in {"tp": ("tp_r", "tp_w", m_tp), "sk": ("skh_r", "skh_w", m_skh)}.items():
|
||||
r = J[rc].values.copy()
|
||||
w = J[wc].values.copy()
|
||||
if mult != 1.0:
|
||||
cut = (1.0 - mult) * r.mean()
|
||||
r = r - cut
|
||||
w = w - cut
|
||||
legs[nm] = (r, w)
|
||||
r_h = w_tp * legs["tp"][0] + w_skh * legs["sk"][0]
|
||||
w_h = w_tp * legs["tp"][1] + w_skh * legs["sk"][1]
|
||||
idx = J.index
|
||||
days = idx.floor("D")
|
||||
rows = []
|
||||
for day, pos in pd.Series(np.arange(len(idx)), index=days).groupby(level=0):
|
||||
sl = pos.values
|
||||
r = r_h[sl]
|
||||
wk = w_h[sl]
|
||||
cum = np.cumprod(1.0 + r)
|
||||
cum_prev = np.concatenate(([1.0], cum[:-1]))
|
||||
m = min(cum.min(), (cum_prev * (1.0 + wk)).min()) - 1.0
|
||||
rows.append((day, cum[-1] - 1.0, min(m, cum[-1] - 1.0)))
|
||||
return pd.DataFrame(rows, columns=["day", "R", "m"]).set_index("day")
|
||||
|
||||
|
||||
def _crypto(w_tp: float, w_skh: float, m_tp: float = 1.0, m_skh: float = 1.0) -> pd.DataFrame:
|
||||
key = (round(w_tp, 6), round(w_skh, 6), round(m_tp, 4), round(m_skh, 4))
|
||||
if key not in _CRY_CACHE:
|
||||
_CRY_CACHE[key] = pc.crypto_daily_tuples(w_tp, w_skh)
|
||||
_CRY_CACHE[key] = (pc.crypto_daily_tuples(w_tp, w_skh) if (m_tp == 1.0 and m_skh == 1.0)
|
||||
else _crypto_stressed(w_tp, w_skh, m_tp, m_skh))
|
||||
return _CRY_CACHE[key]
|
||||
|
||||
|
||||
@@ -221,11 +252,8 @@ def book_RG(w: dict, start: str = START_WIN,
|
||||
R = np.zeros(len(idx))
|
||||
M = np.zeros(len(idx))
|
||||
if w_tp > 0 or w_skh > 0:
|
||||
c = _crypto(w_tp, w_skh).reindex(idx)
|
||||
cr = c["R"].values
|
||||
if w_tp > 0 and dm.get("TP01", 1.0) != 1.0 or w_skh > 0 and dm.get("SKH01", 1.0) != 1.0:
|
||||
raise NotImplementedError("stress sul drift crypto: il minimo e' path-esatto, non separabile")
|
||||
R += cr
|
||||
c = _crypto(w_tp, w_skh, dm.get("TP01", 1.0), dm.get("SKH01", 1.0)).reindex(idx)
|
||||
R += c["R"].values
|
||||
M += c["m"].values
|
||||
for nm, fr in (("XS01", pc.xsec_daily_tuples()), ("VRP01", vrp_daily_tuples()),
|
||||
("GTAA01", gtaa_daily_tuples())):
|
||||
@@ -702,6 +730,28 @@ def main() -> None:
|
||||
print(" scoperta; se resta a drift 0, il vantaggio e' pura DECORRELAZIONE e non dipende da")
|
||||
print(" quell'ipotesi. Il numero, non la narrazione, dice quale delle due.")
|
||||
|
||||
hr("E-quater. LA DISTORSIONE CHE MI RIGUARDA — l'ottimo si appoggia a SKH01, e SKH01 e' lo")
|
||||
print(" sleeve con la FORTUNA D'ANCORA piu' grande da restituire. Il LOO del 26/07: l'ancora")
|
||||
print(" canonica gli regala 2/3 del contributo FULL (+0.43 -> +0.14) e il 70% dell'hold-out;")
|
||||
print(" l'audit 02/07 lo trova al 93-98° pctl di 23 offset, 'spike, non plateau'. Questa lente")
|
||||
print(" gira sull'ancora CANONICA e la banda non e' ri-misurabile qui -> il mio ottimo e'")
|
||||
print(" distorto A FAVORE di SKH01 e va detto PRIMA di leggerlo. Taglio del drift di SKH01:")
|
||||
print(f"\n {'drift SKH01':>13} {'config':>16} {'leva':>6} {'J':>7} {'J del LIVE':>11} "
|
||||
f"{'delta appaiato':>16}")
|
||||
for mult in (1.00, 0.66, 0.50, 0.33):
|
||||
dmt = (("SKH01", mult),)
|
||||
rows = [(w, lv, objective(w, lv, "HYRO", ev_idx, fu_idx, drift_mult=dmt))
|
||||
for w in top_w for lv in LEVS]
|
||||
w_, lv_, o_ = max(rows, key=lambda x: x[2]["J"])
|
||||
lvL, oL = max(((lv, objective({"TP01": 0.75, "SKH01": 0.25}, lv, "HYRO", ev_idx, fu_idx,
|
||||
drift_mult=dmt)) for lv in LEVS), key=lambda x: x[1]["J"])
|
||||
dd_, sd_ = paired_delta(w_, lv_, {"TP01": 0.75, "SKH01": 0.25}, lvL, "HYRO",
|
||||
ev_idx, fu_idx)
|
||||
print(f" {mult:>13.2f} {wkey(w_):>16} {lv_:>6.3f} {o_['J']:>7.3f} {oL['J']:>11.3f} "
|
||||
f"{dd_:>+11.3f} +-{sd_:.3f}")
|
||||
print(" NB: il taglio si applica anche al LIVE 75/25 (che ha SKH01 al 25%), quindi il delta e'")
|
||||
print(" un confronto onesto: entrambe le colonne perdono, la domanda e' quale perde di piu'.")
|
||||
|
||||
hr("E-ter. IL BUCO CHE LA FINESTRA NON PUO' CHIUDERE — 2024-2026 non contiene un CRASH")
|
||||
print(" L'ottimizzazione toglie peso a TP01 (Sharpe 0.79 su questa finestra). Ma TP01 e' lo")
|
||||
print(" sleeve DIFENSIVO: il LOO del 26/07 misura il suo contributo hold-out NEGATIVO nel 99.1%")
|
||||
|
||||
Reference in New Issue
Block a user