Survivorship Bias ในข้อมูลหุ้นคืออะไรและส่งผลอย่างไร
Survivorship bias ทำให้ข้อมูลหุ้นขาดบริษัทที่ถูกเพิกถอนหรือถูกซื้อกิจการ ส่งผลให้การทำ Backtest คลาดเคลื่อนจากความเป็นจริง เรียนรู้วิธีวัดผลข้อมูลในระดับสากลเพื่อการวิเคราะห์ที่แม่นยำ
Survivorship bias ในข้อมูลหุ้นคือช่องว่างที่เกิดขึ้นเมื่อไฟล์ข้อมูลมีเฉพาะ Ticker ที่ยังคงมีการซื้อขายอยู่ในปัจจุบัน บริษัททั้งหมดที่ถูกเพิกถอนจากการเป็นหลักทรัพย์จดทะเบียน ถูกซื้อกิจการ เปลี่ยนชื่อ หรือปิดตัวลง จะหายไปอย่างเงียบเชียบ ทำให้การทำ Backtest บนชุดข้อมูลดังกล่าวเป็นการวัดผลจากกลุ่มตัวอย่างที่ถูกคัดกรองมาแล้ว ไม่ใช่สภาพตลาดที่เป็นจริงในขณะนั้น ข้อมูลในไฟล์ดูปกติทุกประการ แต่ละแถวมีราคาที่เกิดขึ้นจริง ปัญหาคือแถวข้อมูลที่ไม่มีใครบันทึกไว้นั่นเอง
Survivorship bias ในข้อมูลหุ้นคืออะไร?
ลองพิจารณาว่าชุดข้อมูล "หุ้นสหรัฐฯ ทั้งหมด" ถูกรวบรวมมาอย่างไร โดยทั่วไปจะมีกระบวนการขอรายชื่อสัญลักษณ์จากผู้ให้บริการข้อมูล แล้วจึงดึงประวัติราคาของแต่ละชื่อในรายการนั้น รายการดังกล่าวเป็นปัจจุบันโดยโครงสร้าง มันตอบคำถามว่า "ปัจจุบันมีอะไรให้เทรดบ้าง" และสัญลักษณ์ทุกตัวที่หยุดซื้อขายไปก่อนที่จะมีการร้องขอข้อมูลจะหายไปจากคำตอบ พร้อมกับประวัติทั้งหมดของมัน
คำนี้มีที่มาจากงานวิจัยของ Abraham Wald ในปี 1943 เกี่ยวกับเครื่องบินทิ้งระเบิดที่บินกลับฐาน โดยสรุปว่าควรติดเกราะในจุดที่เครื่องบินที่รอดกลับมาไม่มีรอยกระสุน เพราะเครื่องบินที่ถูกยิงในจุดเหล่านั้นไม่เคยได้กลับมาให้ตรวจวัด ฐานข้อมูลหุ้นที่สร้างจากรายชื่อหุ้นในปัจจุบันก็มีลักษณะเดียวกัน กลุ่มตัวอย่างที่คุณเห็นคือกลุ่มที่ "รอดกลับมา" และการได้เป็นส่วนหนึ่งของกลุ่มตัวอย่างนั้นถูกตัดสินด้วยผลลัพธ์ที่การทำ Backtest พยายามจะวัดผลนั่นเอง
มี Ticker จำนวนเท่าใดที่หายไปในแต่ละปี?
เริ่มต้นด้วยขนาดของช่องว่างนี้ ตารางด้านล่างจัดกลุ่มสัญลักษณ์ทั้งหมดในข้อมูลการซื้อขายรายวันตามปีปฏิทินของราคาปิดครั้งสุดท้าย โดยเก็บเฉพาะสัญลักษณ์ที่หยุดการซื้อขายไปก่อนเดือนมิถุนายน 2026
SQL เบื้องหลังตัวเลขแต่ละตัว
SELECT
toString(toYear(last_bar)) AS year,
count() AS gone_dark_count,
round(avg(bars_on_tape)) AS avg_bars_on_tape
FROM
(
SELECT
ticker,
max(date) AS last_bar,
count() AS bars_on_tape
FROM global_markets.stocks_daily_aggs
WHERE date >= '2015-01-01'
AND ticker NOT IN ('SPCX')
GROUP BY ticker
HAVING max(date) >= toDate('2016-01-01')
AND max(date) < toDate('2026-01-01')
)
GROUP BY year
ORDER BY yearใน 2025 มีสัญลักษณ์ 1283 ตัวที่พิมพ์ราคาปิดรายวันเป็นครั้งสุดท้ายและไม่เคยกลับมาอีกเลย นี่ไม่ใช่หุ้นปั่นที่เพิ่งเข้าตลาดเพียงสัปดาห์เดียว กลุ่มนี้มีค่าเฉลี่ยอยู่ที่ 999 วันทำการนับตั้งแต่ปี 2015 เป็นต้นมา ตลอดระยะเวลา 10 ปีในตาราง จำนวนนี้มีการเปลี่ยนแปลงและไม่มีปีใดที่ใกล้เคียงศูนย์ สัญลักษณ์ต่างๆ หายไปจากตลาดด้วยเหตุผลปกติ เช่น การควบรวมกิจการเสร็จสิ้น กองทุนปิดตัวลง การควบรวมบริษัท หรือการไม่ผ่านเกณฑ์การจดทะเบียน
สังเกตความเอนเอียงที่เกิดขึ้นในสคริปต์สิบบรรทัด
การคำนวณทางคณิตศาสตร์นั้นเห็นภาพได้ง่ายกว่าการอธิบาย สคริปต์ด้านล่างเขียนไฟล์ CSV ขนาดเล็กสองไฟล์ ได้แก่ ไฟล์จักรวาลหุ้นที่มีเฉพาะผู้รอดชีวิต และไฟล์เดิมที่เพิ่มชื่อหุ้นที่หยุดซื้อขายกลับเข้าไป จากนั้นคำนวณค่าเฉลี่ยของแต่ละไฟล์และแสดงส่วนต่าง สคริปต์นี้ใช้เพียงไลบรารีมาตรฐานของ Python จึงไม่ต้องติดตั้งอะไรเพิ่มเติม
python3 <<'PY'
import csv, statistics
survivors = [("AAA", 0.42), ("BBB", 0.18), ("CCC", 0.63), ("DDD", 0.07)]
delisted = [("EEE", -1.00), ("FFF", -0.55), ("GGG", 0.31)]
def write_csv(path, rows):
with open(path, "w", newline="") as f:
w = csv.writer(f)
w.writerow(["ticker", "total_return"])
w.writerows(rows)
def mean_return(path):
with open(path, newline="") as f:
return statistics.mean(float(r["total_return"]) for r in csv.DictReader(f))
write_csv("survivors_only.csv", survivors)
write_csv("full_universe.csv", survivors + delisted)
a = mean_return("survivors_only.csv")
b = mean_return("full_universe.csv")
print(f"survivors only: {a:+.1%} across {len(survivors)} names")
print(f"full universe: {b:+.1%} across {len(survivors) + len(delisted)} names")
print(f"survivorship bias: {a - b:+.1%}")
PY
ตัวเลขผลตอบแทนทั้งเจ็ดในสคริปต์นั้นถูกสมมติขึ้น ไม่ใช่ข้อมูลตลาดจริง แต่มีไว้เพื่อให้เห็นกลไกการทำงาน ค่าเฉลี่ยของกลุ่มผู้รอดชีวิตอยู่ที่ +32.5% ในขณะที่กลุ่มจักรวาลหุ้นเต็มรูปแบบอยู่ที่ +0.9% โดยส่วนต่าง 31.6 จุดคือค่าความเอนเอียง (bias) ไม่มีข้อมูลใดในไฟล์ผู้รอดชีวิตที่เป็นเท็จ หุ้นทั้งสี่ชื่อนั้นให้ผลตอบแทนตามที่ระบุจริง เพียงแต่ไฟล์นั้นไม่ได้กล่าวถึงหุ้นอีกสามตัวที่จะฉุดค่าเฉลี่ยให้ต่ำลง
การวัดผลแบบเดียวกันในกลุ่มหุ้นจริง
คราวนี้ลองคำนวณแบบเดียวกันกับข้อมูลจริง ตารางด้านล่างสร้างจักรวาลหุ้นเริ่มต้นในเดือนมกราคมของแต่ละปีตั้งแต่ 2016 ถึง 2022 โดยเก็บเฉพาะสัญลักษณ์ที่มีราคาเปิดเดือนนั้นสูงกว่า $5 และมีปริมาณการซื้อขายเฉลี่ยต่อวันสูงกว่า 250,000 หุ้น จากนั้นติดตามหุ้นทุกตัวจนถึงราคาปิดล่าสุด หุ้นที่หยุดซื้อขายจะถูกคงไว้ที่ราคาปิดสุดท้ายแทนที่จะถูกตัดออก คอลัมน์ผู้รอดชีวิตจะเฉลี่ยเฉพาะสัญลักษณ์ที่ยังมีการซื้อขายอยู่ ส่วนคอลัมน์จักรวาลหุ้นเต็มรูปแบบจะเฉลี่ยหุ้นทุกตัวที่มีอยู่ในตอนเริ่มต้น
SQL เบื้องหลังตัวเลขแต่ละตัว
WITH
entry AS
(
SELECT
ticker,
toYear(date) AS cohort_start,
argMin(toFloat64(close), date) AS entry_close
FROM global_markets.stocks_daily_aggs
WHERE toMonth(date) = 1
AND date BETWEEN '2016-01-01' AND '2022-01-31'
AND ticker NOT IN ('SPCX')
GROUP BY ticker, cohort_start
HAVING argMin(toFloat64(close), date) >= 5
AND avg(volume) >= 250000
),
outcome AS
(
SELECT
ticker,
argMax(toFloat64(close), date) AS final_close,
max(date) AS last_bar
FROM global_markets.stocks_daily_aggs
WHERE date >= '2016-01-01'
GROUP BY ticker
)
SELECT
toString(e.cohort_start) AS cohort_year,
count() AS cohort_size,
countIf(o.last_bar < today() - 45) AS gone_count,
round(100 * avgIf(o.final_close / e.entry_close - 1, o.last_bar >= today() - 45), 1) AS survivors_only_pct,
round(100 * avg(o.final_close / e.entry_close - 1), 1) AS full_universe_pct,
round(100 * (avgIf(o.final_close / e.entry_close - 1, o.last_bar >= today() - 45)
- avg(o.final_close / e.entry_close - 1)), 1) AS gap_pct
FROM entry AS e
INNER JOIN outcome AS o ON o.ticker = e.ticker
GROUP BY e.cohort_start
HAVING countIf(o.last_bar >= today() - 45) > 0
ORDER BY e.cohort_startสำหรับกลุ่มหุ้นปี 2016 มีหุ้น 968 จากทั้งหมด 2728 ตัวที่หายไปจากตลาด ณ เวลาที่จัดทำหน้านี้ การเฉลี่ยเฉพาะผู้รอดชีวิตให้ผลลัพธ์ 212% ในขณะที่การเฉลี่ยทั้งกลุ่มให้ผลลัพธ์ 149.3% คอลัมน์ส่วนต่างแสดงระยะห่างระหว่างค่าทั้งสอง คือ 62.7 จุดสำหรับกลุ่มปีนั้น และ 9.1 จุดสำหรับกลุ่มปี 2022 ซึ่งมีเวลาในการสูญเสียสมาชิกน้อยกว่า นี่คือผลตอบแทนรวมในช่วงเวลาที่มีความยาวต่างกัน ดังนั้นควรดูไล่ลงมาในคอลัมน์ส่วนต่างแทนการเปรียบเทียบระดับระหว่างแถว คำถามเรื่องจักรวาลหุ้นเดียวกันนี้เป็นพื้นฐานของ วิธีการวัดผลตอบแทนรายเดือน และการคำนวณค่าเฉลี่ยแบบถ่วงน้ำหนักเท่ากันทุกตัว
จุดจบของชื่อหุ้นที่หายไป
การถูกเพิกถอนไม่ได้หมายถึงการสูญเสียทั้งหมดเสมอไป ตารางด้านล่างใช้จักรวาลหุ้นเริ่มต้นในเดือนมกราคม 2019 และจัดกลุ่มตามสิ่งที่เกิดขึ้นหลังจากนั้น
SQL เบื้องหลังตัวเลขแต่ละตัว
WITH
entry AS
(
SELECT
ticker,
argMin(toFloat64(close), date) AS entry_close
FROM global_markets.stocks_daily_aggs
WHERE date BETWEEN '2019-01-01' AND '2019-01-31'
AND ticker NOT IN ('SPCX')
GROUP BY ticker
HAVING argMin(toFloat64(close), date) >= 5
AND avg(volume) >= 250000
),
outcome AS
(
SELECT
ticker,
argMax(toFloat64(close), date) AS final_close,
max(date) AS last_bar
FROM global_markets.stocks_daily_aggs
WHERE date >= '2019-01-01'
GROUP BY ticker
)
SELECT
if(o.last_bar >= today() - 45,
'Still trading',
concat('Last bar in ', toString(toYear(o.last_bar)))) AS outcome_label,
count() AS cohort_size,
round(100 * avg(o.final_close / e.entry_close - 1), 1) AS avg_return_pct,
round(100 * countIf(o.final_close > e.entry_close) / count(), 1) AS share_above_entry_pct
FROM entry AS e
INNER JOIN outcome AS o ON o.ticker = e.ticker
GROUP BY outcome_label
ORDER BY outcome_labelกลุ่ม Still trading มีหุ้น 1954 ตัว ให้ผลตอบแทนเฉลี่ย 139.8% จากราคาเริ่มต้นในเดือนมกราคม 2019 โดยมี 72.1% ของหุ้นกลุ่มนี้ที่มีราคาสูงกว่าจุดเริ่มต้น ลองอ่านแถว 9 แล้วจะเห็นว่าผลลัพธ์ค่อนข้างหลากหลาย บริษัทที่ถูกซื้อกิจการด้วยราคาพรีเมียมอาจออกจากตลาดด้วยราคาปิดที่แข็งแกร่ง ในขณะที่บริษัทที่ค่อยๆ ซบเซาจนถูกเพิกถอนจะออกจากตลาดด้วยราคาที่อ่อนแอ ทั้งสองกรณีหายไปจากไฟล์ที่มีเฉพาะผู้รอดชีวิต หากใส่กลับเข้าไป ค่าเฉลี่ยก็จะเปลี่ยนไป
Survivorship bias เทียบกับ Look ahead bias
ทั้งสองเรื่องนี้มักถูกจัดอยู่ในหมวดหมู่เดียวกัน แต่สร้างความเสียหายต่อการทำ Backtest ในจุดที่ต่างกัน Look ahead bias เป็นปัญหาด้านเวลา: การทดสอบใช้ข้อเท็จจริงในช่วงเวลาที่ยังไม่มีใครทราบ เช่น ตัวเลขกำไรที่ปรับปรุงใหม่หรือการปรับเปลี่ยนที่เกิดขึ้นในหลายเดือนต่อมา ส่วน Survivorship bias เป็นปัญหาด้านสมาชิก: รายชื่อหุ้นที่ใช้ในการทดสอบคือรายชื่อที่มีอยู่ในปัจจุบัน ไม่ใช่รายชื่อที่มีอยู่ในขณะนั้น การทำ Backtest อาจแม่นยำเรื่องเวลาแต่ยังคงเทรดบนจักรวาลหุ้นที่รวบรวมด้วยความได้เปรียบของข้อมูลย้อนหลัง การปรับราคาหุ้นก็นำมาซึ่งกับดักที่เกี่ยวข้อง เนื่องจาก ประวัติราคาที่ปรับปรุงจากหุ้นแตกพาร์ จะเขียนทับระดับราคาของทุกแท่งก่อนวันแตกพาร์
วิธีแก้ไข Survivorship bias ในการทำ Backtest
- สร้างจักรวาลหุ้นใหม่ ณ แต่ละวันที่ทำการทดสอบ (Point in time): หมายความว่ารายชื่อหุ้นจะถูกสร้างขึ้นใหม่สำหรับวันที่ทำการทดสอบ โดยใช้บันทึกที่มีอยู่จริงในวันนั้น การทดสอบจะถือหุ้นที่ยังมีการซื้อขายอยู่ในขณะนั้น รวมถึงหุ้นที่หายไปในภายหลังด้วย
- จัดทำ Security master: Security master จะทำหน้าที่เชื่อมโยงตัวระบุ (Identifier) ตลอดช่วงเวลา ว่าสัญลักษณ์ใดชี้ไปยังบริษัทใดในช่วงวันที่เท่าใด และมีอะไรมาแทนที่หลังจากมีการควบรวมหรือเปลี่ยนชื่อ ไฟล์ราคาจะอ้างอิงตามสัญลักษณ์ แต่บริษัทไม่ได้อ้างอิงตามสัญลักษณ์เสมอไป
- ปิดสถานะหุ้นที่ถูกเพิกถอนที่ราคาจริงสุดท้าย: เมื่อหุ้นหายไปจากตลาด สถานะควรถูกปิดที่ราคาปิดสุดท้ายแทนที่จะหายไปจากค่าเฉลี่ย การลบข้อมูลออกคือสิ่งที่ทำให้เกิดช่องว่างในตารางด้านบน การทำ Backtest ที่ทำซ้ำได้ จะกำหนดกฎนี้ไว้ในโค้ดควบคู่ไปกับจักรวาลหุ้น
- อ่านเอกสารของผู้ให้บริการข้อมูลเกี่ยวกับสัญลักษณ์ที่ตายแล้ว: ผู้ให้บริการที่ให้ความสำคัญกับเรื่องนี้จะระบุไว้ชัดเจน Massive เปิดเผยสัญลักษณ์ที่ถูกเพิกถอนผ่านทาง Ticker endpoint พร้อมสถานะ active flag และบันทึกการเปลี่ยนสัญลักษณ์ การเพิกถอน การควบรวม และการเข้าซื้อกิจการไว้เป็นบันทึกใน Ticker events endpoint แยกต่างหาก
"เราไม่เปลี่ยนแปลงข้อมูลหรือนำการเปลี่ยนแปลง Ticker มาต่อกันเป็นชุดข้อมูลเดียว"
ฐานความรู้ Massive, "Massive จัดการกับการเปลี่ยน Ticker และการเข้าซื้อกิจการอย่างไร?", อ่านเมื่อสิงหาคม 2026
หากเอกสารของผู้ให้บริการไม่ได้ระบุถึงสัญลักษณ์ที่ถูกเพิกถอน ให้ถือว่าข้อมูลที่ดาวน์โหลดมามีเฉพาะผู้รอดชีวิตจนกว่าคุณจะตรวจสอบ ความครอบคลุมของข้อมูลมีความแตกต่างกันมากในแต่ละแหล่งข้อมูล: ดูบันทึกของเราเกี่ยวกับ API ข้อมูลหุ้นฟรี
กับดักการนำ Ticker กลับมาใช้ใหม่
สัญลักษณ์ต่างๆ จะถูกนำกลับมาหมุนเวียนใช้ใหม่หลังจากที่การจดทะเบียนเดิมสิ้นสุดลง ตารางด้านล่างนับจำนวนสัญลักษณ์ที่มีราคาปิดรายวันอย่างน้อย 200 วัน เงียบหายไปอย่างน้อย 250 วันปฏิทิน แล้วปรากฏขึ้นมาใหม่ในฐานะหุ้นจดทะเบียนใหม่ตั้งแต่ปี 2022 เป็นต้นไป
SQL เบื้องหลังตัวเลขแต่ละตัว
SELECT
toString(toYear(relisted_on)) AS year,
count() AS relisting_count,
round(avg(dark_stretch)) AS avg_dark_stretch,
max(dark_stretch) AS longest_dark_stretch
FROM
(
SELECT
ticker,
any(relist_date) AS relisted_on,
dateDiff('day', max(date), any(relist_date)) AS dark_stretch
FROM
(
SELECT
d.ticker AS ticker,
d.date AS date,
i.relist_date AS relist_date
FROM global_markets.stocks_daily_aggs AS d
INNER JOIN
(
SELECT
ticker,
min(toDate(listing_date)) AS relist_date
FROM global_markets.stocks_ipos
WHERE toDate(listing_date) BETWEEN '2022-01-01' AND today()
AND ticker NOT IN ('SPCX')
GROUP BY ticker
) AS i ON i.ticker = d.ticker
WHERE d.date < i.relist_date
)
GROUP BY ticker
HAVING dateDiff('day', max(date), any(relist_date)) >= 250
AND count() >= 200
)
GROUP BY year
ORDER BY yearใน 2022 มีสัญลักษณ์ 16 ตัวที่กลับมาในลักษณะนี้ หลังจากเงียบหายไปเฉลี่ย 3247 วันปฏิทิน ช่วงเวลาที่เงียบหายไปนานที่สุดในแถวนั้นคือ 5734 วัน ไฟล์ราคาที่อ้างอิงตามสัญลักษณ์เพียงอย่างเดียวจะนำประวัติของบริษัทหนึ่งไปต่อกับอีกบริษัทหนึ่ง และการเชื่อมต่อดูราบรื่นตลอดทั้งชุด นี่คือกรณีที่ Security master ตรวจพบได้ แต่คอลัมน์ Ticker เปล่าๆ ไม่สามารถทำได้
หมายเหตุข้อมูลและคำจำกัดความ
สัญลักษณ์จะถูกนับว่ายังมีการซื้อขายอยู่เมื่อราคาปิดรายวันล่าสุดอยู่ในช่วง 45 วันปฏิทินนับจากวันที่สร้างหน้านี้ บัฟเฟอร์นี้ครอบคลุมความล่าช้าหนึ่งถึงสองวันในช่วงต้นของข้อมูลและหุ้นที่มีสภาพคล่องต่ำซึ่งอาจขาดช่วงการซื้อขาย
ผลตอบแทนคือผลตอบแทนรวมของราคาจากราคาปิดของเดือนมกราคมจนถึงราคาปิดล่าสุดที่มีสำหรับสัญลักษณ์นั้น โดยไม่มีเงินปันผลและไม่มีการปรับเป็นรายปี กลุ่มหุ้นรุ่นก่อนหน้ามีเวลาในการทบต้นนานกว่า ดังนั้นระดับผลตอบแทนจึงไม่สามารถเปรียบเทียบข้ามแถวได้ แต่ส่วนต่างระหว่างค่าเฉลี่ยทั้งสองนั้นเปรียบเทียบกันได้
จักรวาลหุ้นเริ่มต้นจะเก็บเฉพาะสัญลักษณ์ที่มีราคา $5 ขึ้นไป และมีปริมาณการซื้อขายเฉลี่ยต่อวัน 250,000 หุ้นขึ้นไปในช่วงเดือนที่เริ่มต้น ข้อมูลการซื้อขายรายวันประกอบด้วยกองทุน หน่วยลงทุน และใบสำคัญแสดงสิทธิควบคู่ไปกับบริษัทดำเนินงาน และไม่มีการแยกประเภทในที่นี้ ดังนั้นการปิดกองทุนจึงถูกนับรวมไปพร้อมกับการเพิกถอนบริษัท สัญลักษณ์ที่มีความขัดแย้งของตัวตนในฟีดข้อมูลของผู้ให้บริการจะถูกแยกออกด้วย SQL จากทุกตารางแทนที่จะถูกกรองออกในภายหลัง
คำถามที่พบบ่อย (FAQ)
Survivorship bias ในการทำ Backtest หุ้นคืออะไร?
คือความผิดพลาดที่เกิดขึ้นเมื่อจักรวาลหุ้นที่ใช้เทรดถูกสร้างขึ้นจากสัญลักษณ์ที่ยังคงมีอยู่ในปัจจุบัน บริษัทที่ถูกเพิกถอนหรือถูกซื้อกิจการจะไม่เคยเข้าสู่การทดสอบ ทำให้กลยุทธ์นั้นได้รับเฉพาะรายชื่อหุ้นที่รอดมาถึงปัจจุบันเท่านั้น
ฉันจะรู้ได้อย่างไรว่าชุดข้อมูลของฉันมี Survivorship bias?
ให้ดูจักรวาลหุ้นที่ไฟล์ของคุณอ้างว่าครอบคลุมในช่วงหลายปีก่อน แล้วตรวจสอบราคาปิดสุดท้ายของแต่ละสัญลักษณ์ หากทุกชื่อในรายการปี 2016 ยังคงมีการพิมพ์ราคาอยู่ในปัจจุบัน แสดงว่ารายการนั้นถูกสร้างจากรายชื่อหุ้นปัจจุบัน และหุ้นที่ตายไปแล้วไม่เคยอยู่ในนั้น
Survivorship bias ทำให้ผลการทำ Backtest ดูดีขึ้นเสมอไปหรือไม่?
ไม่เสมอไป ทิศทางขึ้นอยู่กับว่าหุ้นออกจากตลาดอย่างไร การถูกซื้อกิจการอาจปิดสถานะด้วยราคาพรีเมียม และการตัดหุ้นเหล่านั้นออกอาจทำให้ผลตอบแทนของกลุ่มต่ำกว่าความเป็นจริง ในขณะที่การค่อยๆ ซบเซาจนถูกเพิกถอนจะให้ผลตรงกันข้าม ตารางด้านบนวัดผลสุทธิของทั้งสองกรณีในกลุ่มหุ้นจริง
จักรวาลหุ้นแบบ Point in time คืออะไร?
คือรายชื่อสมาชิกที่ถูกสร้างขึ้นใหม่ ณ แต่ละวันที่ทำการทดสอบ โดยใช้เฉพาะบันทึกที่มีอยู่จริงในวันนั้น ประกอบด้วยชื่อหุ้นที่สามารถเทรดได้ในขณะนั้นและหายไปในภายหลัง และไม่รวมชื่อหุ้นที่ยังไม่ได้เข้าจดทะเบียน
Survivorship bias เหมือนกับ Look ahead bias หรือไม่?
ไม่เหมือนกัน Look ahead bias เกี่ยวกับเวลา: การทดสอบใช้ข้อมูลก่อนที่ใครจะทราบ ส่วน Survivorship bias เกี่ยวกับสมาชิก: การทดสอบเทรดบนรายชื่อหุ้นที่รวบรวมด้วยความได้เปรียบของข้อมูลย้อนหลัง การทำ Backtest อาจสะอาดในเรื่องหนึ่งแต่พังในอีกเรื่องหนึ่ง
ทุกตารางที่นี่มี SQL ที่ใช้สร้างข้อมูลกำกับอยู่ เปลี่ยนเดือนที่เริ่มต้นหรือปรับตัวกรองสภาพคล่อง แล้วรันบน Strasmore terminal เพื่อดูว่าส่วนต่างนั้นยังคงอยู่มากน้อยเพียงใดภายใต้กฎจักรวาลหุ้นของคุณเอง