SSD Nodes Learn Hosting plans →
Guide Matt ConnorDi Matt Connor

VPS per trading bot: cosa conta davvero

Scopri cosa serve davvero a un trading bot: riavvio con systemd, orologio sincronizzato, chiavi API protette, heartbeat e limiti reali della latenza.

Cosa serve a un trading bot da un VPS

Un VPS per trading bot si valuta in base a quattro aspetti: il processo riparte dopo un arresto anomalo, l’orologio è sincronizzato, le chiavi API (application programming interface) sono protette dai furti e ricevi una notifica quando il bot si arresta. Per un bot retail, la velocità pura è molto meno importante. La parte più lenta del percorso dell’ordine dipende dal broker e dalla distanza da esso, non dall’host che esegue il tuo codice Python.

Questa è una guida tecnica. Il contenuto non costituisce consulenza finanziaria e non tratta alcuna strategia.

L’uptime dipende dalla disciplina dei riavvii, non da un numero in una pagina commerciale

Gli impegni di uptime dichiarati differiscono tra i fornitori. AWS specifica almeno il 99.5 percento per una singola istanza EC2 e il 99.99 percento per le distribuzioni idonee su più zone di disponibilità. Questi impegni riguardano la disponibilità dell’infrastruttura, non lo stato di salute del bot. Un bot può terminare a causa di un’eccezione non gestita, di un websocket che non riesce più a riconnettersi o dell’OOM (out of memory) killer, mentre il server resta operativo per tutto il tempo. La domanda utile è quindi che cosa accade nei dieci secondi successivi alla terminazione del processo.

Esegui il bot come servizio systemd e lascia che sia il sistema init a gestirne il riavvio. Un file unit svolge questo compito.

[Unit]
Description=Trading bot
After=network-online.target
Wants=network-online.target
StartLimitIntervalSec=0

[Service]
Type=simple
User=bot
WorkingDirectory=/opt/tradingbot
EnvironmentFile=/etc/tradingbot/api.env
ExecStart=/opt/tradingbot/venv/bin/python -m tradingbot
Restart=always
RestartSec=10
NoNewPrivileges=true
ProtectSystem=strict
ProtectHome=true
PrivateTmp=true
ReadWritePaths=/var/lib/tradingbot

[Install]
WantedBy=multi-user.target

StartLimitIntervalSec=0 è la direttiva che spesso viene trascurata. Le impostazioni predefinite di systemd consentono 5 avvii in 10 secondi, includendo l’avvio iniziale e gli avvii manuali; la configurazione del manager può sovrascrivere questi valori predefiniti. Quando viene raggiunto il limite, i tentativi di riavvio automatico vengono interrotti, ma l’unit può essere avviata manualmente oppure da un timer o un socket dopo la scadenza dell’intervallo. Impostando il valore su 0 si disabilita il limite di frequenza, quindi un bot che entra in un ciclo di crash continua a essere riavviato invece di restare inattivo. RestartSec=10 interrompe il ciclo prima che martelli l’exchange con tentativi di riconnessione.

Controlla il file prima di considerarlo affidabile, quindi avvia il servizio:

sudo systemd-analyze verify /etc/systemd/system/tradingbot.service
sudo systemctl daemon-reload
sudo systemctl enable --now tradingbot
systemctl status tradingbot

enable è la parte che consente al servizio di sopravvivere a un riavvio, e gli aggiornamenti del kernel richiedono riavvii. Per verificare se il bot termina senza produrre segnali evidenti, chiedi a systemd il contatore dei riavvii:

systemctl show tradingbot -p NRestarts
journalctl -u tradingbot --since "24 hours ago" | tail -50

