Timestamp dei market data: SIP o orologi degli exchange?
I market data usano quattro orologi: scopri come cambiano il tape ordinando gli stessi trade e quale timestamp scegliere per analisi, audit e trading.
I timestamp dei market data sono gli orari associati a una singola operazione eseguita, mentre viaggia dal matching engine che l’ha eseguita allo schermo che la visualizza. Nel record pubblico, un’operazione su azioni statunitensi ne riporta tre, e ciascuno risponde a una domanda diversa. Ordinando i print della stessa giornata prima secondo un orologio e poi secondo un altro, si ottengono due tape realmente diversi.
I quattro orologi attraversati da un singolo print
Un print riceve più timestamp durante il percorso fino a te. In ordine:
- Orario del matching engine. L’istante in cui il matching engine di una venue abbina due ordini. Nessuno al di fuori della venue legge direttamente questo valore. È il riferimento reale per stabilire quando è avvenuta l’operazione, e ogni orologio successivo ne è un’approssimazione.
- Orario del participant, detto anche orario della venue o dell’exchange. Il timestamp che la venue scrive quando pubblica il print sul proprio feed, riportato nel campo
participant_timestamp. Tra tutti i valori effettivamente leggibili, è quello più vicino al matching engine. - Orario SIP. Il timestamp che il securities information processor scrive quando il print raggiunge il consolidated tape, il feed ufficiale unico che aggrega tutte le venue azionarie statunitensi. È il campo
sip_timestamp, e la sequenza del tape ufficiale segue questo timestamp. La differenza tra questo feed e quello proprietario di una venue è illustrata in SIP e feed diretti degli exchange. - Orario di acquisizione. Il timestamp scritto dalla scheda di rete del tuo sistema quando arriva il pacchetto. Non compare nei record di un vendor, perché descrive il tuo percorso e non il mercato. Le attività di acquisizione e replay dei pacchetti usano esclusivamente questo orologio.
I print eseguiti fuori exchange riportano un quinto timestamp, trf_timestamp, che indica quando una trade reporting facility ha ricevuto la segnalazione.
Perché i timestamp dei market data non coincidono tra le venue
La differenza tra il timestamp della venue e quello consolidato è il tempo trascorso dal print durante il transito e nella coda del processor. Non è un valore unico. Ogni venue si trova a una distanza diversa dal processor, usa hardware differente e si trova dietro una coda diversa. Il pannello seguente misura questa differenza per ogni venue che ha registrato print su AAPL durante una mezz’ora fissa il 10 giugno 2026.
L'esatto SQL dietro ogni numero
WITH venues AS
(
SELECT
toUInt32(id) AS exchange_id,
any(coalesce(nullIf(acronym, ''), name)) AS venue_name
FROM global_markets.stocks_exchanges
WHERE asset_class = 'stocks'
GROUP BY exchange_id
)
SELECT
if(v.venue_name = '', concat('Venue ', toString(t.exchange)), v.venue_name) AS venue,
count() AS print_count,
round(quantileDeterministic(0.5)(
toFloat64(toUnixTimestamp64Nano(t.sip_timestamp)
- toUnixTimestamp64Nano(t.participant_timestamp)) / 1000,
toUInt64(t.sequence_number)), 1) AS median_lag_us,
round(quantileDeterministic(0.99)(
toFloat64(toUnixTimestamp64Nano(t.sip_timestamp)
- toUnixTimestamp64Nano(t.participant_timestamp)) / 1000,
toUInt64(t.sequence_number)), 1) AS p99_lag_us
FROM global_markets.stocks_trades AS t
LEFT JOIN venues AS v ON v.exchange_id = toUInt32(t.exchange)
WHERE t.ticker = 'AAPL'
AND t.sip_timestamp >= '2026-06-10 14:30:00'
AND t.sip_timestamp < '2026-06-10 15:00:00'
AND ifNull(toUnixTimestamp64Nano(t.trf_timestamp), 0) = 0
GROUP BY venue
HAVING count() >= 200
ORDER BY median_lag_us DESC
LIMIT 15Tra quelle venue, la differenza mediana più ampia tra il timestamp della venue e quello consolidato è stata di 346.2 microsecondi, presso NYSE Arca, Inc.. Nella stessa finestra, la venue più rapida ha registrato 13.7 microsecondi. La colonna p99 è quella da osservare con maggiore attenzione: per la venue più lenta ha raggiunto 420.8 microsecondi, mostrando la coda che la mediana nasconde.
Quale timestamp usare
Quattro regole coprono quasi tutti i casi.
- Orario del participant per gli studi di microstruttura e gli event study. Tutto ciò che misura cosa è successo su una venue e in quale ordine deve usare l’orologio della venue. La ricostruzione del book, trattata in dati del book MBO e MBP, è inutilizzabile con qualsiasi altro orologio.
- Orario SIP per tutto ciò che deve riconciliarsi con il tape ufficiale. Reporting regolamentare, verifiche di best execution, apertura e chiusura ufficiali e qualsiasi dato che una controparte confronterà con il record consolidato.
- Orario di acquisizione solo per misurare il tuo percorso. Indica quanto tempo hanno impiegato i dati per raggiungere la tua macchina. Non indica quando è avvenuta l’operazione, e due macchine non produrranno mai lo stesso valore.
- Non mescolare mai gli orologi nello stesso dataset. Un join che abbina quote su un orologio e trade su un altro restituisce numeri plausibili, ma fallisce proprio nei momenti più importanti.
Gli stessi print, ordinati in due modi
È nell’ordinamento che l’astrazione si rompe. Il pannello seguente prende i dieci millisecondi più intensi di quella mezz’ora, mantiene i primi dodici print di exchange nell’ordine della venue e poi classifica gli stessi dodici secondo l’ordine del consolidated tape. La tabella è ordinata in base a quanto ogni print è cambiato tra le due classifiche.
L'esatto SQL dietro ogni numero
WITH
burst AS
(
SELECT intDiv(toUnixTimestamp64Nano(participant_timestamp), 10000000) AS slice_10ms
FROM global_markets.stocks_trades
WHERE ticker = 'AAPL'
AND sip_timestamp >= '2026-06-10 14:30:00'
AND sip_timestamp < '2026-06-10 15:00:00'
AND ifNull(toUnixTimestamp64Nano(trf_timestamp), 0) = 0
GROUP BY slice_10ms
ORDER BY count() DESC, slice_10ms ASC
LIMIT 1
),
sample AS
(
SELECT
participant_timestamp,
sip_timestamp,
toUInt64(sequence_number) AS seq,
toUnixTimestamp64Nano(sip_timestamp)
- toUnixTimestamp64Nano(participant_timestamp) AS lag_ns
FROM global_markets.stocks_trades
WHERE ticker = 'AAPL'
AND sip_timestamp >= '2026-06-10 14:30:00'
AND sip_timestamp < '2026-06-10 15:00:00'
AND ifNull(toUnixTimestamp64Nano(trf_timestamp), 0) = 0
AND intDiv(toUnixTimestamp64Nano(participant_timestamp), 10000000)
IN (SELECT slice_10ms FROM burst)
ORDER BY participant_timestamp ASC, seq ASC
LIMIT 12
),
ranked AS
(
SELECT
participant_timestamp,
sip_timestamp,
lag_ns,
row_number() OVER (ORDER BY participant_timestamp ASC, seq ASC) AS participant_rank,
row_number() OVER (ORDER BY sip_timestamp ASC, seq ASC) AS sip_rank
FROM sample
)
SELECT
concat('P', leftPad(toString(participant_rank), 2, '0')) AS print_label,
concat(formatDateTime(toTimeZone(participant_timestamp, 'America/New_York'), '%H:%i:%S'), '.',
leftPad(toString(intDiv(toUnixTimestamp64Nano(participant_timestamp) % 1000000000, 1000)), 6, '0')) AS venue_clock_et,
concat(formatDateTime(toTimeZone(sip_timestamp, 'America/New_York'), '%H:%i:%S'), '.',
leftPad(toString(intDiv(toUnixTimestamp64Nano(sip_timestamp) % 1000000000, 1000)), 6, '0')) AS tape_clock_et,
participant_rank,
sip_rank,
abs(toInt32(sip_rank) - toInt32(participant_rank)) AS places_moved,
round(lag_ns / 1000, 1) AS sip_lag_delta_us
FROM ranked
ORDER BY places_moved DESC, participant_rank ASCLa differenza più ampia tra le due posizioni di un print è 6. Quel print ha lasciato la venue alle 10:44:17.160712 e ha raggiunto il tape 305.7 microsecondi dopo, alle 10:44:17.161018, passando dalla posizione 6 secondo l’orologio della venue alla posizione 12 secondo il tape. Nessuno dei due ordinamenti è sbagliato. Rispondono a domande diverse. Uno studio sulla sequenza delle operazioni eseguito con l’orologio del tape legge questo flusso in un ordine che nessuna venue ha mai prodotto, mentre una verifica di best execution eseguita con l’orologio della venue non coincide con il record ufficiale.
I print fuori exchange arrivano molto dopo l’evento
Un’operazione eseguita al di fuori di un exchange, presso un wholesaler o in un dark pool, viene segnalata a una trade reporting facility invece di essere abbinata su un book pubblico. La segnalazione contiene l’orario di esecuzione e arriva successivamente al tape. Questo intervallo è un ritardo di reporting, non un tempo di transito, ed è di ordini di grandezza superiore.
L'esatto SQL dietro ogni numero
WITH off_exchange AS
(
SELECT
(toUnixTimestamp64Nano(sip_timestamp)
- toUnixTimestamp64Nano(participant_timestamp)) / 1000000.0 AS delay_ms
FROM global_markets.stocks_trades
WHERE ticker = 'AAPL'
AND sip_timestamp >= '2026-06-10 14:30:00'
AND sip_timestamp < '2026-06-10 15:00:00'
AND ifNull(toUnixTimestamp64Nano(trf_timestamp), 0) > 0
)
SELECT
multiIf(delay_ms < 1, 'under 1 ms',
delay_ms < 10, '1 to 10 ms',
delay_ms < 100, '10 to 100 ms',
delay_ms < 1000, '100 ms to 1 s',
delay_ms < 10000, '1 s to 10 s',
'over 10 s') AS reporting_delay,
count() AS print_count,
round(100 * count() / (SELECT count() FROM off_exchange), 2) AS share_pct
FROM off_exchange
GROUP BY reporting_delay
ORDER BY min(delay_ms) ASCTra i print AAPL fuori exchange in quella finestra, 24.8% rientrano nel bucket under 1 ms. La coda arriva fino al bucket 1 s to 10 s, che contiene 74 print. Un print che arriva con dieci secondi di ritardo conserva l’orario della venue in cui è stato effettivamente eseguito, ma si trova dieci secondi più avanti nel flusso del tape. Se si ordina per orario del tape, appare nel minuto sbagliato. I print segnalati fuori dalla sequenza normale riportano sale condition code che lo indicano; è uno degli aspetti che i codici delle condizioni di negoziazione servono a segnalare.
Perché due persone costruiscono barre diverse dagli stessi trade
Quasi ogni ticket che segnala che «i dati sono sbagliati» nasce da questo problema. Una barra è un bucket di print, e il bucket in cui finisce un print dipende dal timestamp usato per assegnarlo. Il pannello seguente conta i print che cambiano bucket passando dall’orologio della venue a quello del tape, su quattro durate comuni delle barre.
L'esatto SQL dietro ogni numero
WITH
prints AS
(
SELECT
toUnixTimestamp64Nano(participant_timestamp) AS venue_ns,
toUnixTimestamp64Nano(sip_timestamp) AS tape_ns
FROM global_markets.stocks_trades
WHERE ticker = 'AAPL'
AND sip_timestamp >= '2026-06-10 14:30:00'
AND sip_timestamp < '2026-06-10 15:00:00'
),
grids AS
(
SELECT arrayJoin([1, 10, 60, 300]) AS bar_seconds
)
SELECT
multiIf(bar_seconds = 1, '1 second',
bar_seconds = 10, '10 seconds',
bar_seconds = 60, '1 minute',
'5 minutes') AS bar_length,
countIf(intDiv(venue_ns, toInt64(bar_seconds) * 1000000000)
!= intDiv(tape_ns, toInt64(bar_seconds) * 1000000000)) AS moved_print_count,
round(100 * countIf(intDiv(venue_ns, toInt64(bar_seconds) * 1000000000)
!= intDiv(tape_ns, toInt64(bar_seconds) * 1000000000)) / count(), 3) AS moved_pct
FROM prints
CROSS JOIN grids
GROUP BY bar_seconds
ORDER BY bar_seconds ASCSu una griglia di 1 second, 8.966% dei print di quella finestra finiscono in una barra diversa con i due orologi, per un totale di 8944 print. Estendendo la barra a 5 minutes, il dato scende a 0.024%. Il meccanismo è automatico: un print cambia bucket ogni volta che la differenza tra i due orologi attraversa un confine, e le barre più brevi contengono più confini. Due vendor possono quindi essere entrambi corretti e pubblicare comunque volumi diversi per lo stesso minuto. La costruzione è illustrata in come vengono costruite le barre OHLCV.
Un campo in nanosecondi non implica una precisione al nanosecondo
Entrambi i timestamp arrivano come numeri interi con risoluzione al nanosecondo. La risoluzione indica ciò che un campo è in grado di esprimere. La precisione indica quanto il valore sia vicino all’orario reale. Le due caratteristiche dipendono da fattori completamente diversi.
La sincronizzazione degli orologi nel settore è regolata da una tolleranza normativa, non dalla fisica. La regola di FINRA sulla sincronizzazione impone agli intermediari di mantenere gli orologi aziendali entro 50 millisecondi dal riferimento NIST. Exchange e processor operano con tolleranze molto più strette, usando il Precision Time Protocol (PTP, standardizzato come IEEE 1588), che distribuisce un orologio di riferimento sulla stessa rete che trasporta i dati e mantiene le macchine sincronizzate a meno di un microsecondo.
Ne derivano due conclusioni. All’interno dei timestamp di una stessa organizzazione, l’ordinamento alla risoluzione del microsecondo è significativo. Tra organizzazioni diverse, una differenza di alcune centinaia di nanosecondi tra due timestamp rientra nel margine di errore. Trattarla come un ordine reale significa interpretare il rumore come informazione.
FAQ
Qual è la differenza tra il timestamp SIP e il timestamp del participant?
Il timestamp del participant viene scritto dalla venue quando pubblica un trade sul proprio feed. Il timestamp SIP viene scritto dal processor del consolidated tape quando il trade raggiunge il feed ufficiale aggregato. La differenza tra i due è il tempo di transito e di attesa nella coda: si misura in microsecondi per i print di exchange e spesso in millisecondi o più per i print segnalati tramite una trade reporting facility.
Quale timestamp dei market data devo usare per il backtesting?
Usa il timestamp del participant per tutto ciò che modella cosa un partecipante avrebbe potuto vedere o fare su una venue, e il timestamp SIP per tutto ciò che deve riconciliarsi con il record consolidato ufficiale. Qualunque sia la scelta, applicala a tutte le tabelle dello studio, incluse le quote.
Perché le mie barre a un minuto non coincidono con quelle del mio data provider?
Di solito la causa è una differenza tra gli orologi. Un print il cui timestamp della venue cade appena prima del confine di un minuto può avere un timestamp del tape appena successivo, collocando lo stesso trade in barre diverse secondo le due convenzioni. I print fuori exchange segnalati in ritardo amplificano l’effetto.
I timestamp al nanosecondo sono precisi al nanosecondo?
No. Il campo ha una risoluzione al nanosecondo, ma la precisione dipende da quanto è sincronizzato l’orologio della macchina che lo scrive. I sistemi degli exchange e dei processor che usano PTP mantengono una sincronizzazione inferiore al microsecondo, mentre gli orologi aziendali dei broker sono soggetti a una tolleranza regolamentare di 50 millisecondi. I confronti più fini della tolleranza dell’orologio meno preciso non sono significativi.
Ogni pannello precedente viene fornito con il codice SQL che lo ha prodotto, così puoi verificare esattamente da quale orologio proviene ciascun dato. Per riordinare la tua finestra di print secondo un altro orologio e osservare come cambia il tape, formula la richiesta in linguaggio naturale sul terminale Strasmore.