เจาะลึกโครงสร้างตลาด 29 มิถุนายน 2026
วิเคราะห์ข้อมูลการซื้อขายและราคาแบบละเอียดประจำวันที่ 29 มิถุนายน 2026 ครอบคลุมข้อมูล Tape, การแก้ไข Volume ตามรหัสข้อมูล และรายละเอียดไฟล์จาก FINRA
นี่คือข้อมูลประกอบเชิงลึกสำหรับ สรุปภาวะตลาดประจำวันที่ 29 มิถุนายน 2026: ข้อมูลดิบที่อยู่เบื้องหลังแท่งกราฟรายนาที — 156.1 ล้านรายการซื้อขาย และ 505.38 ล้านการอัปเดตราคา NBBO ภายในหนึ่งเซสชันของวันจันทร์ปกติ ทุกตัวเลขเป็นผลลัพธ์จากการสืบค้นข้อมูล (สามารถขยายส่วนต่างๆ เพื่อดูคำสั่ง SQL ที่แม่นยำ) และมีการรายงานรายละเอียดเชิงลึกสำหรับสองประเด็นที่ตรวจพบจากการตรวจสอบข้อมูลในวันนี้ ได้แก่ การแก้ไขปริมาณการซื้อขายตามข้อกำหนดของรหัสข้อมูลใน tape และไฟล์ข้อมูลจากผู้ให้บริการที่สิ้นสุดลงที่ตัวอักษร S อย่างผิดปกติ
รายงานการซื้อขาย รายการต่อรายการ
การตรวจสอบเซสชันต้องทำเป็นอันดับแรกและห้ามละเลย: ปฏิทินวันหยุดของตลาดหลักทรัพย์ระบุว่ามี 0 แถว สำหรับวันที่ 29 มิถุนายน 2026 และ SPY มีการบันทึกแท่งราคาแบบรายนาทีจำนวน 390 แท่ง ภายในช่วงเวลาทำการปกติ ซึ่งเป็นหนึ่งเซสชันเต็ม ตั้งแต่เวลา 9:30 น. ถึง 16:00 น. ตามเวลาของนิวยอร์ก สำหรับช่วงเวลาที่ขยายออกไป ข้อมูลการซื้อขายรวมบันทึกจำนวน 156.1 ล้านรายการ
SQL เบื้องหลังตัวเลขแต่ละตัว
WITH
(SELECT count() FROM global_markets.stocks_market_holidays WHERE date = '2026-06-29') AS holiday_rows,
(
SELECT countIf(window_start >= '2026-06-29 13:30:00' AND window_start < '2026-06-29 20:00:00')
FROM global_markets.delayed_stocks_minute_aggs
WHERE ticker = 'SPY' AND window_start >= '2026-06-29 00:00:00' AND window_start < '2026-06-30 00:00:00'
) AS spy_bars
SELECT
holiday_rows AS holiday_rows_jun29,
spy_bars AS spy_regular_session_bars,
round(count() / 1e6, 1) AS trades_m,
round(100.0 * countIf(size < 100) / count(), 2) AS odd_lot_pct_of_trades,
round(100.0 * toFloat64(sumIf(size, size < 100)) / toFloat64(sum(size)), 2) AS odd_lot_pct_of_shares,
multiIf(
countIf(size <= 19) >= 0.5 * count(), 19,
countIf(size <= 20) >= 0.5 * count(), 20,
countIf(size <= 21) >= 0.5 * count(), 21,
countIf(size <= 22) >= 0.5 * count(), 22,
countIf(size <= 23) >= 0.5 * count(), 23,
0) AS median_print_shares,
round(countIf(size = 1) / 1e6, 1) AS one_share_trades_m,
round(100.0 * countIf(size != round(size)) / count(), 2) AS fractional_pct_of_trades
FROM global_markets.stocks_trades
WHERE sip_timestamp >= '2026-06-29 00:00:00' AND sip_timestamp < '2026-06-30 00:00:00'72.61% ของรายการซื้อขายทั้งหมดเป็น odd lots หรือการซื้อขายที่น้อยกว่า 100 หุ้น แต่รายการเหล่านี้มีปริมาณหุ้นรวมเพียง 8.79% ของจำนวนหุ้นทั้งหมด ซึ่งเป็นยอดรวมที่ยังไม่ได้ปรับปรุงซึ่งจะถูกตัดออกในส่วนการวิเคราะห์ปริมาณการซื้อขายด้านล่าง ค่ามัธยฐานของรายการซื้อขายคือ 21 หุ้น วัดโดยใช้การตรวจสอบแบบ bracket probe ซึ่งเป็นการนับสะสมที่ 19 ถึง 23 หุ้น โดยจะคืนค่าเป็น 0 หากการตรวจสอบไม่พบ และมีการกำหนดขอบเขตเพื่อไม่ให้ค่าที่ผิดพลาดส่งผลต่อผลลัพธ์ มีรายการซื้อขายจำนวน 17.9 ล้านรายการที่เป็นการซื้อขายเพียงหนึ่งหุ้น และ 4.73% รายการมีการซื้อขายในรูปแบบเศษหุ้น ซึ่งเป็นรูปแบบที่สอดคล้องกับการที่แอปพลิเคชันสำหรับรายย่อยส่งคำสั่งซื้อขายทีละส่วน โดยมี market makers เป็นคู่สัญญาอีกด้านหนึ่ง
การตรวจสอบปริมาณการซื้อขาย: การหา "matched volume" จาก dictionary
ผลรวมของฟิลด์ size ในทุกรายการ print แสดงให้เห็นว่าวันที่ 29 มิถุนายน มีการซื้อขายทั้งหมด 24.79 billion shares ตัวเลขนี้ไม่ถูกต้อง และข้อมูลใน tape ระบุไว้เช่นนั้น ทุกรายการ print จะมี condition codes และ SIP — Securities Information Processor ซึ่งรวบรวมข้อมูลจากทุกแหล่งมาไว้ใน stream เดียวกัน — จะเผยแพร่ dictionary ที่ระบุว่าแต่ละรหัสจะอัปเดต consolidated volume หรือไม่ ข้อความบางอย่างเป็นการส่งข้อมูลซ้ำ (administrative re-broadcasts) ของปริมาณการซื้อขายที่นับไปแล้ว แทนที่จะใช้วิธีระบุรายการรหัสที่ "รู้จัก" ไว้ล่วงหน้า บทความนี้จะหาชุดข้อมูลที่จะยกเว้น (exclusion set) จาก dictionary โดยตรง:
SQL เบื้องหลังตัวเลขแต่ละตัว
SELECT
count() AS excluded_codes,
sum(id) AS excluded_id_checksum,
arrayStringConcat(arraySort(groupArray(concat(toString(id), ' ', name))), ' · ') AS codes
FROM global_markets.stocks_condition_codes
WHERE asset_class = 'stocks'
AND type = 'sale_condition'
AND JSONExtractBool(update_rules, 'consolidated', 'updates_volume') = 0เงื่อนไขการขาย 3 มีค่า updates_volume = false ในข้อมูล feed แบบ consolidated: 15 Market Center Official Close · 16 Market Center Official Open · 38 Corrected Consolidated Close (per listing market) บทเรียนที่ได้รับคือ: ร่างแรกของสรุปรายวันมีการระบุรหัส 15 และ 16 ไว้ล่วงหน้า ซึ่งเป็นข้อความเปิด/ปิดตลาดอย่างเป็นทางการที่คู่มือข้อมูลทุกฉบับระบุไว้ แต่กลับพลาดรหัส 38 ไปอย่างสิ้นเชิง ดังนั้น dictionary คือแหล่งข้อมูลที่ถูกต้อง (source of truth) ไม่ใช่รายการรหัสที่จดจำไว้
การใช้สอง block เป็นความตั้งใจ: การใช้ scalar subquery บน dictionary ภายในการ scan ข้อมูล 156.1-million-row ใช้เวลานานเกินขีดจำกัด 30 วินาทีของเรา ดังนั้น block ด้านบนจึงคำนวณหาชุดข้อมูลออกมาเป็นแถวเดียว โดยมีการจำกัดขอบเขตด้วยจำนวนรหัสและ id checksum (69) และ block ด้านล่างจะนำค่า literal ที่ได้ไปใช้งาน หาก dictionary เปลี่ยนแปลงไป ค่า checksum จะช่วยแจ้งเตือนให้ตรวจสอบบทความนี้ ทำให้ค่า literal ไม่ล้าสมัยโดยที่เราไม่ทราบ
SQL เบื้องหลังตัวเลขแต่ละตัว
SELECT
round(toFloat64(sum(size)) / 1e9, 2) AS raw_shares_bn,
round(toFloat64(sumIf(size, NOT hasAny(conditions, [15, 16, 38]))) / 1e9, 2) AS matched_shares_bn,
round(toFloat64(sumIf(size, hasAny(conditions, [15, 16, 38]))) / 1e9, 2) AS excluded_shares_bn,
countIf(hasAny(conditions, [15, 16, 38])) AS excluded_prints
FROM global_markets.stocks_trades
WHERE sip_timestamp >= '2026-06-29 00:00:00' AND sip_timestamp < '2026-06-30 00:00:00'การคำนวณที่ถูกต้อง: ปริมาณดิบคือ 24.79 billion shares, 20.66 billion คือจำนวนที่นับโดย SIP, และถูกยกเว้นไป 4.13 billion จากรายการ print เชิงบริหารจัดการ (administrative prints) จำนวน 91175 รายการ นิยามหนึ่งเดียวที่ระบุไว้อย่างชัดเจนคือ: "matched volume" หมายถึงปริมาณการซื้อขายที่กฎเงื่อนไขของ SIP นับรวมเข้ากับยอดรวมแบบ consolidated เท่านั้น ไม่มีความหมายอื่น เราไม่ได้ตัดสินว่าการซื้อขายใดมีความสำคัญทางเศรษฐกิจ แต่เรากำลังใช้หลักการบัญชีของ tape เอง
การตีความรายการซื้อขายขนาดใหญ่ที่สุด
รายการซื้อขายที่มีขนาดใหญ่ที่สุดของวัน คือจุดที่รหัสเงื่อนไข (condition codes) มีความสำคัญมากกว่าแค่ข้อมูลทั่วไป:
SQL เบื้องหลังตัวเลขแต่ละตัว
SELECT
ticker,
formatDateTime(toTimeZone(sip_timestamp, 'America/New_York'), '%H:%i:%S') AS et_time,
round(toFloat64(size) / 1e6, 2) AS shares_m,
toFloat64(price) AS price,
round(toFloat64(size) * toFloat64(price) / 1e6, 1) AS notional_usd_m,
round(100 * (toFloat64(size) * toFloat64(price)) / max(toFloat64(size) * toFloat64(price)) OVER (), 1) AS pct_of_biggest_dollar_print,
arrayStringConcat(arrayMap(c -> toString(c), conditions), ', ') AS condition_id
FROM global_markets.stocks_trades
WHERE sip_timestamp >= '2026-06-29 00:00:00' AND sip_timestamp < '2026-06-30 00:00:00'
AND size >= 10000000
AND NOT hasAny(conditions, [15, 16, 38])
ORDER BY size DESC
LIMIT 10พิจารณาแถวบนสุดเพื่อเป็นตัวอย่าง รายการซื้อขายที่ใหญ่ที่สุดของวัน คือหุ้น CAG (Conagra) จำนวน 61.69 ล้านหุ้น ที่ราคา $13.98 คิดเป็นมูลค่าประมาณ $862.5 ล้าน โดยระบุเวลา 16:04:53 ET ภายใต้รหัส 8, 41 (8 Closing Prints, 41 Trade Thru Exempt) ซึ่งเป็นผลจากการประมูลปิดตลาดของ NYSE ที่ประกาศหลังเวลา 16:00 น. รายการนี้จะถูกนับรวมในปริมาณการซื้อขายเพียงครั้งเดียว จากนั้นหุ้นจำนวน 61.69 ล้านหุ้นเดิมจะปรากฏขึ้นอีกครั้งภายใต้รหัส 15 (Market Center Official Close) ซึ่งเป็นการรายงานซ้ำที่พจนานุกรมข้อมูลไม่นำมานับรวม และเป็นส่วนหนึ่งของยอด 4.13 พันล้านที่ถูกตัดออกไปข้างต้น แถวรหัส-15 ดังกล่าวถูกออกแบบมาให้ตัดออกจากตารางด้านบน ดังนั้นข้อมูลการรับรายการนี้จึงมีแผงข้อมูลแยกต่างหากหนึ่งแถว:
SQL เบื้องหลังตัวเลขแต่ละตัว
SELECT
round(toFloat64(maxIf(size, has(conditions, 8))) / 1e6, 2) AS auction_print_shares_m,
round(toFloat64(maxIf(size, has(conditions, 15))) / 1e6, 2) AS official_close_reprint_shares_m,
round(toFloat64(maxIf(size, has(conditions, 8))) - toFloat64(maxIf(size, has(conditions, 15))), 2) AS share_difference,
formatDateTime(toTimeZone(argMaxIf(sip_timestamp, size, has(conditions, 15)), 'America/New_York'), '%H:%i:%S') AS reprint_et,
argMaxIf(exchange, size, has(conditions, 15)) AS reprint_exchange_id,
countIf(has(conditions, 15)) AS cag_code15_prints
FROM global_markets.stocks_trades
WHERE ticker = 'CAG'
AND sip_timestamp >= '2026-06-29 00:00:00' AND sip_timestamp < '2026-06-30 00:00:00'รายการที่ใหญ่ที่สุดในบรรดาข้อความปิดตลาดอย่างเป็นทางการ 6 รายการของ CAG มีจำนวน 61.69 ล้านหุ้น ซึ่งเท่ากับจำนวน 61.69 ล้านหุ้นจากการประมูลพอดี (ส่วนต่างคือ 0) ระบุเวลา 16:04:53 ET จาก exchange id 10 ซึ่งคือ NYSE ในสารบบหุ้น: เป็นการรายงานผลการประมูลซ้ำโดยตลาดหลักทรัพย์ที่จดทะเบียน
ส่วนอีก CAG แถวที่เหลือเป็นคนละประเภทกัน รายการซื้อขายจำนวน 15.17 ล้านหุ้นภายใต้รหัส 12, 2 (12 Form T / extended hours, 2 Average Price Trade) และอีกสองรายการภายใต้รหัส 12 คือรายการหลังการประมูลที่รายงานผ่าน FINRA ซึ่งมีเงื่อนไข updates_volume = true ระบบ SIP นับรายการเหล่านี้เป็นรายการซื้อขายจริง และข้อมูลที่จับคู่ของเราก็นับเช่นกัน
ในส่วนอื่นๆ รหัส 9 หมายถึงการจับคู่ปิดตลาดของ Nasdaq โดยรายการของ NVDA มูลค่า $3389.5 ล้าน คือรายการที่มีมูลค่าดอลลาร์สูงที่สุดในตาราง และรหัสในรายการ SNAP (53, 41) รวมถึงรหัส 53 ซึ่งเป็น Qualified Contingent Trade
เวลา: สิบนาทีที่ครองตลาดทั้งวัน
เมื่อพิจารณาความละเอียดระดับนาที ปริมาณการซื้อขายเกือบทั้งหมดจะกระจุกตัวอยู่บริเวณช่วงเปิดและช่วงปิดตลาด:
SQL เบื้องหลังตัวเลขแต่ละตัว
SELECT
formatDateTime(toTimeZone(toStartOfMinute(sip_timestamp), 'America/New_York'), '%H:%i') AS et_minute,
round(count() / 1e6, 2) AS trades_m
FROM global_markets.stocks_trades
WHERE sip_timestamp >= '2026-06-29 00:00:00' AND sip_timestamp < '2026-06-30 00:00:00'
GROUP BY et_minute
ORDER BY trades_m DESC
LIMIT 10ในช่วง 15:59 ET มีการซื้อขายเกิดขึ้น 3.98 ล้านรายการ — หรือมากกว่าหกหมื่นรายการต่อวินาที ส่วนข้อมูลว่าหุ้นตัวอื่นในกลุ่ม top ten จะกระจุกตัวอยู่เฉพาะช่วงเปิดและช่วงปิดตลาดหรือไม่นั้น สามารถพิจารณาได้จากบรรทัดเดียว:
SQL เบื้องหลังตัวเลขแต่ละตัว
SELECT
countIf(NOT (et_minute BETWEEN '09:30' AND '09:39' OR et_minute BETWEEN '15:50' AND '16:00')) AS entries_outside_open_close,
countIf(et_minute BETWEEN '09:30' AND '09:39' OR et_minute BETWEEN '15:50' AND '16:00') AS entries_in_open_close,
maxIf(et_minute, NOT (et_minute BETWEEN '09:30' AND '09:39' OR et_minute BETWEEN '15:50' AND '16:00')) AS outside_entry_minute,
maxIf(trades_m, NOT (et_minute BETWEEN '09:30' AND '09:39' OR et_minute BETWEEN '15:50' AND '16:00')) AS outside_entry_trades_m
FROM (
SELECT
formatDateTime(toTimeZone(toStartOfMinute(sip_timestamp), 'America/New_York'), '%H:%i') AS et_minute,
round(count() / 1e6, 2) AS trades_m
FROM global_markets.stocks_trades
WHERE sip_timestamp >= '2026-06-29 00:00:00' AND sip_timestamp < '2026-06-30 00:00:00'
GROUP BY et_minute
ORDER BY trades_m DESC
LIMIT 10
)9 ของหุ้นในกลุ่มสิบอันดับแรก มีปริมาณการซื้อขายในช่วงสิบนาทีแรกของการเปิดตลาดหรือสิบนาทีสุดท้ายก่อนปิดตลาด มีเพียงข้อยกเว้นเดียวคือ 10:15 ET ซึ่งมีการซื้อขายพุ่งสูงขึ้นถึง 0.88 ล้านรายการ และถือเป็นความผิดปกติในช่วงสายของวัน ข้อมูลนี้ไม่สามารถระบุสาเหตุที่แน่ชัดได้ และเราจะไม่คาดเดาเหตุผลดังกล่าว โดยช่วงเวลาเดียวกันนี้จะปรากฏในส่วนถัดไปด้านล่าง
กระแสข้อมูลราคา: การอัปเดตครึ่งพันล้านครั้ง
National Best Bid and Offer หรือราคาเสนอซื้อและเสนอขายที่ดีที่สุดจากทุกตลาดหลักทรัพย์ ซึ่งจะมีการเผยแพร่ใหม่ทุกครั้งที่มีการเปลี่ยนแปลงราคา มีการอัปเดตทั้งหมด 505.38 ล้านครั้ง เมื่อวันที่ 29 มิถุนายน โดยมีจำนวนการซื้อขายอยู่ที่ 156.1 ล้านรายการ
SQL เบื้องหลังตัวเลขแต่ละตัว
WITH
(
SELECT (round(countIf(ticker = 'QQQ') / 1e6, 2), round(countIf(ticker = 'NVDA') / 1e6, 2),
round(countIf(ticker = 'AAPL') / 1e6, 2), round(countIf(ticker = 'TSLA') / 1e6, 2))
FROM global_markets.cache_stocks_quotes
WHERE ticker IN ('QQQ', 'NVDA', 'AAPL', 'TSLA')
AND sip_timestamp >= '2026-06-29 00:00:00' AND sip_timestamp < '2026-06-30 00:00:00'
) AS pinned
SELECT
round(count() / 1e6, 2) AS updates_m,
pinned.1 AS qqq_updates_m,
pinned.2 AS nvda_updates_m,
round(pinned.1 - pinned.2, 2) AS qqq_minus_nvda_updates_m,
round(pinned.2 - greatest(pinned.3, pinned.4), 2) AS nvda_minus_next_single_m
FROM global_markets.cache_stocks_quotes
WHERE sip_timestamp >= '2026-06-29 00:00:00' AND sip_timestamp < '2026-06-30 00:00:00'ผลิตภัณฑ์ดัชนีเป็นกลุ่มที่มีการเสนอราคามากที่สุด โดย QQQ เพียงอย่างเดียวมีการอัปเดตถึง 5.23 ล้านครั้ง เมื่อเทียบกับ 1.8 ล้านครั้งของ NVDA ซึ่งเป็นหุ้นรายตัวที่มีการเสนอราคามากที่สุดจากการตรวจสอบของเรา โดยมีจำนวนการอัปเดตมากกว่าหุ้นรายตัวลำดับถัดไปถึง 0.67 ล้านครั้ง เนื่องจากการสำรวจข้อมูลทุกหลักทรัพย์อย่างละเอียดไม่สามารถดำเนินการได้ภายในข้อจำกัดเวลา 30 วินาที ดังนั้นตารางอันดับด้านล่างนี้จึงเป็นเพียงชุดข้อมูลที่ผ่านการตรวจสอบแล้ว ไม่ใช่การจัดอันดับทั้งหมด
SQL เบื้องหลังตัวเลขแต่ละตัว
SELECT ticker, round(count() / 1e6, 2) AS updates_m
FROM global_markets.cache_stocks_quotes
WHERE ticker IN ('QQQ', 'SPY', 'TQQQ', 'IWM', 'SQQQ', 'NVDA', 'AAPL', 'TSLA')
AND sip_timestamp >= '2026-06-29 00:00:00' AND sip_timestamp < '2026-06-30 00:00:00'
GROUP BY ticker
ORDER BY updates_m DESCQQQ เป็นผู้นำในชุดข้อมูลที่ตรวจสอบ โดยมีการอัปเดต 5.23 ล้านครั้ง ทั้งนี้ อันดับต้นๆ ของตารางคือกลุ่มกองทุนดัชนีและกองทุนที่มีอัตราทด (leveraged) ไม่ใช่หุ้นรายตัวที่เป็นที่รู้จักทั่วไป
เจาะลึก SPY: ข้อมูลระดับนาโนวินาที และความแตกต่างของ spread สองรูปแบบ
SQL เบื้องหลังตัวเลขแต่ละตัว
WITH
(
SELECT (formatDateTime(toTimeZone(toStartOfSecond(sip_timestamp), 'America/New_York'), '%H:%i:%S'), count())
FROM global_markets.cache_stocks_quotes
WHERE ticker = 'SPY' AND sip_timestamp >= '2026-06-29 13:30:00' AND sip_timestamp < '2026-06-29 20:00:00'
GROUP BY toStartOfSecond(sip_timestamp)
ORDER BY count() DESC, toStartOfSecond(sip_timestamp) ASC
LIMIT 1
) AS busiest_sec,
ordered AS (
SELECT
toFloat64(ask_price - bid_price) AS spread,
bid_price,
ask_price,
toFloat64(sip_timestamp - lagInFrame(sip_timestamp) OVER (ORDER BY sip_timestamp, sequence_number)) AS gap_s,
greatest(toFloat64(least(leadInFrame(sip_timestamp, 1, toDateTime64('2026-06-29 20:00:00', 9)) OVER (ORDER BY sip_timestamp, sequence_number ROWS BETWEEN CURRENT ROW AND 1 FOLLOWING), toDateTime64('2026-06-29 20:00:00', 9)) - sip_timestamp), 0) AS dwell_s,
rowNumberInAllBlocks() AS rn
FROM global_markets.cache_stocks_quotes
WHERE ticker = 'SPY' AND sip_timestamp >= '2026-06-29 13:30:00' AND sip_timestamp < '2026-06-29 20:00:00'
)
SELECT
round(count() / 1e6, 2) AS spy_updates_m,
busiest_sec.1 AS busiest_second_et,
toUInt8(startsWith(busiest_sec.1, '10:15')) AS busiest_second_in_1015,
busiest_sec.2 AS busiest_second_updates,
round(minIf(gap_s, rn > 0 AND gap_s > 0) * 1e9) AS min_gap_between_updates_ns,
round(quantileExactIf(0.5)(gap_s, rn > 0) * 1e6, 1) AS median_gap_us,
countIf(rn > 0 AND gap_s = 0) AS identical_timestamp_pairs,
round(sumIf(spread * dwell_s, bid_price > 0 AND ask_price >= bid_price) / sumIf(dwell_s, bid_price > 0 AND ask_price >= bid_price) * 100, 2) AS time_weighted_avg_spread_cents,
round(avgIf(spread, bid_price > 0 AND ask_price >= bid_price) * 100, 2) AS per_update_avg_spread_cents,
round((avgIf(spread, bid_price > 0 AND ask_price >= bid_price) - sumIf(spread * dwell_s, bid_price > 0 AND ask_price >= bid_price) / sumIf(dwell_s, bid_price > 0 AND ask_price >= bid_price)) * 100, 2) AS per_update_premium_cents,
countIf(bid_price > 0 AND ask_price > 0 AND ask_price < bid_price) AS crossed_updates,
countIf(bid_price <= 0 OR ask_price <= 0) AS zero_bid_or_ask_updates
FROM orderedราคาเสนอซื้อขายของ SPY มีการเปลี่ยนแปลงถึง 3.98 ล้านครั้งเฉพาะในช่วงเวลาทำการปกติเท่านั้น ช่วงเวลาที่มีการซื้อขายหนาแน่นที่สุดคือ 10:15:43 ET ภายในช่วงเวลา 10:15 นาทีที่ระบุไว้ข้างต้น โดยมีการอัปเดตข้อมูลถึง 1461 ครั้ง ระยะห่างที่สั้นที่สุดระหว่างการอัปเดตที่ต่อเนื่องกันคือ 1375 nanoseconds โดยมีค่ามัธยฐานอยู่ที่ 245.6 microseconds และมีข้อมูล 75138 คู่ที่ต่อเนื่องกันที่มีค่า timestamp ระดับ nanosecond เหมือนกัน ซึ่งแสดงให้เห็นว่าแม้แต่ความละเอียดระดับ nanosecond ก็ยังไม่สามารถจัดลำดับข้อมูลในตลาดสมัยใหม่ได้อย่างสมบูรณ์
ข้อมูลระดับ nanoseconds เหล่านี้มีความสำคัญในการวัด bid-ask spread หากนับการอัปเดตทุกครั้งด้วยน้ำหนักที่เท่ากัน ค่าเฉลี่ย spread ของ SPY จะอยู่ที่ 2.72 cents แต่หากถ่วงน้ำหนักแต่ละราคาตามระยะเวลาที่ราคานั้นคงอยู่ ค่าเฉลี่ยจะอยู่ที่ 2.34 cents ตัวเลขต่อการอัปเดตหนึ่งครั้งมีค่ากว้างกว่าในเชิงกลไกอยู่ 0.38 cents เนื่องจากข้อมูลการอัปเดตมักจะกระจุกตัวอยู่ในช่วงเวลาที่ spread กว้างและกำลังเคลื่อนไหว ในขณะที่คำสั่งซื้อขายที่รออยู่ในตลาดจะถูกนับตามเวลาจริง เมื่อคุณเห็นสถิติ spread ควรพิจารณาว่าใช้การวัดด้วยนาฬิกาประเภทใด ข้อมูลสถิติเหล่านี้มีการเปิดเผยอย่างชัดเจน: มีการอัปเดตในช่วงเวลาทำการปกติจำนวน 1544 ครั้งที่เกิดสภาวะราคาตัดกัน (ราคา ask ต่ำกว่า bid ซึ่งเกิดจากการสลับกันของราคาจากแหล่งซื้อขายที่ต่างกัน) และมี 0 ครั้งที่มีราคา bid หรือ ask เป็นศูนย์ โดยสถิติ spread จะไม่นับรวมทั้งสองกรณีนี้และจะนับเฉพาะข้อมูลที่ถูกคัดออกเท่านั้น
ส่วนต่างราคา (Spread) มีช่วงเวลาที่แน่นอน
การจัดกลุ่มค่า spread ของ SPY ตามช่วงเวลาทุกครึ่งชั่วโมง ช่วยให้เห็นโครงสร้างตลาดในรูปแบบเส้นโค้งที่นักเทรดสามารถนำไปใช้ประโยชน์ได้:
SQL เบื้องหลังตัวเลขแต่ละตัว
SELECT
formatDateTime(toTimeZone(toStartOfInterval(sip_timestamp, INTERVAL 30 MINUTE), 'America/New_York'), '%H:%i') AS et_time,
round(quantileExactIf(0.5)(toFloat64(ask_price - bid_price), bid_price > 0 AND ask_price >= bid_price) * 100, 1) AS median_spread_cents,
count() AS quote_updates
FROM global_markets.cache_stocks_quotes
WHERE ticker = 'SPY' AND sip_timestamp >= '2026-06-29 08:00:00' AND sip_timestamp < '2026-06-30 00:00:00'
GROUP BY et_time
ORDER BY et_timeค่ามัธยฐานอยู่ที่ 8 cents ในช่วง premarket ของ 04:00 ET, 3 cents ในช่วงเปิดตลาด 09:30 และอยู่ที่ 2 cents เมื่อถึงเวลา 14:00 — การซื้อขายหุ้นตัวเดียวกันในช่วงเปิด premarket มีต้นทุนสูงกว่าค่า spread ของคำสั่งซื้อขายในช่วงบ่ายต้นประมาณสี่เท่า ส่วนต่างราคาไม่ใช่ค่าคงที่ แต่เป็นตารางเวลาที่กำหนดไว้ชัดเจน
หลักฐานเชิงนิติวิทยาศาสตร์: ไฟล์ข้อมูลที่สิ้นสุดลงที่ตัวอักษร S
ไฟล์ข้อมูลรายวันจากผู้ให้บริการทุกรายต้องผ่านการตรวจสอบความครบถ้วนก่อนที่เราจะนำตัวเลขไปเผยแพร่ โดยการนับจำนวน tickers ตรวจสอบช่วงตัวอักษร และเปรียบเทียบกับข้อมูลในวันใกล้เคียง ไฟล์ข้อมูลปริมาณการขายชอร์ตนอกตลาด (off-exchange short-volume) ของ FINRA ประจำวันที่ 29 มิถุนายน คือตัวอย่างที่แสดงให้เห็นถึงเหตุผลดังกล่าว:
SQL เบื้องหลังตัวเลขแต่ละตัว
SELECT
date,
uniqExact(ticker) AS tickers,
min(ticker) AS first_ticker,
max(ticker) AS last_ticker,
countIf(ticker = 'TSLA') AS tsla_rows,
round(100 * sum(short_volume) / sum(total_volume), 2) AS short_pct_of_reported
FROM global_markets.stocks_short_volume
WHERE date BETWEEN '2026-06-26' AND '2026-06-30'
GROUP BY date
ORDER BY dateไฟล์ของวันที่ 26 มิถุนายน ครอบคลุม 15052 tickers ตั้งแต่ A ถึง ZYME ส่วนไฟล์ของวันที่ 29 มิถุนายน ครอบคลุมเพียง 5489 ตั้งแต่ A ถึง SSUS โดยข้อมูลหยุดลงกลางคันในช่วงชื่อที่ขึ้นต้นด้วยตัว S ทุก ticker ที่อยู่ถัดไปตามลำดับตัวอักษร รวมถึง TSLA ซึ่งมีจำนวน 0 แถวในวันที่ 29 มิถุนายน เทียบกับ 1 ในวันที่ 26 มิถุนายน ได้ขาดหายไป และเมื่อถึงวันที่ 30 มิถุนายน ไฟล์ข้อมูลกลับมามีจำนวน 15362 tickers การตรวจสอบความครบถ้วนนั้นไม่ซับซ้อนไปกว่าการตรวจสอบความถูกต้องของข้อมูลรายวันเช่นนี้ ซึ่งเป็นความแตกต่างระหว่างการเผยแพร่สถิติกับการเผยแพร่ข้อมูลที่ผิดพลาด
เมื่อพิจารณาจากการเปิดเผยข้อมูลดังกล่าว — และต้องพิจารณาควบคู่กันเท่านั้น — นี่คืออัตราส่วน: ปริมาณการขายชอร์ต (marked-short volume) คิดเป็น 45.85% ของปริมาณการซื้อขายนอกตลาดที่รายงานในวันที่ 29 มิถุนายน เทียบกับ 46.89% ในวันที่ 26 มิถุนายน และ 48.82% ในวันที่ 30 มิถุนายน ตัวเลขของวันที่ 29 มิถุนายน ครอบคลุมเพียงข้อมูลช่วงตัวอักษร A ถึง S ดังนั้นจึงควรพิจารณาว่าเป็นข้อมูลเพียงบางส่วน ปริมาณการขายชอร์ตเกือบครึ่งหนึ่งเป็นระดับปกติที่พบได้ในทุกช่วงเวลาที่ใกล้เคียงกัน และปริมาณการขายชอร์ตรายวันไม่ใช่ short interest
หมายเหตุข้อมูล
หมายเหตุข้อมูลฉบับเต็ม
- ช่วงตลาดเงียบเหงาเวลา 17:00 ถึง 18:00 น. กระแสราคาของ SPY จะเกือบหยุดนิ่งในช่วงครึ่งชั่วโมงของ 17:00 ET (233) และจะกลับมาเคลื่อนไหวอีกครั้งในช่วง 18:00 (40608) ซึ่งเป็นรูปแบบการส่งข้อมูลและช่วงเวลาที่เกิดขึ้นกับทุก ticker ไม่ใช่ข้อมูลที่ขาดหายไป
- มีการใช้หุ้นเศษส่วน (Fractional shares) ในทุกที่ 4.73% ของรายการที่บันทึกมีขนาดไม่เป็นจำนวนเต็ม ดังนั้นต้องรวมปริมาณการซื้อขาย (volume) โดยใช้ค่าทศนิยม
- พจนานุกรมรหัสมีการใช้ id ซ้ำกันในแต่ละประเภท Id 15 เป็นทั้งเงื่อนไขการขาย (Market Center Official Close) และเงื่อนไขราคา (Closed) ทุกการสืบค้นพจนานุกรมในที่นี้จะกรองด้วย asset_class = 'stocks' และ type = 'sale_condition' การสืบค้นด้วย id เพียงอย่างเดียวจะทำให้การระบุรหัสผิดพลาด
- การยกเว้นคุณภาพราคาถูกนับรวมไว้ในเนื้อหา จำนวนรายการที่ราคาตัดกัน (crossed) และรายการที่ไม่มีราคาเสนอซื้อหรือเสนอขาย (zero-bid-or-ask) จะแสดงอยู่ในแผง SPY microscope ด้านบน โดยไม่มีสถิติ spread ใดที่ปกปิดการลดลงของข้อมูลดังกล่าว
- การสแกนข้อมูลทั้งแถบ (Whole-tape scans) เป็นแผงข้อมูลแบบ batch-only ข้อมูลบล็อกทั่วทั้งตลาดที่แสดงที่นี่วัดค่าโดยใช้เวลาประมาณ 30 วินาทีต่อบล็อกบน cold cache (หากบล็อกหมดเวลาจะมีการลองใหม่หนึ่งครั้ง; การประมวลผลแบบ warmed pass จะล้างข้อจำกัดดังกล่าว) ข้อมูลเหล่านี้จะทำงานเพียงครั้งเดียว ณ เวลาที่ผู้เขียนจัดทำผ่านเส้นทางอ่านอย่างเดียว (read-only path) และผลลัพธ์ที่จัดเก็บไว้คือข้อมูลที่บันทึกไว้
ระเบียบวิธี
- ข้อมูลเวลาถูกจัดเก็บในรูปแบบ UTC และกรองด้วยขอบเขต UTC ดั้งเดิม (เวลาทำการปกติในวันที่ 29 มิถุนายน คือ 13:30 ถึง 20:00 UTC) โดยฟังก์ชัน toTimeZone จะปรากฏเฉพาะในรายการ SELECT เท่านั้น
- ประเภทของเซสชันจะถูกตรวจสอบเทียบกับปฏิทินวันหยุดและช่วงเวลาทำการปกติ 390-bar ที่ตรวจพบ โดยไม่มีการสมมติขึ้นเอง
- "SIP-counted (matched) volume" คือปริมาณการซื้อขายที่กฎเงื่อนไขของ SIP นับรวมเข้ากับยอดรวมรวม (consolidated total) โดยชุดข้อมูลที่ถูกยกเว้นจะถูกดึงมาจาก dictionary และมีการจำกัดด้วย checksum โดยไม่มีการกำหนดค่าตายตัว
- สถิติ spread ต่อการอัปเดต (per-update spread statistics) จะให้ค่าน้ำหนักกับการอัปเดต NBBO แต่ละครั้งเท่ากัน ส่วนสถิติแบบถ่วงน้ำหนักด้วยเวลา (time-weighted statistics) จะให้ค่าน้ำหนักตามระยะเวลาที่ราคาเสนอขายนั้นคงอยู่ โดยทั้งสองแบบจะมีการระบุข้อมูลที่ถูกยกเว้นไว้
- คอลัมน์ราคา/ขนาดที่เป็นทศนิยมจะถูกรวมค่าด้วยวิธี native และแปลงเป็น 64-bit floats ก่อนการคำนวณอัตราส่วนหรือราคาคูณขนาด
- ตาราง Tick จะเก็บประวัติฉบับเต็มโดยไม่มีการหมดอายุแบบ rolling; ผลลัพธ์ที่จัดเก็บและมีการระบุเวอร์ชันเหล่านี้คือบันทึกที่ถาวร ข้อมูลคลังข้อมูล ณ วันที่ 3 กรกฎาคม 2026
ทุกแผงข้อมูลด้านบนคือออบเจกต์ที่จัดเก็บไว้หนึ่งชุด ซึ่งประกอบด้วย กราฟ ตาราง และ SQL รวมกัน คุณสามารถเปิดรายการใดก็ได้ คัดลอกคำสั่ง query และนำไปใช้งานต่อบนเทอร์มินัล Strasmore ได้ทันที