NRestarts=0 conta i job di riavvio automatico dall’ultimo azzeramento del contatore; non dimostra che il bot sia stato operativo o privo di crash per una settimana. I riavvii manuali e systemctl reset-failed azzerano il contatore, mentre un bot bloccato può continuare a mostrare zero. NRestarts=812 conta 812 job di riavvio, non le riconnessioni riuscite all’exchange né le operazioni eseguite, e non indica quando si sono verificati. Controlla il journal per determinare tempi e cause, inclusi i problemi verificatisi prima della connessione del bot. L’anatomia completa del file unit, inclusi i timer per i job pianificati come un report giornaliero, è descritta in eseguire un programma come servizio systemd.

Imposta l’orologio su UTC e verifica che sia sincronizzato

Le API scambiano timestamp per convalidare le richieste firmate; Binance Spot usa per impostazione predefinita una finestra di ricezione di 5 secondi e rifiuta i timestamp avanti di almeno 1 secondo rispetto all’ora del server. Un orologio non sincronizzato produce errori che sembrano problemi di autenticazione, quindi gli amministratori possono ruotare le chiavi per ore prima di controllare l’ora. Nelle API in stile Binance il messaggio è letterale: Timestamp for this request was 1000ms ahead of the server's time.

Imposta il server su UTC. I fusi orari locali introducono cambi dell’ora legale negli orari visualizzati; i timestamp Unix usati dalle API non cambiano quando cambia il fuso orario di visualizzazione.

sudo timedatectl set-timezone UTC
timedatectl

Ubuntu usa chrony per impostazione predefinita a partire dalla versione 25.10; nelle installazioni precedenti è possibile usare systemd-timesyncd, un client SNTP (simple network time protocol). systemd-timesyncd regola l’orologio, ma non può interrogare più server contemporaneamente per rilevare una sorgente oraria errata. Usa invece chrony:

sudo apt update && sudo apt install -y chrony
sudo systemctl enable --now chrony
chronyc tracking
chronyc sources -v

La riga da leggere da chronyc tracking è System time, ad esempio System time : 0.000031415 seconds fast of NTP time. Un valore basso indica una piccola correzione ancora da applicare all’orologio NTP di chrony; prima di valutare la precisione, controlla anche la sincronizzazione, Root delay e Root dispersion. Se restituisce Leap status : Not synchronised, chrony non è sincronizzato, anche se i server hanno risposto; le misurazioni possono essere rifiutate perché troppo imprecise. Attendi un minuto, quindi esegui di nuovo il controllo prima di modificare le regole del firewall.

Mantieni le chiavi API fuori dalle directory che copi

Una chiave dell'exchange divulgata è più rischiosa di una chiave SSH divulgata, perché il permesso di effettuare prelievi consente di convertire immediatamente l'accesso in denaro. Due pratiche coprono gran parte del rischio.

Per prima cosa, non concedere mai il permesso di effettuare prelievi alla chiave di un bot e, se l'exchange lo supporta, vincola la chiave all'indirizzo IP del server. Questo è il singolo controllo che rende quasi inutilizzabile una chiave rubata.

In secondo luogo, mantieni il secret fuori dalla directory del codice. Qualsiasi elemento contenuto in /opt/tradingbot finisce prima o poi in un repository git o in un archivio di backup. Inseriscilo in un file di proprietà di root che systemd possa leggere:

sudo install -d -m 750 -o root -g bot /etc/tradingbot
sudo install -m 640 -o root -g bot /dev/null /etc/tradingbot/api.env
sudo nano /etc/tradingbot/api.env

Il file contiene righe KEY=value semplici, senza virgolette e senza export. La modalità 640 concede al proprietario root l'accesso in lettura e scrittura e ai membri del gruppo bot l'accesso in lettura, senza permessi per gli altri utenti. Verifica con sudo -u bot cat /etc/tradingbot/api.env e poi con un utente non privilegiato che non appartenga al gruppo bot: l'accesso deve fallire con Permission denied.

Il bot non deve essere eseguito come root né come utente con cui effettui il login. Crea un account di sistema con shell nologin e /var/lib/tradingbot come directory home prima di avviare il servizio o creare file appartenenti al gruppo bot:

