research(gtaa): l'assenza di API DEGIRO vale -0.02 di Sharpe, non e' squalificante
Domanda dell'operatore: "degiro ha api?". Fatto: no, non ufficiale; Revolut nemmeno (la sua e' per pagamenti); IB si'. I wrapper non ufficiali girano su credenziali + seed 2FA e si rompono IN SILENZIO a ogni cambio di front-end — e il progetto ha gia' pagato quel prezzo con fresh_5m il 26/07. Un esecutore che puo' rompersi senza dirlo e' peggio dell'esecuzione manuale. Misurato il costo di NON automatizzare invece di discuterlo: carico operativo: 15 settimane/anno con >=1 ordine (29% dei controlli, 1.4 per volta) ritardo 1g -0.02 Sharpe (peggiora in 6/11 anni = moneta) ritardo 3g -0.13 ritardo 10g -0.27 Il costo non e' il ritardo tipico ma la coda: il rischio dell'operativita' manuale e' la dimenticanza, e si copre con un allarme, non con una API (gtaa_rebalance_plan esiste gia' in produzione ed e' nato per un esecutore). Nota di metodo: sulla finestra UCITS di 3.2 anni la curva del ritardo NON e' monotona (5g -0.26, 10g -0.13) -> il campione corto non risolve differenze di questa taglia, quindi il numero si legge sulla finestra lunga a 10 anni, dove lo e'. Book, pesi, cron, config INVARIATI. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01XBbYmiXqbUNuGpK9sfbsGp
This commit is contained in:
@@ -174,6 +174,61 @@ def main() -> None:
|
||||
print(" controllo (2) su 10 anni e veicoli diversi, ma GTAA01 non e' deployabile prima dei")
|
||||
print(" $20k (decisione venue 26/07): c'e' tempo per validarla come si deve.")
|
||||
|
||||
# ---------- (5-bis) l'esecuzione MANUALE e' sostenibile? ----------
|
||||
print("\n" + "=" * 100)
|
||||
print(" (5-bis) SE IL BROKER NON HA UNA API — quanto costa eseguire a mano")
|
||||
print("=" * 100)
|
||||
print(" DEGIRO non espone una API di trading ufficiale; Revolut nemmeno (la sua API e' per")
|
||||
print(" pagamenti). Esistono wrapper non ufficiali degli endpoint interni, ma girano su")
|
||||
print(" credenziali + seed 2FA e si rompono in SILENZIO a ogni cambio di front-end — e questo")
|
||||
print(" progetto ha gia' pagato una volta il prezzo di un guasto silenzioso (fresh_5m, 26/07).")
|
||||
print(" Quindi la domanda giusta non e' 'si puo' automatizzare' ma 'quanto costa NON farlo'.")
|
||||
per_bar = None
|
||||
band_c = BAND_FRAC * CAP / 6.0
|
||||
for k in dep:
|
||||
_, pos = U.leg_returns(dep[k], dep[k], cal, CAP / 6.0, band_c, can_every,
|
||||
U.cost_form(fixed=1.0))
|
||||
o = (pos.diff().abs() > 1e-12).astype(int)
|
||||
per_bar = o if per_bar is None else per_bar + o
|
||||
anni = len(cal) / 252.0
|
||||
att = int((per_bar > 0).sum())
|
||||
print(f"\n Carico operativo a ${CAP:,.0f} (banda {BAND_FRAC:.0%}, controllo settimanale):")
|
||||
print(f" controlli/anno {len(cal)/5/anni:.0f}")
|
||||
print(f" settimane con >=1 ordine/anno {att/anni:.0f} ({att/(len(cal)/5):.0%} dei controlli)")
|
||||
print(f" ordini per settimana attiva {per_bar[per_bar > 0].mean():.1f} "
|
||||
f"(max {int(per_bar.max())})")
|
||||
|
||||
print("\n Costo del RITARDO di esecuzione — veicoli USA, finestra lunga "
|
||||
f"({len(cal_us)/252:.0f} anni), perche' su 3.2 anni la curva non risulta monotona")
|
||||
print(" (cioe' il campione corto non risolve differenze di questa taglia):")
|
||||
print(f"\n {'ritardo':>10s}{'Sharpe':>9s}{'CAGR':>9s}{'dSharpe':>10s} stabilita' per anno")
|
||||
base_sh, base_s = None, None
|
||||
for d in (0, 1, 2, 3, 5, 10):
|
||||
cols = {}
|
||||
for k in us:
|
||||
_, pos = U.leg_returns(us[k], us[k], cal_us, CAP / 6.0, band_c, can_every,
|
||||
U.cost_form(fixed=1.0))
|
||||
px = U._norm(us[k]).reindex(cal_us).ffill().values.astype(float)
|
||||
ret = np.zeros(len(px))
|
||||
ret[1:] = px[1:] / px[:-1] - 1.0
|
||||
p = pos.shift(d).fillna(0.0).values
|
||||
c = (pos.diff().abs() > 1e-12).astype(float).shift(d).fillna(0.0).values / (CAP / 6.0)
|
||||
cols[k] = __import__("pandas").Series(p * ret - c, index=cal_us)
|
||||
s = __import__("pandas").concat(cols, axis=1).mean(axis=1)
|
||||
m = U.met(s)
|
||||
if base_sh is None:
|
||||
base_sh, base_s = m["sharpe"], s.copy()
|
||||
peggio = sum(1 for y, g in s.groupby(s.index.year)
|
||||
if len(g) > 100 and U.met(g)["sharpe"] < U.met(base_s[base_s.index.year == y])["sharpe"])
|
||||
tot = sum(1 for y, g in s.groupby(s.index.year) if len(g) > 100)
|
||||
print(f" {str(d)+' giorni':>10s}{m['sharpe']:>9.2f}{m['cagr']:>8.2%}"
|
||||
f"{m['sharpe']-base_sh:>+10.2f} peggiora in {peggio}/{tot} anni")
|
||||
print("\n LETTURA: eseguire il giorno stesso o il giorno dopo costa ~nulla (-0.02, e peggiora")
|
||||
print(" in 6/11 anni = moneta). Il costo NON e' il ritardo tipico ma la CODA: dieci giorni")
|
||||
print(" valgono -0.27, cioe' quasi un terzo dello sleeve. Il rischio dell'operativita' manuale")
|
||||
print(" non e' la lentezza, e' la DIMENTICANZA — e quella si compra con un ALLARME, non con")
|
||||
print(" una API: `gtaa_rebalance_plan()` esiste gia' in produzione ed e' nato per un esecutore.")
|
||||
|
||||
# ---------- (5) cosa cercare sul proprio conto ----------
|
||||
print("\n" + "=" * 100)
|
||||
print(" (5) COSA CERCARE SUL PROPRIO BROKER — per ISIN, non per ticker")
|
||||
|
||||
Reference in New Issue
Block a user