Dấu thời gian dữ liệu: SIP hay đồng hồ sàn?
Dữ liệu thị trường dùng bốn đồng hồ khác nhau. Xem cách mỗi cách sắp xếp cùng giao dịch làm thay đổi tape và nên dùng đồng hồ nào cho từng mục đích.
Dấu thời gian của dữ liệu thị trường là các mốc thời gian được gắn vào một giao dịch đơn lẻ khi giao dịch đó đi từ matching engine thực hiện lệnh đến màn hình hiển thị. Một giao dịch cổ phiếu Mỹ có ba mốc trong dữ liệu công khai, và mỗi mốc trả lời một câu hỏi khác nhau. Nếu sắp xếp các giao dịch trong cùng một ngày theo một đồng hồ rồi theo đồng hồ khác, bạn sẽ có hai tape thực sự khác nhau.
Bốn đồng hồ mà một giao dịch đơn lẻ trải qua
Một giao dịch được gắn dấu nhiều lần trên đường đến bạn. Theo thứ tự:
- Thời gian của matching engine. Đây là thời điểm matching engine của một venue khớp hai lệnh. Không ai bên ngoài venue có thể đọc trực tiếp giá trị này. Đây là mốc xác thực cho thời điểm giao dịch xảy ra, còn mọi đồng hồ sau đó chỉ là phép xấp xỉ.
- Thời gian của participant, còn gọi là thời gian của venue hoặc sàn giao dịch. Đây là dấu thời gian venue ghi khi công bố giao dịch trên feed riêng, được truyền trong trường
participant_timestamp. Trong tất cả dữ liệu bạn có thể thực sự đọc, mốc này gần với matching engine nhất. - Thời gian SIP. Đây là dấu thời gian securities information processor ghi khi giao dịch đến consolidated tape, feed chính thức duy nhất hợp nhất mọi venue cổ phiếu Mỹ. Đây là trường
sip_timestamp, và thứ tự trên tape chính thức tuân theo mốc này. Sự khác biệt giữa feed đó và feed riêng của venue được trình bày trong SIP và feed trực tiếp của sàn giao dịch. - Thời gian capture. Đây là dấu thời gian card mạng của bạn ghi khi packet đến nơi. Mốc này không xuất hiện trong bản ghi của vendor vì nó mô tả đường truyền của bạn, không phải thị trường. Các công việc capture và phát lại packet hoàn toàn sử dụng đồng hồ này.
Các giao dịch ngoài sàn có thêm dấu thời gian thứ năm, trf_timestamp, cho biết thời điểm trade reporting facility tiếp nhận báo cáo.
Vì sao dấu thời gian dữ liệu thị trường khác nhau giữa các venue
Khoảng cách giữa dấu thời gian của venue và dấu thời gian hợp nhất là thời gian giao dịch đi qua đường truyền và hàng đợi của bộ xử lý. Đây không phải một con số cố định. Mỗi venue có khoảng cách khác nhau đến bộ xử lý, sử dụng phần cứng khác nhau và nằm sau một hàng đợi khác nhau. Bảng dưới đây đo khoảng cách đó cho mọi venue có giao dịch AAPL trong một khoảng 30 phút cố định vào ngày 10 tháng 6 năm 2026.
Câu lệnh SQL chính xác đằng sau mỗi con số
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 15Trong các venue đó, khoảng cách trung vị lớn nhất giữa dấu thời gian của venue và dấu thời gian hợp nhất là 346.2 microsecond, tại NYSE Arca, Inc.. Venue có khoảng cách nhỏ nhất trong cùng khung thời gian là 13.7 microsecond. Cột p99 đáng chú ý nhất: tại venue chậm nhất, khoảng cách này đạt 420.8 microsecond, cho thấy phần đuôi mà giá trị trung vị che khuất.
Nên sử dụng dấu thời gian nào
Bốn quy tắc bao quát gần như mọi trường hợp.
- Sử dụng thời gian của participant cho phân tích microstructure và event study. Mọi phân tích đo lường điều gì đã xảy ra tại một venue và theo thứ tự nào đều phải dùng đồng hồ của venue. Việc tái dựng order book, được trình bày trong dữ liệu order book MBO và MBP, sẽ không thể thực hiện đúng với bất kỳ đồng hồ nào khác.
- Sử dụng thời gian SIP cho mọi dữ liệu cần đối soát với tape chính thức. Bao gồm báo cáo theo quy định, đánh giá best execution, giá mở cửa và đóng cửa chính thức, cùng mọi số liệu mà đối tác sẽ kiểm tra với dữ liệu hợp nhất.
- Chỉ sử dụng thời gian capture để đo đường truyền của chính bạn. Mốc này cho biết dữ liệu mất bao lâu để đến máy của bạn. Nó không cho biết giao dịch xảy ra khi nào, và hai máy khác nhau sẽ không bao giờ có cùng giá trị.
- Không bao giờ trộn các đồng hồ trong cùng một bộ dữ liệu. Một phép join ghép quote theo một đồng hồ với giao dịch theo đồng hồ khác có thể tạo ra các con số nhìn hợp lý nhưng sai đúng vào những thời điểm quan trọng nhất.
Cùng một giao dịch, hai cách sắp xếp
Việc sắp xếp cho thấy rõ sự khác biệt này. Bảng dưới đây lấy mười millisecond có giao dịch nhiều nhất trong khoảng 30 phút đó, giữ lại mười hai giao dịch đầu tiên trên sàn theo thứ tự của venue, rồi xếp lại chính mười hai giao dịch đó theo thứ tự trên consolidated tape. Bảng được sắp xếp theo mức độ thay đổi thứ hạng của mỗi giao dịch giữa hai cách xếp.
Câu lệnh SQL chính xác đằng sau mỗi con số
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 ASCKhoảng cách lớn nhất giữa hai thứ hạng của một giao dịch là 6. Giao dịch đó rời venue lúc 10:44:17.160712 và đến tape sau 305.7 microsecond, vào lúc 10:44:17.161018, chuyển từ vị trí 6 theo đồng hồ của venue sang vị trí 12 trên tape. Không thứ tự nào sai. Chúng chỉ trả lời các câu hỏi khác nhau. Một nghiên cứu về chuỗi giao dịch sử dụng đồng hồ tape sẽ đọc đợt giao dịch này theo thứ tự mà không venue nào từng tạo ra, còn một đánh giá best execution sử dụng đồng hồ venue sẽ không khớp với dữ liệu chính thức.
Giao dịch ngoài sàn đến tape rất lâu sau khi sự kiện xảy ra
Một giao dịch được thực hiện ngoài sàn, tại wholesaler hoặc dark pool, sẽ được báo cáo cho trade reporting facility thay vì được khớp trên order book công khai. Báo cáo có thời gian thực hiện và đến tape sau đó. Khoảng thời gian này là độ trễ báo cáo, không phải thời gian truyền dữ liệu, và lớn hơn nhiều lần.
Câu lệnh SQL chính xác đằng sau mỗi con số
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) ASCTrong các giao dịch AAPL ngoài sàn trong khung thời gian đó, 24.8% giao dịch nằm trong bucket under 1 ms. Phần đuôi kéo dài đến bucket 1 s to 10 s, gồm 74 giao dịch. Một giao dịch đến muộn mười giây vẫn mang dấu thời gian của venue tại thời điểm thực hiện, nhưng nằm trong stream của tape ở vị trí muộn hơn mười giây. Nếu sắp xếp theo thời gian tape, giao dịch đó sẽ xuất hiện trong sai phút. Các giao dịch được báo cáo ngoài trình tự thông thường có sale condition code cho biết điều đó. Đây là một trong những mục đích của mã điều kiện giao dịch.
Vì sao hai người xây dựng các bar khác nhau từ cùng một tập giao dịch
Gần như mọi yêu cầu với nội dung “dữ liệu bị sai” đều bắt nguồn từ đây. Một bar là một bucket chứa các giao dịch, và giao dịch rơi vào bucket nào phụ thuộc vào dấu thời gian được dùng để phân nhóm. Bảng dưới đây đếm số giao dịch đổi bucket khi chuyển từ đồng hồ venue sang đồng hồ tape, trên bốn độ dài bar phổ biến.
Câu lệnh SQL chính xác đằng sau mỗi con số
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 ASCTrên lưới 1 second, có 8.966% giao dịch trong khung thời gian đó rơi vào bar khác khi dùng hai đồng hồ, tổng cộng 8944 giao dịch. Khi kéo dài bar lên 5 minutes, tỷ lệ này giảm xuống 0.024%. Quy luật hoàn toàn cơ học: một giao dịch đổi bucket khi khoảng cách giữa hai đồng hồ vượt qua ranh giới, và bar ngắn có nhiều ranh giới hơn. Hai vendor có thể đều đúng nhưng vẫn công bố khối lượng khác nhau cho cùng một phút. Cách xây dựng được trình bày trong cách xây dựng bar OHLCV.
Trường nanosecond không đồng nghĩa với độ chính xác nanosecond
Cả hai dấu thời gian đều được truyền dưới dạng số nguyên với độ phân giải nanosecond. Độ phân giải cho biết một trường có thể biểu thị chi tiết đến mức nào. Độ chính xác cho biết giá trị đó gần với thời gian thực đến đâu. Hai yếu tố này được quyết định bởi những điều hoàn toàn khác nhau.
Việc đồng bộ đồng hồ trong toàn ngành được điều chỉnh bằng ngưỡng dung sai theo quy định, không phải bởi giới hạn vật lý. Quy định đồng bộ đồng hồ của FINRA yêu cầu đồng hồ nghiệp vụ của các công ty thành viên lệch không quá 50 millisecond so với mốc tham chiếu NIST. Các sàn giao dịch và bộ xử lý sử dụng hệ thống chính xác hơn nhiều, với Precision Time Protocol (PTP, được tiêu chuẩn hóa theo IEEE 1588). Giao thức này phân phối đồng hồ tham chiếu trên cùng mạng truyền dữ liệu và duy trì độ lệch giữa các máy ở mức dưới một microsecond.
Có hai hệ quả. Trong các dấu thời gian của cùng một tổ chức, việc xác định thứ tự ở độ phân giải microsecond có ý nghĩa. Giữa các tổ chức, chênh lệch vài trăm nanosecond giữa hai dấu thời gian nằm trong biên sai số. Xem đó là thứ tự thực sẽ chỉ là diễn giải nhiễu.
Câu hỏi thường gặp
Dấu thời gian SIP khác gì dấu thời gian của participant?
Dấu thời gian của participant do venue ghi khi công bố giao dịch trên feed riêng. Dấu thời gian SIP do bộ xử lý consolidated tape ghi khi giao dịch đến feed hợp nhất chính thức. Khoảng cách giữa hai mốc là thời gian truyền và xếp hàng. Khoảng cách này được tính bằng microsecond đối với giao dịch trên sàn, và thường là millisecond hoặc lâu hơn đối với giao dịch được báo cáo qua trade reporting facility.
Nên sử dụng dấu thời gian dữ liệu thị trường nào để backtest?
Hãy sử dụng dấu thời gian của participant cho mọi mô hình mô phỏng những gì một participant có thể nhìn thấy hoặc thực hiện tại một venue. Sử dụng dấu thời gian SIP cho mọi dữ liệu cần đối soát với hồ sơ hợp nhất chính thức. Dù chọn mốc nào, bạn phải áp dụng nhất quán cho mọi bảng trong nghiên cứu, bao gồm cả quote.
Vì sao bar một phút của tôi không khớp với nhà cung cấp dữ liệu?
Câu trả lời thường là khác đồng hồ. Một giao dịch có dấu thời gian venue ngay trước ranh giới phút có thể có dấu thời gian tape ngay sau ranh giới đó. Vì vậy, cùng một giao dịch sẽ rơi vào các bar khác nhau theo hai quy ước. Các giao dịch ngoài sàn được báo cáo muộn sẽ làm chênh lệch lớn hơn.
Dấu thời gian nanosecond có chính xác đến nanosecond không?
Không. Trường dữ liệu có độ phân giải nanosecond, còn độ chính xác phụ thuộc vào mức độ đồng bộ của đồng hồ trên máy ghi. Hệ thống của sàn giao dịch và bộ xử lý sử dụng PTP duy trì độ lệch dưới một microsecond, trong khi đồng hồ nghiệp vụ của broker tuân theo ngưỡng dung sai 50 millisecond theo quy định. Những phép so sánh có độ chi tiết cao hơn ngưỡng dung sai của đồng hồ kém chính xác hơn sẽ không có ý nghĩa.
Mỗi bảng trên đều đi kèm SQL đã tạo ra bảng đó, để bạn có thể thấy chính xác mỗi con số bắt nguồn từ đồng hồ nào. Để sắp xếp lại khung giao dịch của bạn theo một đồng hồ khác và quan sát tape thay đổi, hãy đặt câu hỏi bằng tiếng Việt tự nhiên trên terminal Strasmore.