sudo useradd --system --shell /usr/sbin/nologin --home-dir /var/lib/tradingbot --create-home bot

La spiegazione di ciascuno di questi flag e dei limiti effettivi di ProtectSystem=strict è disponibile in esecuzione dei servizi come utente non privilegiato. Il resto della configurazione di base del server, ovvero chiavi SSH e firewall, è illustrato in i primi dieci minuti su un nuovo VPS.

Scopri il problema prima che lo faccia il tuo broker

systemctl status indica che il processo è in esecuzione. Non indica che il bot stia eseguendo attività. Un processo bloccato in un ciclo di tentativi contro un websocket non raggiungibile supera i controlli sul processo descritti nell’unità precedente.

Usa invece un heartbeat. Uptime Kuma supporta i monitor push: si aspetta che il bot chiami un URL a intervalli regolari e invia un avviso quando le chiamate smettono di arrivare. Inserisci la chiamata alla fine del ciclo principale, dopo la parte che dimostra che il bot è attivo, ad esempio dopo una lettura riuscita dei dati di mercato.

curl -fsS "http://monitor.example.com:3001/api/push/YOUR_TOKEN?status=up&msg=loop_ok"

Imposta l’intervallo del monitor a circa il doppio della durata del ciclo, in modo che le normali variazioni dei tempi non generino avvisi. Esegui il monitor su un server diverso da quello del bot, perché un monitor che si arresta insieme al servizio controllato non può segnalare nulla. La configurazione è descritta in monitoraggio dello stato self-hosted con Uptime Kuma.

Aggiungi anche un avviso per lo spazio su disco. Un bot che scrive log dettagliati può riempire il filesystem root in poche settimane. Quando il disco è pieno, la scrittura nel database si interrompe, mentre le chiamate di rete possono continuare; per questo i sintomi possono essere insoliti. journalctl --vacuum-time=14d e una direttiva SystemMaxUse= in /etc/systemd/journald.conf mantengono il journal entro limiti definiti.

La parte onesta: la latenza dipende soprattutto da fattori esterni al tuo host

È qui che il mercato dei prodotti VPS per il trading smette di essere tecnico. Le pagine di marketing dichiarano valori inferiori al millisecondo e lasciano intendere che l'host sia ciò che separa il bot dall'esecuzione dell'ordine. Per quasi tutti i bot retail, non è così.

L'ordine viaggia dal bot all'endpoint dell'exchange o del broker tramite Internet pubblico. Questo percorso dipende soprattutto dalla distanza fisica e dal peering tra il tuo provider e quello dell'exchange o del broker. Inoltre, i sistemi del broker aggiungono le proprie code, i controlli di rischio e i limiti di frequenza.

Misura invece di fare supposizioni. curl riporta i tempi di connessione e di ricezione del primo byte per un endpoint reale:

curl -s -o /dev/null -w 'dns=%{time_namelookup}s connect=%{time_connect}s ttfb=%{time_starttransfer}s\n' \
  https://api.kraken.com/0/public/Time
mtr -rwzc 100 api.kraken.com

Esegui il comando da un server candidato prima di procedere. Se connect è pari a 0.180 secondi, il valore include la risoluzione DNS e la connessione TCP; non stabilisce in quale continente si trovi il server. Se connect è pari a 0.004 secondi e ttfb è pari a 0.140 secondi, la differenza comprende la configurazione TLS, la trasmissione della richiesta, i ritardi di rete e l'elaborazione sul server. Cambiare host può influire su alcuni di questi componenti, quindi confronta le misurazioni eseguite da più posizioni candidate.

Quando conta quindi l'host? Quando il server è colocato o connesso direttamente alla sede del mercato e la competizione riguarda la posizione nella coda. È un'attività diversa, con un budget diverso. L'host conta anche quando il collo di bottiglia è il tuo codice: un bot che ricalcola gli indicatori sull'intera cronologia a ogni tick può consumare 200 millisecondi di CPU per ciclo. Questa è latenza reale che puoi ridurre gratuitamente. Esegui il profiling del ciclo prima di cercare un server più veloce.

