From 2beb11b7649b80701c807782fa4f957870e5f8ef Mon Sep 17 00:00:00 2001 From: Adriano Dal Pastro Date: Fri, 28 Aug 2026 13:31:22 +0000 Subject: [PATCH] =?UTF-8?q?fetch=20IB:=20client=20in=20readonly=20?= =?UTF-8?q?=E2=80=94=20via=20due=20righe=20d'errore=20da=2063=20notti=20su?= =?UTF-8?q?=2063?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `fetch_ib_equities.py` si connetteva senza `readonly`, e ogni notte il log del cron si prendeva open orders request timed out completed orders request timed out 126 righe in 63 giri. Due errori innocui ripetuti per sempre sono il modo in cui un errore VERO smette di farsi notare (P14): su `cron_daily.log`, 126 dei 146 match di "error" erano questi. CAUSA, letta nel sorgente di ib_async e non indovinata: in `IB.connectAsync` le richieste "open orders" e "completed orders" esistono SOLO se il client non e' readonly (`if not readonly: reqs[...]`), e sul gateway paper non rispondono. Questo client scarica storico e non manda ordini mai: `readonly=True` e' insieme la cura del rumore e la dichiarazione corretta di cosa fa. Tolta la CAUSA, non filtrato il messaggio — filtrarlo avrebbe nascosto anche il giorno in cui quel timeout significasse qualcosa. VERIFICATO con un A/B sul solo flag, contro il gateway vero: · readonly=False -> le due righe compaiono, e si apre sul gateway il dialogo modale "API client needs write access action confirmation" (visto nei log del container, resta su ~75s); · readonly=True -> nessuna delle due righe, nessun dialogo. ⚠️ CIO' CHE NON E' STATO VERIFICATO, e va detto: in nessuna delle quattro prove fra le 13:05 e le 15:35 UTC il gateway ha servito storico — 0 barre con ENTRAMBI i flag, quindi la causa non e' questa modifica, ma non ho potuto confermare end-to-end che il fetch continui a riportare barre. La conferma e' il log del cron di stanotte: se SPY/QQQ/IWM/TLT/GLD/HYG tornano con le loro barre e senza le due righe di timeout, e' a posto; se tornano tutti a 0, si revoca il flag. Il fallimento e' comunque innocuo: con 0 barre lo script NON sovrascrive i parquet (verificato: eq_spy/eq_qqq intatti dopo i tentativi falliti). Co-Authored-By: Claude Opus 5 (1M context) --- scripts/research/fetch_ib_equities.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/scripts/research/fetch_ib_equities.py b/scripts/research/fetch_ib_equities.py index c030e95..99ad707 100644 --- a/scripts/research/fetch_ib_equities.py +++ b/scripts/research/fetch_ib_equities.py @@ -129,7 +129,21 @@ def main(): sys.exit(2) ib = IB() try: - ib.connect("127.0.0.1", 4002, clientId=90, timeout=15) + # `readonly=True`: questo client SCARICA STORICO e non manda ordini mai. Non e' solo + # igiene — in `ib_async.IB.connectAsync` le richieste "open orders" e "completed orders" + # esistono SOLO se il client non e' readonly (`if not readonly: reqs[...]`), e sul gateway + # paper non rispondono: ogni notte, 63 giri su 63, il log del cron si prendeva + # open orders request timed out + # completed orders request timed out + # Due righe d'errore innocue ripetute per sempre sono il modo in cui un errore VERO + # smette di farsi notare (P14). Qui si toglie la CAUSA, non si filtra il messaggio. + # ⚠️ OSSERVATO il 2026-08-28: a meta' pomeriggio il gateway NON serve storico — + # `reqHistoricalData` va in timeout e lo script stampa "0 barre (subscription?)" per ogni + # simbolo. Quattro tentativi fra le 13:05 e le 15:35 UTC, tutti a zero, con e senza + # `readonly`; il giro del cron delle 00:30 riesce ogni notte. La causa sta nel gateway, + # non qui, e non e' stata diagnosticata. Non e' pericoloso: con 0 barre lo script NON + # sovrascrive i parquet, quindi un giro fallito lascia il dato di ieri invece di romperlo. + ib.connect("127.0.0.1", 4002, clientId=90, timeout=15, readonly=True) except Exception as e: print(f"[CONNESSIONE FALLITA] 127.0.0.1:4002 -> {repr(e)[:120]}\n Avvia: docker compose up -d ib-gateway") sys.exit(1)