GARCH(1,1): การพยากรณ์ความผันผวนของคริปโต
ลองเปิดกราฟผลตอบแทนรายวันของ BTC แล้วคุณจะสังเกตเห็นบางอย่างที่ตำราเรื่อง random walk ไม่เคยเตรียมคุณให้พร้อม นั่นคือความสงบและความโกลาหลมักมาเป็นกลุ่มก้อน วันที่ราคาลง 6% แทบไม่เคยเกิดขึ้นเดี่ยวๆ มันอยู่ท่ามกลางสัปดาห์ที่ราคาแกว่ง 4-8% แล้วตลาดก็หายใจออก ลอยผ่านไปทั้งเดือนของเซสชันที่ง่วงเหงาแค่ 1% ก่อนพายุลูกถัดไปจะมา ตัวผลตอบแทนเองดูใกล้เคียงกับสิ่งที่คาดเดาไม่ได้ คุณไม่สามารถบอกได้อย่างน่าเชื่อถือว่าพรุ่งนี้จะขึ้นหรือลง แต่ ขนาด ของมันกลับคาดเดาได้อย่างลึกซึ้ง ความปั่นป่วนของวันนี้บอกอะไรได้มากมายเกี่ยวกับพรุ่งนี้
เครื่องมือจัดการความเสี่ยงเกือบทุกชิ้นที่เทรดเดอร์หยิบมาใช้ ล้วนสมมติเงียบๆ ว่าเรื่องนี้ไม่จริง Black-Scholes ตั้งราคาออปชันด้วย คงที่เพียงค่าเดียว ตัวเลข Value-at-Risk แบบสถิตนำการประมาณความผันผวนค่าเดียวคูณกับ normal quantile ส่วน stop-loss คงที่ที่ 3% ก็ปฏิบัติต่อวันอังคารที่ตลาดนิ่งไร้ทิศทางกับช่วงเวลารอบๆ การประกาศของ FOMC หรือการ de-peg ครั้งใหญ่ของเอ็กซ์เชนจ์ราวกับว่าทั้งสองแบกความเสี่ยงเท่ากัน แต่ละอย่างพังในแบบเดียวกันเป๊ะ นั่นคือมันยุบปริมาณที่เปลี่ยนแปลงตามเวลาให้กลายเป็นค่าคงที่ แล้วก็ประหลาดใจเมื่อค่าคงที่นั้นกลับขยับ
บทความนี้คือ Part 1 ของซีรีส์สี่ตอนว่าด้วยการสร้างโมเดลความผันผวนสำหรับคริปโต มันวางรากฐาน ได้แก่ โมเดล GARCH(1,1) เหตุผลที่มันเข้ากับผลตอบแทนคริปโตได้ดีนัก วิธีประมาณค่าอย่างซื่อตรงด้วย maximum likelihood ผ่านไลบรารี arch และวิธีแปลงการพยากรณ์ conditional variance ให้กลายเป็นสองสิ่งที่ใช้งานได้ทันที นั่นคือขนาดโพซิชันและความกว้างของ stop ที่ต่างก็หายใจไปพร้อมกับตลาด Part 2 เพิ่มความไม่สมมาตรและหางหนา Part 3 ขยายไปสู่หลายตัวแปร และ Part 4 ประกอบร่าง backtest แบบ volatility-targeting เต็มรูปแบบ เราจงใจให้การประยุกต์ใช้ที่นี่เรียบง่าย ส่วนกลยุทธ์ที่ซื่อตรงและผ่านการตรวจสอบแบบ walk-forward เป็นหัวข้อของ Part 4
ข้อเท็จจริงเชิงลักษณะ (Stylized Facts) ของผลตอบแทนคริปโต
ก่อนจะสร้างโมเดลอะไร ควรให้ความชัดเจนว่าเรากำลังพยายามจำลองอะไรอยู่ ผลตอบแทนทางการเงินเชิงประจักษ์ ไม่ว่าจะเป็นหุ้น FX และคริปโตโดยเฉพาะ ต่างมีชุดของความสม่ำเสมอเชิงสถิติที่เข้มแข็งเพียงเล็กน้อยร่วมกัน ซึ่งได้รับการบันทึกมาหลายทศวรรษ มักเรียกกันว่า stylized facts และสามข้อในนั้นเป็นตัวขับเคลื่อนทุกสิ่งที่ตามมา
1. การเกาะกลุ่มของความผันผวน (Volatility clustering). การเคลื่อนไหวขนาดใหญ่มักตามมาด้วยการเคลื่อนไหวขนาดใหญ่ (ไม่ว่าจะเครื่องหมายใด) และการเคลื่อนไหวขนาดเล็กตามมาด้วยขนาดเล็ก Mandelbrot สังเกตเห็นสิ่งนี้ในราคาฝ้ายเมื่อปี 1963 ในทางรูปนัย ขณะที่ผลตอบแทน ใกล้เคียงกับการไม่มี serial correlation แต่ผลตอบแทน ยกกำลังสอง (ตัวแทนของ realized variance) กลับแสดง positive autocorrelation ที่เข้มแข็งและสลายตัวช้า
2. หางหนา (Fat tails / leptokurtosis). การแจกแจงแบบไม่มีเงื่อนไขของผลตอบแทนมีมวลอยู่ในบริเวณสุดขั้วมากกว่าแบบ Gaussian อย่างมาก ในขณะที่การแจกแจงปกติมี kurtosis เท่ากับ 3 ผลตอบแทน log รายวันของ BTC มักอยู่เหนือระดับ 8-10 เป็นประจำ และผลตอบแทนคริปโตที่ความถี่สูงกว่าอาจแย่กว่านั้น วันที่เกิดเหตุการณ์ six-sigma ซึ่งโมเดลปกติบอกว่าน่าจะเกิดราวหนึ่งครั้งต่อล้านปี กลับปรากฏหลายครั้งในหนึ่งทศวรรษ
3. ไม่มี linear autocorrelation ในผลตอบแทน แต่มี autocorrelation ที่เข้มแข็งในผลตอบแทนยกกำลังสอง. นี่คือลายนิ้วมือที่แยกกระบวนการความผันผวนที่แท้จริงออกจากเทรนด์ธรรมดา ถ้าคุณ regress กับ lag ของตัวมันเอง คุณจะไม่ได้อะไรที่นำไปใช้ประโยชน์ได้ แต่ถ้าคุณ regress กับ lag ของมัน คุณจะพบสัญญาณที่ชัดเจนและคงอยู่ยาวนาน นี่คือโครงสร้างที่โมเดล variance ควรจับให้ได้อย่างแม่นยำ และเป็นสิ่งที่โมเดล คงที่โยนทิ้งไปพอดี
เราสามารถมองเห็นทั้งสามอย่างได้ในไม่กี่บรรทัด ไม่มีอะไรที่นี่ต้องการแหล่งข้อมูลพิเศษ ในการใช้งานจริงให้ใช้ ccxt แต่สำหรับสนิปเป็ตที่ทำซ้ำได้ yfinance ก็เพียงพอ
import numpy as np
import pandas as pd
import yfinance as yf
from statsmodels.graphics.tsaplots import plot_acf
from statsmodels.stats.diagnostic import acorr_ljungbox
from scipy import stats
px = yf.download("BTC-USD", start="2021-01-01", end="2025-12-31")["Close"]
ret = np.log(px / px.shift(1)).dropna() # log returns
ret = ret.rename("btc")
print(f"Observations: {len(ret)}")
print(f"Ann. volatility: {ret.std() * np.sqrt(365):.2%}")
print(f"Skewness: {stats.skew(ret):.2f}")
print(f"Excess kurtosis: {stats.kurtosis(ret):.2f}") # 0 == Gaussian
lb_ret = acorr_ljungbox(ret, lags=[10], return_df=True)
lb_ret2 = acorr_ljungbox(ret ** 2, lags=[10], return_df=True)
print("\nLjung-Box p-value, returns (lag 10):", float(lb_ret["lb_pvalue"].iloc[0]))
print("Ljung-Box p-value, squared (lag 10):", float(lb_ret2["lb_pvalue"].iloc[0]))
ค่าที่มักอ่านได้ (เป็นเพียงตัวอย่าง หน้าต่างข้อมูลของคุณจะต่างออกไป) คือ excess kurtosis สูงกว่า 3 มาก ค่า Ljung-Box p-value บนผลตอบแทนดิบที่ไม่สามารถปฏิเสธสมมติฐาน "ไม่มี autocorrelation" ได้ และ p-value บนผลตอบแทนยกกำลังสองที่เกือบเป็นศูนย์ ความแตกต่างข้อสุดท้ายนั้นคือทั้งหมดของเกมนี้ ไม่มีอะไรให้เทรดในเครื่องหมายของผลตอบแทนที่ขอบเขตเวลารายวัน แต่มีโครงสร้างมากมายอยู่ใน variance ของมัน และโครงสร้างนั้นพยากรณ์ได้
หมายเหตุเกี่ยวกับธรรมชาติที่เปิด 24/7 ของคริปโต ต่างจากหุ้น ตรงที่ไม่มี overnight gap และไม่มีการปิดตลาดสุดสัปดาห์ ดังนั้น "วัน" จึงเป็นแท่งเทียน 24 ชั่วโมงที่สะอาด และตัวคูณ annualization คือ ไม่ใช่ การเกาะกลุ่มของความผันผวนยังคงอยู่ที่สเกลระหว่างวันด้วย ซึ่งสำคัญถ้าคุณรัน GARCH บนแท่งรายชั่วโมง การพลิกของ funding-rate และการต่อเนื่องของ liquidation cascade อัดฉีดการปะทุของ variance ที่คมชัดและเกาะกลุ่ม ซึ่งโมเดลรายวันเกลี่ยให้เรียบไป
จาก ARCH สู่ GARCH
ตอนนี้ปัญหาถูกตั้งไว้อย่างคมชัด นั่นคือสร้างโมเดล variance ที่ไม่คงที่แต่ขึ้นอยู่กับอดีตอันใกล้ โมเดลแรกที่ทำสิ่งนี้ได้อย่างถูกต้องคือ ARCH ของ Engle (Autoregressive Conditional Heteroskedasticity, 1982) ซึ่งทำให้เขาได้รับรางวัลโนเบลในปี 2003
เขียนผลตอบแทนเป็นค่าเฉลี่ยแบบมีเงื่อนไขบวกกับ shock ได้ดังนี้
ในที่นี้ คือ conditional variance นั่นคือ variance ของ เมื่อกำหนดทุกสิ่งที่รู้จนถึงเวลา และ คือ innovation ที่ทำให้เป็นมาตรฐานแล้ว (เป็น standard normal ในกรณีที่ง่ายที่สุด) คำว่า "conditional" คือหัวใจของทั้งหมด ในแบบไม่มีเงื่อนไข variance อาจคงที่ แต่เมื่อมีเงื่อนไขอิงกับเมื่อวาน มันขยับ
ARCH() ของ Engle ทำให้ variance ของวันนี้เป็นผลรวมถ่วงน้ำหนักของ shock ยกกำลังสอง ตัวล่าสุด
โดยมี และ เพื่อให้ variance เป็นบวก สิ่งนี้จับการเกาะกลุ่มได้โดยตรง shock ใหญ่ ดัน ให้สูงขึ้น ซึ่งเพิ่มโอกาสของ shock ใหญ่อีกลูก ซึ่งทำให้ variance ยังคงสูงต่อไป ปัญหาคือการสลายตัวเชิงประจักษ์ ความคงอยู่ของความผันผวนในตลาดจริงยืดยาวข้าม lag หลายค่า ดังนั้นเพื่อจะ fit มัน โมเดล ARCH จำเป็นต้องใช้ ขนาดใหญ่ มักเป็น 8, 10 หรือมากกว่า และนั่นหมายถึงการประมาณเวกเตอร์ ที่ยาวและไม่เสถียร ซึ่งมีแนวโน้ม overfit
ข้อคิดของ Bollerslev ในปี 1986 คือการเพิ่มเทอมที่ดูดซับความคงอยู่ทั้งหมดนั้นด้วยพารามิเตอร์เพียงตัวเดียว การเรียกซ้ำของ GARCH(1,1) (Generalized ARCH) เป็นดังนี้
สามพารามิเตอร์ สามการตีความที่ชัดเจน
- คือ ฐาน หรือ floor ค่าคงที่ที่ยึดระดับ variance ในระยะยาว variance ไม่เคยสลายลงต่ำกว่าที่ รองรับ
- คือ การตอบสนอง ต่อข่าว บอกว่า variance ตอบสนองต่อ ความประหลาดใจ ของเมื่อวานรุนแรงเพียงใด ค่า ที่มากหมายถึง conditional variance กระตุกและไวต่อ shock
- คือ ความคงอยู่ หรือความจำ บอกว่า variance ของเมื่อวานถูกส่งต่อมายังวันนี้มากแค่ไหน ค่า ที่มากหมายถึงความผันผวนราบเรียบและจางหายช้า ความสงบคงความสงบ พายุคงความเป็นพายุ
ความสง่างามอยู่ที่การเรียกซ้ำ เพราะ เองก็มีเทอม อยู่ในตัว การกระจายย้อนหลังจึงแสดงว่า GARCH(1,1) คือ ARCH() ที่มีน้ำหนักสลายตัวเชิงเรขาคณิต บน shock ยกกำลังสองในอดีต
ดังนั้น เพียงตัวเดียวก็ซื้อความจำของ shock ในอดีตแบบอนันต์ที่ถ่วงน้ำหนักเชิงเอกซ์โพเนนเชียลให้คุณ นี่คือเหตุผลที่ GARCH(1,1) เพียงแค่สามพารามิเตอร์ มักเอาชนะโมเดล ARCH ที่มีสิบพารามิเตอร์ได้เป็นประจำ และเป็นเหตุที่มันกลายเป็นม้างานของการสร้างโมเดลความผันผวนเชิงประยุกต์ อันที่จริงมันเป็นญาติใกล้ชิดของตัวประมาณ variance แบบ EWMA ของ RiskMetrics ซึ่งเป็นกรณีพิเศษที่ , โดยตรึง ไว้ที่ 0.94 GARCH ขยายมันให้ทั่วไปโดยให้ข้อมูลเป็นตัวเลือก , และระดับ mean-reversion ที่แท้จริง
คุณสมบัติ: Stationarity, Long-Run Variance และ Half-Life
การเรียกซ้ำของ GARCH(1,1) มีคุณสมบัติบางอย่างที่คุ้มค่าแก่การอนุมาน เพราะมันคือสิ่งที่ทำให้คุณใช้เหตุผลเกี่ยวกับโมเดลได้ ไม่ใช่แค่ fit มันแบบสุ่มสี่สุ่มห้า
Unconditional (long-run) variance. สมมติว่ากระบวนการเป็น covariance-stationary เพื่อให้ unconditional variance มีอยู่จริงและคงที่ตลอดเวลา นำ expectation ของทั้งสองข้างของการเรียกซ้ำ เนื่องจาก
นี่คือระดับที่ความผันผวนกลับเข้าหา มันมีอยู่จริง และเป็นบวก ก็ต่อเมื่อ
เงื่อนไข Stationarity. อสมการเดียวกันนั้น
คือเงื่อนไข covariance-stationarity สำหรับ GARCH(1,1) ปริมาณ คือ ความคงอยู่ (persistence) ของกระบวนการ variance มันคือสัมประสิทธิ์ AR(1) ที่กำกับว่า shock ของ variance สลายกลับเข้าหา อย่างไร ถ้า unconditional variance จะเป็นอนันต์ (หรือไม่นิยาม) และ shock จะไม่เคยตายสนิท
เราสามารถเห็น mean-reversion ได้อย่างชัดเจน นิยามค่าเบี่ยงเบนของ variance พีชคณิตเล็กน้อยบนการเรียกซ้ำ (แทน ) ให้ผลในรูป expectation ดังนี้
ช่องว่างระหว่าง variance ปัจจุบันกับระดับระยะยาวของมันหดตัวลงด้วยแฟกเตอร์ ในแต่ละก้าว นี่คือการพยากรณ์แบบหลายก้าวที่เราใช้ในภายหลังพอดี
Half-life ของความผันผวน. ใช้เวลานานเท่าไรกว่า shock ของ variance จะสลายลงครึ่งทางกลับสู่ปกติ ตั้ง แล้วแก้สมการ
สำหรับ half-life อยู่ที่ประมาณ 13.5 วัน สำหรับ อยู่ที่ประมาณ 34 วัน สำหรับ อยู่ที่ประมาณ 69 วัน ตัวเลขเดียวนี้มักเข้าใจได้ง่ายกว่าพารามิเตอร์ดิบ มันบอกคุณในหน่วยของแท่งเทียนของคุณว่าความผันผวนติดหนึบแค่ไหน
ปัญหา near-IGARCH ในคริปโต. นี่คือจุดพลิกที่เฉพาะเจาะจงกับคริปโต เมื่อคุณ fit GARCH(1,1) กับผลตอบแทนของ BTC หรือ ETH คุณเกือบจะพบเสมอว่า ใกล้ 1 มาก ค่า 0.98, 0.99 บางครั้ง 0.995 เป็นเรื่องปกติ นี่คือ regime แบบ near-IGARCH (Integrated GARCH) ซึ่งมีผลกระทบจริง
- half-life กลายเป็นมหาศาล (เป็นสัปดาห์ถึงเป็นเดือน) โมเดลจึงมองว่าความผันผวนคงอยู่มากและแทบไม่กลับเข้าค่าเฉลี่ย
- การประมาณค่า กลายเป็นสิ่งที่ไวต่อการเปลี่ยนแปลงอย่างยิ่ง การเปลี่ยน เล็กน้อยจาก 0.99 เป็น 0.995 ทำให้ long-run variance ที่โดยนัยเพิ่มขึ้นเป็นสองเท่า อย่าเชื่อค่าประมาณจุดของ long-run vol ใน regime นี้โดยไม่มีช่วงความเชื่อมั่น
- การพยากรณ์หลายก้าวกลับเข้าค่าเฉลี่ยช้ามากจนกระทั่งสำหรับขอบเขตเวลาที่ใช้ได้จริงต่ำกว่าสองสามสัปดาห์ GARCH ทำตัวเกือบเหมือน random-walk-in-variance (ซึ่งเป็นสิ่งที่ EWMA สมมติ)
การที่ near-integration เป็นของจริงหรือเป็นสิ่งประดิษฐ์จาก structural break (การเปลี่ยนแปลงถาวรในระดับความผันผวนที่โมเดลอ่านว่าเป็นเหตุการณ์คงอยู่ยาวเหตุการณ์เดียว) นั้นเป็นข้อถกเถียงจริง มันเป็นเหตุผลอีกข้อหนึ่งที่ควร refit บนหน้าต่างแบบ rolling แทนที่จะ fit เพียงครั้งเดียวบนประวัติทั้งหมด ประเด็นที่เราจะกลับมาพูดในส่วนหลุมพราง โครงสร้าง regime โดยเฉพาะนั้นจัดการได้ดีกว่าด้วยโมเดลสลับ (switching model) แบบชัดเจน ดู การตรวจจับ regime ด้วย hidden Markov models ซึ่งเสริมกับ GARCH มากกว่าจะเป็นตัวแทน
การประมาณค่าด้วย Maximum Likelihood
พารามิเตอร์ของ GARCH ประมาณค่าด้วย maximum likelihood ตรรกะนั้นตรงไปตรงมา เมื่อกำหนด การเรียกซ้ำจะสร้างเส้นทางเต็มของ conditional variance และภายใต้การแจกแจงที่สมมติสำหรับ innovation เราสามารถเขียนได้ว่าผลตอบแทนที่สังเกตได้มีความน่าจะเป็นเพียงใด จากนั้นเราเลือก ที่ทำให้ likelihood นั้นสูงสุด
สมมติ innovation แบบ Gaussian ดังนั้น ความหนาแน่นแบบมีเงื่อนไขของการสังเกตหนึ่งค่าคือ
เนื่องจากโมเดลถูกเขียนแบบมีเงื่อนไข joint likelihood จึงแยกตัวประกอบเป็นผลคูณของความหนาแน่นแบบ one-step-ahead และ log-likelihood ก็เป็นผลรวมธรรมดา
มีข้อเท็จจริงเชิงโครงสร้างสองอย่างที่ควรสังเกต ข้อแรก ปรากฏทั้งในฐานะบทลงโทษ ( โมเดลถูกลงโทษเมื่ออ้างว่า variance สูง) และในเศษเหลือที่ทำให้เป็นมาตรฐาน ( โมเดลถูกลงโทษเมื่อประหลาดใจ) จุดที่เหมาะสมที่สุดถ่วงดุลทั้งสอง ซึ่งเป็นสิ่งที่ทำให้ variance ติดตามได้ ข้อสอง การเรียกซ้ำต้องการค่าเริ่มต้น ตัวเลือกปกติคือ sample variance ของผลตอบแทน และเมื่อมีการสังเกตหลายพันค่า ค่าเริ่มต้นแทบไม่มีผล
ไม่มีรูปแบบปิด (closed form) สำหรับตัวที่ทำให้สูงสุด เราจึงหาค่าที่เหมาะสมเชิงตัวเลข (arch ใช้วิธี quasi-Newton พร้อม gradient เชิงวิเคราะห์หรือเชิงตัวเลข) พื้นผิว likelihood โดยทั่วไปมีพฤติกรรมดีสำหรับ GARCH(1,1) แต่มีสองสิ่งที่กัดในทางปฏิบัติ นั่นคือข้อจำกัดความเป็นบวก () และพฤติกรรมใกล้ขอบเมื่อ ซึ่งตัวหาค่าที่เหมาะสมอาจคืบคลานอย่างช้าๆ ทั้งสองจัดการให้คุณโดยไลบรารีที่ดี และคุณควรใช้มัน การเขียน GARCH MLE ด้วยมือเป็นแบบฝึกหัดการเรียนรู้ที่ดี แต่เป็นตัวเลือกที่แย่สำหรับการใช้งานจริง
ไลบรารี arch
แพ็กเกจ arch โดย Kevin Sheppard เป็นเครื่องมือมาตรฐานใน Python การ fit ทั้งหมดใช้เพียงสี่บรรทัด
from arch import arch_model
r = ret * 100.0
model = arch_model(r, mean="Constant", vol="Garch", p=1, q=1, dist="normal")
res = model.fit(disp="off")
print(res.summary())
ขอพูดถึงชื่ออาร์กิวเมนต์สักนิด เพราะมันเป็นแหล่งความสับสนที่พบบ่อย ใน arch นั้น p คือจำนวน lagged variance (เทอม หรือลำดับ GARCH) และ q คือจำนวน lagged squared residual (เทอม หรือลำดับ ARCH) ดังนั้น p=1, q=1 จึงเป็น GARCH(1,1) ที่เราอนุมานมา (โน้ตดั้งเดิมของ Bollerslev เขียนเป็น GARCH() โดยให้ เป็นลำดับ ARCH ทั้งสองระบบสัญกรณ์สลับกัน จงเชื่อเอกสารของไลบรารีเอง ไม่ใช่ความจำของคุณ)
เมื่ออ่าน summary ตารางสัมประสิทธิ์จะหน้าตาราวๆ นี้ (ค่าตัวอย่างสำหรับผลตอบแทนรายวันของ BTC ไม่ใช่การทดลองจริง)
Volatility Model
==========================================================
coef std err t P>|t|
----------------------------------------------------------
omega 0.4821 0.201 2.40 0.016
alpha[1] 0.0912 0.021 4.34 0.000
beta[1] 0.8994 0.024 37.5 0.000
==========================================================
วิธีอ่าน
alpha[1] + beta[1]= 0.0912 + 0.8994 = 0.9906 ความคงอยู่ต่ำกว่า 1 นิดเดียว regime แบบ near-IGARCH เป๊ะตามที่เตือนไว้ half-life วันomega= 0.4821 ดังนั้น variance ระยะยาวคือ ในหน่วย percent-squared นั่นคือความผันผวนรายวันระยะยาวที่ หรือราว ต่อปี ซึ่งเป็นตัวเลข BTC ที่สมเหตุสมผล- ทั้ง
alphaและbetaมีนัยสำคัญอย่างเข้มแข็ง การที่alphaเล็กเมื่อเทียบกับbetaเป็นเรื่องปกติ variance ของคริปโตส่วนใหญ่มาจากความคงอยู่ (ความจำ) โดยมีการตอบสนองต่อ shock ใหม่ที่พอประมาณแต่มีจริง
กับดักการสเกล ×100
นี่คือวิธีที่พบบ่อยที่สุดวิธีเดียวที่จะทำให้ได้ผลลัพธ์ไร้สาระออกมาจาก arch มันจึงสมควรมีหัวข้อย่อยของตัวเอง ตัวหาค่าที่เหมาะสมทำงานได้ดีที่สุดเมื่อตัวเลขที่มันเห็นอยู่ในช่วง ถึง ผลตอบแทน log รายวันอยู่ที่ ดังนั้นกำลังสองของมันอยู่ที่ และ ต้องอยู่ราว ซึ่งอยู่ในช่วงที่ gradient เชิงตัวเลขสูญเสียความแม่นยำ และการ fit อาจล้มเหลวในการลู่เข้าอย่างเงียบๆ หรือคืนค่า standard error ที่เป็นขยะ
การแก้คือ fit บนผลตอบแทนที่สเกลด้วย 100 (นั่นคือในหน่วย percent) ตามข้างต้น arch จะแม้กระทั่งส่ง DataScaleWarning ออกมาถ้าคุณลืม ทุกสิ่งที่คุณอ่านออกมาจากโมเดลจึงอยู่ในหน่วย percent หรือ percent-squared และคุณต้อง unscale อย่างสม่ำเสมอ
sigma_pct = np.sqrt(res.forecast(horizon=1).variance.iloc[-1, 0])
sigma_decimal = sigma_pct / 100.0
print(f"1-day-ahead conditional vol: {sigma_decimal:.2%}")
การผสมปริมาณที่สเกลแล้วกับที่ยังไม่สเกล เช่นป้อนความผันผวนแบบ percent เข้าไปในสูตรกำหนดขนาดโพซิชันที่คาดหวังค่าทศนิยม จะให้ข้อผิดพลาดที่ 100 เท่าพอดี ซึ่งพลาดได้ง่ายเพราะโค้ดยังรันได้ปกติ เลือกแบบแผนสักอย่าง (ผมเก็บทุกอย่างเป็นทศนิยมนอกการ fit และสเกลเฉพาะที่ขอบเขตของ arch เท่านั้น) แล้วอย่าข้ามมันเด็ดขาด
การพยากรณ์ Conditional Variance
โมเดลที่ fit แล้วมีประโยชน์ก็ต่อเมื่อมันพยากรณ์ได้ GARCH ให้การพยากรณ์เชิงวิเคราะห์ที่สะอาดที่ขอบเขตเวลาใดก็ได้
ก้าวเดียวข้างหน้า. ที่เวลา (จุดสิ้นสุดของ sample) เรารู้ และ ดังนั้น variance ถัดไปจึงเป็นค่าที่กำหนดได้แน่นอน
ไม่ต้องใช้ expectation ทุกอย่างทางขวามือถูกสังเกตแล้ว
หลายก้าวข้างหน้า. สำหรับ เรายังไม่รู้ shock ที่แทรกอยู่ระหว่างทาง เราจึงนำ conditional expectation โดยใช้ (เพราะ ) การเรียกซ้ำยุบลงเป็น AR(1) อย่างง่ายในตัว variance ที่พยากรณ์
การวนซ้ำสิ่งนี้จากการพยากรณ์ก้าวเดียวให้รูปแบบปิด ซึ่งคือผลลัพธ์ mean-reversion ที่เราอนุมานไว้ก่อนหน้านี้เขียนออกมาอย่างชัดเจน
อ่านสิ่งนี้อย่างระมัดระวัง เพราะมันคือเรขาคณิตของการพยากรณ์ GARCH ทุกครั้ง โครงสร้างเทอม (term structure) ของ variance เริ่มที่ conditional variance ของวันนี้ และสลายตัวเชิงเรขาคณิตเข้าหาระดับระยะยาว ถ้าวันนี้สงบกว่าค่าเฉลี่ย เส้นพยากรณ์จะไต่ขึ้นเข้าหา ถ้าวันนี้เป็นวิกฤต มันจะตกลงเข้าหา ความเร็วของการสลายตัวนั้นถูกกำหนดโดย ทั้งหมด และใน regime near-IGARCH ของคริปโตที่ การสลายตัวช้ามากจนกระทั่งสำหรับขอบเขตเวลาต่ำกว่าสองสามสัปดาห์ การพยากรณ์แทบไม่ขยับออกจากระดับของวันนี้ นี่เป็นสิ่งที่ควรซึมซับไว้ สำหรับช่วงถือครองสั้นๆ การพยากรณ์ GARCH ของคริปโตโดยพื้นฐานคือ "พรุ่งนี้หน้าตาเหมือนวันนี้ เพียงแต่กลับเข้าค่าเฉลี่ยช้ามากๆ"
การรวม (Aggregating) สู่ขอบเขตการถือครอง. เทรดเดอร์แทบไม่สนใจ variance ของวันในอนาคตวันเดียว ถ้าคุณถือโพซิชันเป็นเวลา วัน และผลตอบแทนไม่มี correlation แบบมีเงื่อนไข (stylized fact จากตอนต้น) variance ของผลตอบแทน สะสม วันคือผลรวมของ variance พยากรณ์รายวัน
นี่คือตัวเลขที่คุณกำหนดขนาดโพซิชันโดยเทียบกับมันจริงๆ นั่นคือความผันผวนของ P&L ตลอดช่วงการถือครองของคุณ สังเกตว่ามันไม่ใช่การสเกลแบบ ที่ไร้เดียงสาอย่างเน้นหนัก ซึ่งถูกต้องก็ต่อเมื่อ variance คงที่เท่านั้น เมื่อ variance ของวันนี้อยู่เหนือ การพยากรณ์แบบ mean-reverting ทำให้ vol วันที่แท้จริง ต่ำกว่า กฎรากที่สอง เมื่อวันนี้สงบ มันจะ สูงกว่า การทำสิ่งนี้ให้ถูกต้องคือความแตกต่างระหว่าง stop ที่เคารพ term structure กับ stop ที่ไม่เคารพ
ในโค้ด
H = 10
fc = res.forecast(horizon=H, reindex=False)
var_path_pct2 = fc.variance.iloc[-1].values # [E_T sigma^2_{T+1}, ..., T+H]
var_path = var_path_pct2 / (100.0 ** 2) # back to decimal variance
daily_vol = np.sqrt(var_path)
print("Forecast daily vol path:", np.round(daily_vol * 100, 2), "%")
H_day_var = var_path.sum()
H_day_vol = np.sqrt(H_day_var)
print(f"{H}-day holding-period vol: {H_day_vol:.2%}")
naive = np.sqrt(var_path[0] * H)
print(f"Naive sqrt(H) * sigma_1: {naive:.2%}")
สำหรับขอบเขตที่ยาวกว่านั้น GARCH ยังรองรับการพยากรณ์แบบ simulation (method="simulation") ซึ่งขยายการแจกแจง innovation ไปข้างหน้าและให้ความหนาแน่นของการพยากรณ์เต็มรูปแบบแก่คุณ ไม่ใช่แค่ variance ของมัน มีประโยชน์เมื่อ innovation ไม่เป็น Gaussian ดังที่จะเป็นเมื่อเราขยับไปสู่การแจกแจง Student-t และแบบเบ้ (skewed) ใน Part 2 สำหรับปริมาณที่เป็นเชิงเส้นใน variance ข้างต้น เส้นทางเชิงวิเคราะห์นั้นแม่นยำเป๊ะและไม่มีต้นทุน
การวินิจฉัย (Diagnostics): โมเดลได้ผลจริงหรือไม่?
การ fit โมเดลไม่ใช่สิ่งเดียวกับการตรวจสอบความถูกต้อง ประเด็นทั้งหมดของ GARCH คือการดูดซับ conditional heteroskedasticity หรือการเกาะกลุ่มของความผันผวน เพื่อให้สิ่งที่เหลืออยู่นั้น (ใกล้เคียง) i.i.d. การตรวจสอบที่ถูกต้องจึงคือการดู standardized residuals
แล้วถามว่า การเกาะกลุ่มหายไปแล้วหรือไม่ ถ้าโมเดลจับพลวัตของ variance ได้ ควรมี variance เท่ากับหนึ่ง และที่สำคัญที่สุด กำลังสอง ของมัน ควรไม่แสดง autocorrelation ที่เหลืออยู่ เราจะรันการทดสอบสามอย่าง
1. Ljung-Box บน standardized residuals. ตรวจว่าไม่มี linear autocorrelation เหลืออยู่ในระดับของ (ที่จริงเป็นการทดสอบโมเดลค่าเฉลี่ย ไม่ใช่โมเดล variance) ควรไม่ปฏิเสธ
2. Ljung-Box บน standardized residuals ยกกำลังสอง. นี่คืออันที่สำคัญ ถ้า ยังมี autocorrelation ที่มีนัยสำคัญ แสดงว่าโมเดล variance ล้มเหลวในการกำจัดการเกาะกลุ่ม มีโครงสร้างที่ GARCH(1,1) ไม่ได้จับ และคุณอาจต้องใช้ลำดับที่สูงขึ้น รูปแบบที่ไม่สมมาตร หรือการแจกแจง innovation ที่ต่างออกไป ควรไม่ปฏิเสธ
3. การทดสอบ ARCH-LM (Lagrange-multiplier test ของ Engle). Regress กับ lag ของตัวมันเองแล้วทดสอบนัยสำคัญร่วม โดยพื้นฐานมันคือเวอร์ชันทางการของการทดสอบข้อ 2 และถามตรงๆ ว่า "ยังมีผล ARCH หลงเหลือ หรือไม่?" ผลลัพธ์ที่ไม่มีนัยสำคัญยืนยันว่า conditional heteroskedasticity ถูกสร้างโมเดลจนหมดไปแล้ว
from statsmodels.stats.diagnostic import acorr_ljungbox
from arch.unitroot.cointegration import engle_granger # (unrelated; shown for import clarity)
z = res.std_resid.dropna() # standardized residuals
z2 = z ** 2
lb_z = acorr_ljungbox(z, lags=[10, 20], return_df=True)
lb_z2 = acorr_ljungbox(z2, lags=[10, 20], return_df=True)
print("Ljung-Box on standardized residuals:\n", lb_z, "\n")
print("Ljung-Box on SQUARED standardized residuals:\n", lb_z2, "\n")
lm = res.arch_lm_test(lags=10, standardized=True)
print(lm)
print(f"\nStd-resid excess kurtosis: {stats.kurtosis(z):.2f}")
ผลลัพธ์ที่ดีหน้าตาเป็นอย่างไร ค่า Ljung-Box p-value บน กระโดดจากเกือบศูนย์ (บนผลตอบแทนยกกำลังสองดิบ) ขึ้นมาอยู่เหนือ 0.05 อย่างสบายๆ และการทดสอบ ARCH-LM ไม่ปฏิเสธ นั่นคือหลักฐานของคุณว่าโมเดลทำงานของมันได้บน โมเมนต์ที่สอง
ผลลัพธ์ที่ไม่สมบูรณ์แบบหน้าตาเป็นอย่างไร และเป็นสิ่งที่คุณควรคาดหวังกับ GARCH(1,1) แบบ Gaussian ธรรมดาบนคริปโต ก็คือการทดสอบการเกาะกลุ่มผ่าน แต่ kurtosis ของ standardized residual ยัง สูงอยู่ (เช่น 4-6 แทนที่จะเป็น 0) GARCH กำจัดการเกาะกลุ่มได้ แต่การแจกแจงแบบไม่มีเงื่อนไขที่หางหนาค่าเดียวยังเหลืออยู่ เพราะ innovation แบบ Gaussian ไม่สามารถจำลองหางได้ ความหางหนาที่เหลืออยู่นั้นไม่ใช่บั๊กที่ต้องแก้ที่นี่ มันคือแรงจูงใจสำหรับ Part 2 asymmetric GARCH และ leverage effect ในคริปโต ซึ่ง innovation แบบ Student-t และ skewed-t และเทอมความไม่สมมาตรของ GJR/EGARCH จัดการกับเรื่องนี้พอดี
การประยุกต์ใช้: การกำหนดขนาดและ Stop ที่สเกลตามความผันผวน
ตอนนี้เรามีการพยากรณ์ความผันผวนของพรุ่งนี้ (และของ วันถัดไป) เราจะทำอะไรกับมัน การใช้งานที่ง่ายที่สุดและมีคุณค่าสูงสุดสองอย่างคือการกำหนดขนาดโพซิชันและการวาง stop เราจงใจให้ทั้งสองเรียบง่ายที่นี่ กลยุทธ์ vol-targeting เต็มรูปแบบพร้อมกลไกในทางปฏิบัติทั้งหมดเป็น Part 4
การกำหนดขนาดโพซิชันแบบ volatility-targeted
แนวคิดคือการถือโพซิชันที่ การมีส่วนร่วมของความเสี่ยง คงที่โดยประมาณตลอดเวลา แทนที่จะเป็นโพซิชันที่ มูลค่าตามหน้าตั๋ว (notional) คงที่ ถ้าคุณลงขนาดเงินเท่ากันเสมอ ความเสี่ยงของคุณจะพองโตใน regime ที่ vol สูงและหดตัวในช่วงสงบ ซึ่งตรงข้ามกับสิ่งที่คุณต้องการ volatility targeting พลิกกลับสิ่งนี้ นั่นคือตั้งเป้าไปที่ความผันผวนของ P&L ที่คงที่ แล้วให้การพยากรณ์กำหนดขนาด
สำหรับความผันผวนต่อปีเป้าหมาย (เช่น 20%) และความผันผวนต่อปีที่พยากรณ์ น้ำหนักของโพซิชันคือ
เมื่อ vol ที่พยากรณ์สูง คุณลดขนาดลง เมื่อมันต่ำ คุณเพิ่มขนาดขึ้น นั่นคือกลไกทั้งหมด เพราะ เป็นค่า พยากรณ์ ซึ่งรู้ ณ เวลา ก่อนที่ผลตอบแทนที่ จะเกิดขึ้นจริง จึงไม่มี look-ahead ตราบใดที่คุณมีวินัยเรื่องจังหวะเวลา (เพิ่มเติมในส่วนหลุมพราง)
def vol_target_weight(sigma_forecast_annual, sigma_target_annual=0.20,
w_max=3.0):
"""Volatility-scaled position weight. Inputs/outputs in decimals.
w_max caps leverage so a tiny forecast vol can't demand insane size."""
w = sigma_target_annual / sigma_forecast_annual
return float(np.clip(w, 0.0, w_max))
sigma_1d = np.sqrt(res.forecast(horizon=1).variance.iloc[-1, 0]) / 100.0
sigma_ann = sigma_1d * np.sqrt(365)
w = vol_target_weight(sigma_ann, sigma_target_annual=0.20)
print(f"Forecast annual vol: {sigma_ann:.1%} -> position weight: {w:.2f}x")
นี่เป็นญาติสนิทของกฎการจัดสรรทุนที่เหมาะสม volatility targeting ตอบว่า "ความเสี่ยงควรสเกลตามความผันผวนเท่าใด" ขณะที่ เกณฑ์ Kelly ตอบว่า "ความเสี่ยงควรสเกลตาม ความได้เปรียบ (edge) เท่าใด" และทั้งสองคูณกันในสแต็กการกำหนดขนาดเต็มรูปแบบ ขนาด edge / variance สังเกตว่าเทอม variance ของ Kelly คือการพยากรณ์ GARCH ที่คุณเพิ่งคำนวณมาพอดี ซึ่งเป็นเหตุผลที่โมเดลความผันผวนแบบ live ทำให้การกำหนดขนาดแบบ Kelly คมชัดขึ้นอย่างมีสาระเมื่อเทียบกับการประมาณจากประวัติแบบสถิต ถ้าการประมาณ edge ของคุณเองมีความไม่แน่นอนที่วัดได้ conformal prediction ให้วิธีแบบ distribution-free ในการขยายหรือหดขนาดให้เข้ากัน และมันประกอบเข้ากับ vol targeting ได้อย่างเรียบร้อย
ค่า cap w_max ไม่ใช่สิ่งเลือกได้ ใน regime near-IGARCH ช่วงที่เงียบสงบสามารถดันการพยากรณ์ vol ให้ต่ำลงมาก และ จะเรียกร้อง leverage ที่ดูดีบนกระดาษแต่หายนะเมื่อความสงบแตกสลาย ซึ่งตามหลักการเกาะกลุ่มของความผันผวนแล้ว ในที่สุดมันก็แตก บ่อยครั้งอย่างฉับพลัน การจำกัด leverage คือการยอมรับแบบหยาบแต่ได้ผลว่า การพยากรณ์ของคุณเป็นค่าเฉลี่ยแบบมีเงื่อนไข ไม่ใช่การรับประกัน และผลตอบแทนของการคิดผิดนั้นไม่สมมาตร ความไม่สมมาตรนั้น บัญชีที่ระเบิดไม่สามารถกู้คืนได้ด้วยการชนะแบบสมมาตร คือ ความไม่สมมาตรระหว่างขาดทุนกับกำไร พอดี ซึ่งควรทำให้คุณระมัดระวังอย่างเป็นระบบมากกว่าที่กฎซึ่งอิง variance เพียงอย่างเดียวแนะนำ
Stop ที่สเกลตามความผันผวน
stop แบบเปอร์เซ็นต์คงที่มีโรคเดียวกันกับขนาดโพซิชันคงที่ นั่นคือ stop ที่ 3% ไวราวกับไกปืนในตลาดสงบ และเป็นเศษปัดในตลาดที่รุนแรง มันทำให้คุณหลุดออกจากโพซิชันที่ดีเพราะ noise ธรรมดาระหว่าง regime ที่ vol สูง และคืนกำไรมากเกินไประหว่างช่วงเปลี่ยนผ่าน การแก้คือตั้งระยะ stop เป็นหน่วยของความผันผวนที่พยากรณ์
โดย คือความผันผวนที่พยากรณ์ตลอดขอบเขตการถือครองที่คาดไว้ (ปริมาณที่รวมมาจากส่วนการพยากรณ์) และ เป็นตัวคูณ โดยทั่วไป 1.5 ถึง 3 ที่เลือกให้ stop อยู่นอกความผันผวนปกติแต่อยู่ในการเคลื่อนไหวสวนทางที่แท้จริง
def vol_scaled_stop(entry_price, side, sigma_H, k=2.0):
"""
entry_price : fill price
side : +1 long, -1 short
sigma_H : forecast volatility over the holding horizon (decimal)
k : stop width in vol units
Returns the stop price.
"""
stop_frac = k * sigma_H
return entry_price * (1.0 - side * stop_frac)
var_path = res.forecast(horizon=10, reindex=False).variance.iloc[-1].values / (100.0 ** 2)
sigma_H = np.sqrt(var_path.sum())
entry = float(px.iloc[-1])
stop = vol_scaled_stop(entry, side=+1, sigma_H=sigma_H, k=2.0)
print(f"Entry {entry:,.0f} | 10-day vol {sigma_H:.2%} | 2-sigma stop {stop:,.0f}")
เพราะ ใช้การพยากรณ์ term-structure แบบ mean-reverting แทนตัวเลขจากประวัติแบบราบเรียบ stop จึงขยายกว้างขึ้นโดยอัตโนมัติเมื่อเข้าสู่ regime ที่ปั่นป่วนและกระชับขึ้นเมื่อความผันผวนลดลง term structure ทำหน้าที่ปรับตัวให้คุณ นี่คือการพยากรณ์เดียวกันที่ป้อนทั้งขนาดและ stop ซึ่งเป็นคุณสมบัติที่ดี ใน regime ที่ vol สูงคุณจะถือ น้อยลง พร้อมกับให้โพซิชัน มีพื้นที่มากขึ้น ในเวลาเดียวกัน และผลทั้งสองทบกันเป็นความเสี่ยงส่วนหางที่ต่ำลงอย่างมีสาระ การกำหนดขนาดและ stop เป็นสองภาพฉายของมุมมองความผันผวนเดียว ไม่ใช่ปุ่มปรับสองปุ่มที่แยกจากกัน
นั่นคือระยะที่ไกลที่สุดที่เราพาการประยุกต์ใช้ไปใน Part 1 กลยุทธ์จริงต้องจัดการต้นทุนธุรกรรมจากการปรับสมดุลอย่างต่อเนื่อง จังหวะเวลาที่คำนวณการพยากรณ์เทียบกับตอนวางออร์เดอร์ การควบคุม turnover และเหนือสิ่งอื่นใดคือการประเมินผลนอกกลุ่มตัวอย่างอย่างซื่อตรง ทั้งหมดนั้นคือ Part 4: กลยุทธ์ GARCH แบบ volatility-targeting ที่เราสร้างและทดสอบแบบ walk-forward ทั้งชุด
หลุมพราง
GARCH นั้น fit ง่ายและหลอกตัวเองได้ง่าย รูปแบบความล้มเหลวมักเกิดขึ้นซ้ำเดิม
การสเกลผลตอบแทน. พูดถึงไปแล้วข้างต้น แต่มันคือบั๊กอันดับหนึ่ง จึงคุ้มค่าที่จะย้ำ fit arch บนผลตอบแทน × 100 และ unscale ทุกผลลัพธ์ (variance ด้วย , volatility ด้วย ) ข้อผิดพลาด 100 เท่าแบบเงียบๆ ตรงนี้จะเป็นพิษต่อการคำนวณขนาดและ stop ทั้งหมดที่อยู่ปลายน้ำ
Look-ahead ในการ fit. ตัวสังหารที่แนบเนียน ถ้าคุณ fit โมเดลบนประวัติ ทั้งหมด แล้วคำนวณ "การพยากรณ์" ทับบนประวัติเดียวกันนั้น การพยากรณ์ทุกครั้งได้แอบเห็นอนาคตแล้ว เพราะพารามิเตอร์ถูกประมาณโดยใช้ข้อมูลจากหลังวันที่พยากรณ์ การ fit แบบ in-sample จะดูวิเศษมาก และผลงานจริงจะไม่เหมือนมันเลย การพยากรณ์ที่ backtest ทุกครั้งต้องมาจากโมเดลที่ fit เฉพาะ บนข้อมูลที่มีอยู่ ณ ขณะนั้น refit บนหน้าต่างแบบขยายหรือแบบ rolling พยากรณ์หนึ่งก้าว แล้วเลื่อนไปข้างหน้า นี่คือสิ่งที่ต่อรองไม่ได้ และเป็นหัวข้อทั้งหมดของ walk-forward optimization ช่องว่างระหว่าง GARCH แบบ in-sample กับแบบ walk-forward ที่ถูกต้อง คือช่องว่างระหว่างเดโมกับระบบที่รอดชีวิตจากการปะทะกับตลาดจริง ดูเพิ่มเติมที่ ความสอดคล้องระหว่าง backtest กับ live
จังหวะเวลาของการพยากรณ์. เกี่ยวข้องกันแต่ต่างกัน การพยากรณ์สำหรับวัน ต้องคำนวณจากข้อมูลที่มีอยู่ ณ ราคา ปิด ของวัน (หรือเมื่อใดก็ตามที่แท่งของคุณปิด) และโพซิชันต้องดำเนินการได้ที่ราคาที่คุณได้จริง การคำนวณการพยากรณ์โดยใช้ราคาปิดของวัน แล้ว "เทรด" ที่ราคาเปิดของวัน เป็น look-ahead ที่ทำให้ทุกผลลัพธ์พองเกินจริงอย่างเงียบๆ
การ overfit ลำดับสูง. GARCH(1,1) เกือบจะเพียงพอเสมอ ความยั่วยวนให้ fit GARCH(2,2) หรือ GARCH(3,1) เพราะมันดัน log-likelihood แบบ in-sample ขึ้นเล็กน้อย มักเป็นการ fit noise พารามิเตอร์ที่เพิ่มมาไม่ค่อยปรับปรุงการพยากรณ์นอกกลุ่มตัวอย่างและมักทำให้ตัวหาค่าที่เหมาะสมไม่เสถียรใกล้ขอบ จงเลือกโมเดลที่ประหยัด และถ้าคุณต้องเปรียบเทียบลำดับ จงเปรียบเทียบด้วย forecast loss นอกกลุ่มตัวอย่างบนการแบ่งแบบ walk-forward ไม่ใช่ด้วย AIC แบบ in-sample เมื่อการวินิจฉัย residual ยังแสดงปัญหา การแก้มักเป็น การแจกแจง innovation ที่ดีกว่าหรือ เทอมความไม่สมมาตร (Part 2) ไม่ใช่ลำดับที่สูงขึ้น
Structural break ถูกอ่านเป็นความคงอยู่. ดังที่กล่าวไว้ การเปลี่ยนแปลงถาวรในระดับความผันผวน (regime ตลาดใหม่ การเปลี่ยนแปลง microstructure ของตลาด) สามารถถูก GARCH ดูดซับเป็นความคงอยู่ที่สูงอย่างหลอกๆ ดัน เข้าหา 1 ถ้าการประมาณ long-run vol ของคุณดูไม่เสถียรข้ามหน้าต่าง ให้สงสัยว่าเป็น break แทนที่จะเชื่อค่าประมาณจุดแบบ near-IGARCH การ refit แบบ rolling และเมื่อเหมาะสมก็ใช้ โมเดล regime แบบชัดเจนช่วยป้องกันสิ่งนี้
การปฏิบัติต่อการพยากรณ์ความผันผวนราวกับการพยากรณ์ผลตอบแทน. GARCH พยากรณ์ ขนาด ของการเคลื่อนไหว ไม่ใช่ ทิศทาง ของมัน มันบอกคุณว่าการแกว่งของพรุ่งนี้น่าจะใหญ่แค่ไหน ไม่ใช่ว่าไปทางไหน นี่คือเหตุผลว่าทำไมบ้านตามธรรมชาติของมันคือการจัดการความเสี่ยง การกำหนดขนาด stop VaR แทนที่จะเป็นการสร้างสัญญาณ อย่าสับสนระหว่างการพยากรณ์ variance ที่ดีกับความได้เปรียบ
สิ่งนี้จะดำเนินต่อไปที่ไหน
GARCH(1,1) คือรากฐาน และมันไม่สมบูรณ์โดยเจตนา ซีรีส์นี้ต่อยอดจากมันในสามทิศทาง
- ความไม่สมมาตรและหางหนา ความผันผวนคริปโตจริงตอบสนองต่อการเคลื่อนไหวขาลงมากกว่าขาขึ้น (leverage effect) และ innovation แบบ Gaussian ไม่สามารถจำลองหางได้ GJR-GARCH, EGARCH และ innovation แบบ Student-t / skewed-t คือ Part 2
- ความผันผวนหลายตัวแปร correlation ระหว่างสินทรัพย์คริปโตเองก็เปลี่ยนแปลงตามเวลาและพุ่งขึ้นในช่วงตลาดพัง การสร้างโมเดลเมทริกซ์ covariance ทั้งก้อนแบบไดนามิกคือ Part 3: DCC-GARCH ซึ่งเชื่อมต่อโดยตรงกับ Markowitz mean-variance และ การจัดสรรบนพื้นฐาน CVaR เมื่อ covariance เป็นไดนามิก
- กลยุทธ์เต็มรูปแบบ การกำหนดขนาด stop ต้นทุน turnover และการประเมิน walk-forward อย่างซื่อตรงมารวมกันใน Part 4
และที่ GARCH marginal ป้อนความเสี่ยง ร่วม (joint) โมเดล conditional-variance แบบตัวแปรเดียวที่นี่คือขั้นแรกของ pipeline แบบ GARCH-EVT-copula สำหรับ VaR/CVaR ของพอร์ต เมื่อคุณมี standardized residual จากการ fit GARCH ต่อสินทรัพย์ คุณจะแปลงมันแล้วเชื่อมเข้าด้วยกันด้วย copula marginal คือ GARCH ส่วนการพึ่งพา (dependence) คือ copula การสร้างนั้น รวมถึง tail dependence และการจัดการหางแบบ EVT ถูกกล่าวถึงอย่างลึกซึ้งใน โมเดล copula สำหรับความเสี่ยงร่วมของคริปโต บทความนี้คือเครื่องยนต์ตัวแปรเดียวที่รองรับอยู่ข้างใต้มัน
สรุป
- ผลตอบแทนคริปโตแสดง การเกาะกลุ่มของความผันผวน หางหนา และไม่มี autocorrelation ในผลตอบแทนแต่มี autocorrelation ที่เข้มแข็งในผลตอบแทนยกกำลังสอง เครื่องมือใดที่สมมติว่าความผันผวนคงที่ ไม่ว่าจะ Black-Scholes ด้วย ค่าเดียว VaR แบบสถิต หรือ stop แบบเปอร์เซ็นต์คงที่ ล้วนถูกกำหนดคุณลักษณะผิดพลาดเมื่อเทียบกับข้อเท็จจริงเหล่านี้
- GARCH(1,1), , สร้างโมเดล conditional variance ที่เปลี่ยนแปลงตามเวลาด้วยสามพารามิเตอร์ ได้แก่ ฐาน การตอบสนองต่อ shock และความคงอยู่ มันคือ ARCH() ที่มีความจำสลายตัวเชิงเรขาคณิต ซึ่งเป็นเหตุที่มันเอาชนะ ARCH ลำดับสูงได้
- Stationarity ต้องการ long-run variance คือ ความคงอยู่คือ และ half-life ของความผันผวนคือ คริปโตอยู่ใน regime แบบ near-IGARCH () คงอยู่มาก กลับเข้าค่าเฉลี่ยช้า และมีการประมาณ long-run variance ที่เปราะบาง
- ประมาณค่าด้วย maximum likelihood log-likelihood แบบ Gaussian คือผลรวมของความหนาแน่นก้าวเดียว fit มันด้วย
arch_model(r*100, vol="Garch", p=1, q=1)จำการ สเกล ×100 และ unscale ทุกผลลัพธ์อย่างสม่ำเสมอ - การพยากรณ์กลับเข้าค่าเฉลี่ย เชิงเรขาคณิตเข้าหา long-run variance ที่อัตรา รวม variance พยากรณ์รายวันเพื่อให้ได้ความผันผวนของขอบเขตการถือครอง ไม่ใช่กฎ ที่ไร้เดียงสา
- ตรวจสอบความถูกต้อง ด้วย Ljung-Box บน standardized residual ยกกำลังสองและการทดสอบ ARCH-LM การผ่านเหล่านี้ยืนยันว่าการเกาะกลุ่มถูกสร้างโมเดลจนหมดไป หางหนาที่เหลืออยู่เป็นแรงจูงใจของ Part 2
- นำมันไปใช้ กับการกำหนดขนาดแบบ volatility-targeted ( แบบมี cap) และ stop ที่สเกลตามความผันผวน () การพยากรณ์เดียวขับเคลื่อนทั้งสอง ดังนั้น regime ที่ vol สูงจึงได้ทั้งขนาดที่เล็กลง และ stop ที่กว้างขึ้นในเวลาเดียวกัน
- หลุมพรางที่สำคัญ: การสเกลผลตอบแทน look-ahead ในการ fit (fit เฉพาะบนข้อมูลอดีต ทำ walk-forward เสมอ) จังหวะเวลาของการพยากรณ์ การใช้ลำดับที่มากเกินไป และอย่าเข้าใจผิดว่าการพยากรณ์ variance คือการพยากรณ์ทิศทางเด็ดขาด
References:
- Engle, R. F. (1982). Autoregressive Conditional Heteroscedasticity with Estimates of the Variance of United Kingdom Inflation. Econometrica, 50(4), 987-1007. DOI
- Bollerslev, T. (1986). Generalized Autoregressive Conditional Heteroskedasticity. Journal of Econometrics, 31(3), 307-327. DOI
- Mandelbrot, B. (1963). The Variation of Certain Speculative Prices. The Journal of Business, 36(4), 394-419. DOI
- Nelson, D. B. (1991). Conditional Heteroskedasticity in Asset Returns: A New Approach. Econometrica, 59(2), 347-370. DOI
- Katsiampa, P. (2017). Volatility estimation for Bitcoin: A comparison of GARCH models. Economics Letters, 158, 3-6. DOI
- Chu, J., Chan, S., Nadarajah, S., & Osterrieder, J. (2017). GARCH Modelling of Cryptocurrencies. Journal of Risk and Financial Management, 10(4), 17. DOI
- Sheppard, K. (2023). arch: Autoregressive Conditional Heteroskedasticity (ARCH) and other tools for financial econometrics in Python. GitHub.
MarketMaker.cc Team
การวิจัยและกลยุทธ์เชิงปริมาณ