Nell'host scelto contano invece la posizione geografica, una rete stabile e una quantità di memoria sufficiente a impedire all'OOM killer di intervenire. Aggiungi memoria se conservi la cronologia dei tick in un database locale.

Una breve checklist prima della messa in produzione

  1. systemctl is-enabled tradingbot restituisce enabled e il servizio rimane attivo dopo sudo reboot.
  2. chronyc tracking segnala la sincronizzazione, uno scostamento dell'ora di sistema inferiore a pochi millisecondi e valori di ritardo e dispersione di root entro il margine previsto per la sincronizzazione.
  3. La chiave API dispone dell'autorizzazione al trading, non dispone dell'autorizzazione ai prelievi e usa una lista di indirizzi IP consentiti, se l'exchange la offre.
  4. Terminando il processo con sudo systemctl kill -s SIGKILL tradingbot, il servizio torna attivo dopo il ritardo RestartSec e il tempo di avvio.
  5. Il monitor dell'heartbeat invia una notifica dopo l'intervallo configurato ed esegue nuovi tentativi quando arresti deliberatamente il bot.
  6. I log hanno dimensioni limitate e il filesystem root dispone di spazio libero sufficiente in df -h.

Esegui l'intera procedura nel sandbox dell'exchange o in modalità paper per una settimana prima di usare fondi reali. Durante quella settimana ogni punto precedente fallisce almeno una volta: è proprio questo lo scopo della settimana.

FAQ

Un bot di trading ha bisogno di un server a bassa latenza o di un server bare metal?

Solo se competi sulla velocità di esecuzione con altri partecipanti automatizzati sulla stessa sede di negoziazione. In genere questo richiede la colocation, non un VPS generico. Per un bot retail, il tempo di andata e ritorno dipende soprattutto dalla distanza geografica e dall'elaborazione del broker. Scegli quindi un server vicino all'endpoint API e misura con curl e mtr prima di pagare per prestazioni superiori.

Quanta RAM e CPU richiede un bot di trading?

La maggior parte dei bot con una singola strategia è vincolata alla rete e resta inattiva tra un evento e l'altro. La memoria diventa il fattore limitante quando mantieni in memoria la cronologia dei tick o esegui un database locale. Controlla quindi free -h e il journal per individuare messaggi di terminazione OOM, invece di procedere per supposizioni.

Perché la API dell'exchange rifiuta le richieste con un errore di timestamp?

Il timestamp della richiesta non rientra nella finestra accettata dall'exchange. Sia lo scostamento dell'orologio sia i ritardi delle richieste sono rilevanti. Installa chrony, verifica che chronyc tracking mostri un offset System time ridotto e uno stato dei leap sincronizzato. Controlla anche il ritardo del root e la dispersione. Impostare la macchina sul fuso UTC mantiene coerenti gli orari visualizzati, ma non corregge lo scostamento dell'orologio. La rotazione della API key non risolve un problema dell'orologio.

Come posso impedire che il bot si arresti durante la notte senza che me ne accorga?

Eseguilo tramite systemd con Restart=always e StartLimitIntervalSec=0, in modo che un ciclo di crash continui a ritentare invece di raggiungere il limite di frequenza degli avvii. Aggiungi quindi un heartbeat che il bot invia al termine di ogni ciclo completato correttamente. Il riavvio gestisce il processo. L'heartbeat rileva il caso in cui il processo è attivo, ma bloccato.

Posso eseguire il bot e il monitoraggio sullo stesso VPS?

Puoi farlo, ma il monitoraggio ti fornirà informazioni errate proprio nel giorno in cui sarà importante. Un'interruzione che arresta il bot arresta anche il monitoraggio. Mantieni gli alert su una macchina separata, idealmente presso un provider o in una regione diversa, e usa il server del bot soltanto per il bot e i relativi log.

Questo articolo ti è stato utile?