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:
Adriano Dal Pastro
2026-07-27 11:05:33 +00:00
parent 842b0e865b
commit d0c804ebfc
3 changed files with 135 additions and 0 deletions
+16
View File
@@ -1120,6 +1120,22 @@ Prima ondata di ricerca onesta su BTC/ETH certificati (5 track, harness condivis
**LEZIONE: una raccomandazione poggiata su un fatto non verificato sul conto reale vale quanto **LEZIONE: una raccomandazione poggiata su un fatto non verificato sul conto reale vale quanto
quel fatto** — due volte in due giorni un'assunzione sul conto ha cambiato la conclusione (prima quel fatto** — due volte in due giorni un'assunzione sul conto ha cambiato la conclusione (prima
la negoziabilita' PRIIPs, poi quale conto e' davvero operativo). la negoziabilita' PRIIPs, poi quale conto e' davvero operativo).
(e) **"degiro ha api?" — NO, e costa 0.02 di Sharpe.** DEGIRO non espone una API di trading
ufficiale al retail; Revolut nemmeno (la sua e' per pagamenti); IB si'. I wrapper NON ufficiali
degli endpoint interni girano su credenziali + seed 2FA e **si rompono in silenzio** a ogni cambio
di front-end — e il progetto ha gia' pagato quel prezzo (`fresh_5m`, 26/07): **un esecutore
automatico che puo' rompersi senza dirlo e' peggio dell'esecuzione manuale.** Misurato invece il
costo di NON automatizzare: carico operativo **15 settimane/anno con ≥1 ordine** (29% dei
controlli, 1.4 ordini per volta); costo del ritardo su 10 anni **1g 0.02 (peggiora in 6/11 anni
= moneta), 3g 0.13, 10g 0.27**. ⚠️ Sulla finestra UCITS di 3.2 anni la curva NON e' monotona
(5g 0.26, 10g 0.13) → il campione corto non risolve differenze di questa taglia, si legge la
finestra lunga. **Il costo non e' il ritardo tipico ma la CODA: il rischio e' la dimenticanza, e
si copre con un ALLARME non con una API** (`gtaa_rebalance_plan` esiste gia' in produzione, nato
per un esecutore; l'allerta Telegram c'e' gia' sul book live). ⚠️ Lato opposto, vero: il resto del
book e' automatico, una gamba manuale aggiunge un modo di fallire che oggi non c'e' — argomento
reale a favore di IB, che pero' richiede un secondo venue e quindi cade sotto la decisione venue
($20k). **REGOLA: una capacita' mancante si valuta sul costo di non averla, non sulla sua
assenza.**
- ⚠️ **IL FEED EQUITY NON AVEVA UN CROSS-CHECK — buco trovato e chiuso (2026-07-26).** - ⚠️ **IL FEED EQUITY NON AVEVA UN CROSS-CHECK — buco trovato e chiuso (2026-07-26).**
`src/data/eq_crosscheck.py`. Nel crypto la certificazione incrocia sempre piu' venue `src/data/eq_crosscheck.py`. Nel crypto la certificazione incrocia sempre piu' venue
(`certify_feed.py` vs Coinbase USD); il feed equity aveva **solo controlli locali** (integrita', (`certify_feed.py` vs Coinbase USD); il feed equity aveva **solo controlli locali** (integrita',
+64
View File
@@ -394,3 +394,67 @@ guardando i due conti** — non sono cose che posso misurare da questo lato.
Ieri ho consigliato IB in parte perché "il conto esiste già": era un'assunzione, e per la seconda Ieri ho consigliato IB in parte perché "il conto esiste già": era un'assunzione, e per la seconda
volta in due giorni un'assunzione sul conto reale ha cambiato la conclusione. La prima volta era la volta in due giorni un'assunzione sul conto reale ha cambiato la conclusione. La prima volta era la
negoziabilità (PRIIPs), questa volta quale conto è davvero operativo. negoziabilità (PRIIPs), questa volta quale conto è davvero operativo.
---
# Addendum 2026-07-27 (2) — "degiro ha api?"
**Fatto:** DEGIRO **non** espone una API di trading ufficiale per il retail. Revolut nemmeno (la sua
API è per pagamenti, non per il portafoglio titoli). IB sì, documentata e supportata — è quella che
il progetto già usa per i dati.
Esistono wrapper **non ufficiali** degli endpoint interni del web trader DEGIRO. Girano su
credenziali + seed 2FA depositati sulla macchina, sono fuori dai termini di servizio, e si rompono
**in silenzio** a ogni cambio di front-end. Questo progetto ha già pagato una volta il prezzo di un
guasto silenzioso (`fresh_5m`, 26/07: fallimento muto → latenza d'uscita di SKH01 da ~1h a ~1 giorno
senza che nulla lo segnalasse). **Un esecutore automatico che può rompersi senza dirlo è peggio
dell'esecuzione manuale.**
Quindi la domanda utile non è "si può automatizzare" ma **"quanto costa non farlo"**.
## Carico operativo (banda 25%, controllo settimanale, $10.000)
| | |
|---|---|
| controlli/anno | 50 |
| **settimane con ≥1 ordine** | **15** (29% dei controlli) |
| ordini per settimana attiva | 1.4 (max 5) |
Nel 71% dei controlli non c'è nulla da fare.
## Costo del ritardo di esecuzione
Veicoli USA, 10 anni. ⚠️ Sulla finestra UCITS di 3.2 anni la curva **non risulta monotona** (5
giorni 0.26, 10 giorni 0.13): il campione corto non risolve differenze di questa taglia, quindi
il numero si legge sulla finestra lunga.
| ritardo | Sharpe | ΔSharpe | stabilità |
|---|---|---|---|
| 0 giorni | 0.90 | — | — |
| **1 giorno** | 0.89 | **0.02** | peggiora in 6/11 anni = **moneta** |
| 2 giorni | 0.83 | 0.07 | 7/11 |
| 3 giorni | 0.78 | 0.13 | 7/11 |
| 5 giorni | 0.73 | 0.18 | 7/11 |
| **10 giorni** | 0.63 | **0.27** | 6/11 |
**Il costo non è il ritardo tipico, è la coda.** Eseguire il giorno stesso o il giorno dopo costa
nulla; dieci giorni valgono quasi un terzo dello sleeve.
## Conseguenza
Il rischio dell'operatività manuale non è la lentezza, è la **dimenticanza** — e quella si compra
con un **allarme**, non con una API. `gtaa_rebalance_plan(held, capital)` esiste già in produzione
ed è nato esattamente per un esecutore; il progetto ha già l'allerta Telegram sul book live. Un cron
settimanale che calcola il piano e notifica quando c'è da agire copre il caso 15 volte l'anno.
⚠️ **L'altro lato, che resta vero:** il resto del book è automatico (TP01 e SKH01 mandano ordini
veri su cron). Aggiungere una gamba manuale introduce un modo di fallire che il sistema oggi non ha.
È un argomento reale a favore di IB — che l'API ce l'ha — ma richiede finanziare un secondo venue, e
la decisione venue del 26/07 tiene tutto su Deribit fino a $20k. **La scelta è quindi rimandata al
punto in cui la si riaprirebbe comunque.**
## Lezione
**Una capacità mancante si valuta sul costo di non averla, non sulla sua assenza.** Qui l'assenza di
API sembra squalificante e vale 0.02 di Sharpe se si esegue entro un giorno; ciò che vale davvero
(0.27) è un rischio operativo che si copre con una notifica.
+55
View File
@@ -174,6 +174,61 @@ def main() -> None:
print(" controllo (2) su 10 anni e veicoli diversi, ma GTAA01 non e' deployabile prima dei") 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.") 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 ---------- # ---------- (5) cosa cercare sul proprio conto ----------
print("\n" + "=" * 100) print("\n" + "=" * 100)
print(" (5) COSA CERCARE SUL PROPRIO BROKER — per ISIN, non per ticker") print(" (5) COSA CERCARE SUL PROPRIO BROKER — per ISIN, non per ticker")