ปรากฏการณ์ 26 กุมภาพันธ์ 2020 หุ้นไทยตก 72 จุดในวันเดียว!!! ใช้ Value-at-Risk ประเมินกันดีกว่า (แจก code Python)

No photo description available.
ตลาดหุ้น ณ วันที่ 26 ก.พ. 2020

วันที่ 26 ก.พ. 2020 ตลาดหลักทรัพย์แห่งประเทศไทยเกิดอาการ “เทกระจาด” หล่นลงวันเดียว ถึง 72.69 จุดนับเป็น นับเป็นหล่นลงวันเดียวถึง 5.05% นับเป็นความเสี่ยงอย่างหนึ่งที่นักลงทุนต้องแบกรับ แต่โชคดีที่เราที่มีวิธีการประเมินความเสี่ยงในการลงทุนเพื่อวิเคราะห์ความเสี่ยงล่วงหน้าทำให้เราสามารถวางแผนรับมือกับความเสี่ยงนี้ได้อยู่แล้ว คือ การใช้ทฎษี Value at Risk เข้ามาช่วย ดังที่เราได้เคยนำเสนอไปแล้วในบทความสองพาร์ทแรกซึ่งหาอ่านได้ที่

Value at Risk (VaR) Part 1: VaR แต่ละแบบมีข้อดีข้อเสียอย่างไร

Value-at-Risk Part 2: Cornish-Fisher Expansion – Deal with Fat-tailed

ในบทความนี้เราจะนำตัวอย่าง index ตลาดหลักทรัพย์ไทยมาวิเคราะห์ด้วย value at risk ทั้งสองแบบมาวิเคราะห์ให้ดูว่าเราสามารถคาดการณ์ความเสี่ยงในครั้งนี้ล่วงหน้าได้อย่างไร พร้อมทั้งแจกโค้ด python ไปให้เพื่อนๆลองทดลองดูได้อีกด้วย

ก่อนอื่นเราจะอธิบายขั้นตอนคร่าวๆก่อนว่าแต่ละโค้ดแต่ล่ะส่วนที่สำคัญทำงานอย่างไรเพื่ออธิบายหลักการทำงานก่อน จากนั้นเราจะนำโค้ดทั้งหมดมาแจกในตอนท้ายของบทความ

อธิบายส่วนสำคัญของโค้ด Python

เริ่มต้นเราต้อง Import library ที่สำคัญกันก่อนครับ

หลังจากที่ import library แล้วเราก็จะมาถึงส่วนของการโหลดข้อมูล ในที่นี้เราเราจะละไว้ก่อน เนื่องมาจาก ณ วันที่เขียน ข้อมูล set index ที่ดึงจาก yahoo finance แสดงผลแค่ข้อมูลวันล่าสุดวันเดียวไม่สามารถวิเคราะห์ได้ เราจึงใช้วิธีการดึงข้อมูลจาก framework ที่เขียนเอง(ซึ่งไม่ได้ลงไว้ที่นี้) จากนั้นเก็บข้อมูลใส่ ตัวแปล ชื่อ stock ไว้ อย่างไรก็ตามในตอนท้ายของบทความเรามีโค้ดตัวเต็ม (ที่ใช้ yahoo finance กับหุ้นอื่นที่ไม่มีปัญหาข้างต้น ซึ่งไม่แน่ว่าวันที่ลงบทความปัญหานี้กับ set index อาจจะไม่มีแล้วก็ได้)

จากนั้นหา return ด้วยการนำราคาที่เราต้องการกันก่อน เช่นต้องการ ราคาปิดก็ต้องไปเรียกหา columns ราคาปิด จากนั้นใช้คำสั่ง .pct_change() เป็นการหาค่าการเปลี่ยนแปลงของสองช่วงเวลา(row) เป็นเปอร์เซ็น(Simple Return)

เขียนโค้ดสมการประเมินความเสี่ยง Value at Risk

Value at Risk: Parametric assumption gaussian

จากบทความแรกการประเมินความเสี่ยงแบบ parametric ที่มีสมมุติฐานเป็น gaussian ที่มีสมการดังนี้

สมการการหา VaR แบบ guassian

จะเห็นว่าในสมการนี้นอกจากค่าทางสถิติพื้นฐานอย่าง mean และ stand deviation แล้ว เรายังต้องการค่า z-score ด้วย โชคดีที่เราสามารถ import ฟังก์ชั่น จาก library scipy.stats มี norm ให้เราเรียกใช้งาน percent point function(ppf) มาเพื่อการหาค่า z-score

norm.ppf คือฟังก์ชั่นเราจะใช้ในการหาค่า z-score ซึ่งความมั่นใจที่ 99% คือเราต้องการหาการแจกแจง z-score ที่ด้านซ้ายของกราฟ ตั้งนั้นเราต้องตั้ง 0.99/100 เพื่อให้ return ค่าของออกมา 0.01 หรือ 1% แรกของการแจกแจง ค่า z-score ที่ได้คือ -2.33 โดยประมาณ พอได้ z-score มาแล้วอีกสอตัวที่เหลือก็เป็นแค่ mean และ standard deviation ของข้อมูล ซึ่งหาได้กับฟังก์ชั่น built-in ของ Pandas ง่ายๆ ก็คือ .mean() และ .std() เท่านั้น

จากนั้นเราก็แค่นำมาประกอบกันตามสมการ

ค่าที่ได้คือ -0.032 หรือตีความได้ว่า มีความมั่นใจที่ 99 %ว่าตลาดหลักทรัพย์ไทยจะไม่ลดลงเกิน 3.21% ใน 1 วัน

นำมาเขียนเป็นฟังก์ชั่นได้ดังนี้

ปล. norm.ppf(1-confidence,mu,sigma) จริงๆให้ผลแบบเดียวกับ .mean() + z-score*s.std() ด้านบนนั่นแหละครับแค่เขียนในอีกรูปแบบหนึง

ผลลัพธ์ที่ได้ คือเราจะมีความมั่นใจที่ 99% ว่าตลาดหลักทรัพย์แห่งประเทศไทยจะไม่ตกเกิน -3.21 % ใน 1 วัน จะเห็นว่าผลลัพธ์ที่ได้ต่างกันมากกับสิ่งที่เกิดขึ้นจริง ณ วันที่ 20 ก.พ. 2020 ที่ผ่านมา(-5.02%) ห่างกัน 2% ดูเหมือนไม่มากแต่สำหรับ index ใน time frame daily นี่ถือว่ามากนะครับซึ่งก็คอมเฟริมปัญหาที่เราได้เขียนไว้ใน Part1 ว่า

โมเดลที่สร้างจากสมมุติฐานนั้นๆ ไม่ว่าจะแจกแจง Gaussian หรือการแจกแจงอื่นๆมักจะไม่สามารถอธิบายการแจกแจงที่แท้จริงของข้อมูลการลงทุนได้(มันเป็น Fat-Tail)

เพราะว่าการแจกแจงจริงๆที่ปลายหางของการแจกแจงสามารถเกิดได้บ่อยกว่าสมมุติฐาน gaussian มากนัก

ตัวอย่าง parametic gaussian ที่เทสความมั่นใจตั้งแต่ 99% – 99.99%

จากรูป ในแกน y จะเป็น % ที่หุ้นจะไม่ลดลงเกินเท่าไหร่ใน 1 วัน ซึ่งผมได้แปลงจาก สเกล 0.0x ขึ้นมาเป็นจำนวนเต็ม เช่น ค่าที่คำนวณได้ -0.0321 ข้างต้นจะถูกแสดงผลเป็น 3.21%(ความจริงแล้ว Value at Risk นิยมแสดงเป็นจำนวนเต็มบวก เมื่อเราเห็นแล้วต้องตีความไปเองว่ามันคือความมั่นใจที่หลักทรัพย์จะไม่ลดลงเกิน xx%) ในแกน x คือค่าความมั่นใจจาก 99% ไปจนถึง 99.99%

จะเห็นว่ากว่าเราจะประเมินไปจนถึงระดับ -5% ขึ้นไปก็ต้องไปถึงความมั่นใจที่ 99.99% แล้วซึ่งแปลว่ามันบอกว่าจะเกิดได้แค่ครั้งเดียวในรอบหลายสิบหรืออาจจะร้อยปีต่อ 1 หน แต่เราดูจากหลักญานสิ่งที่เคยเกิดขึ้นจริงของตลาดหลักทรัพย์ไทยที่เพิ่งกำเนิดมาแค่ 40 กว่าปี จะพบว่าได้มีการเกิดการลดลงใ 1 วันมากกว่า -5% มาแล้วถึง 55 ครั้ง ดังที่แสดงให้เห็นด้านล่าง

เรียงลำดับวันที่ตลาดปิดตัวปรับลดลงใน 1 วันมากกว่า 5%

จะเห็นว่ามันมากกว่าที่ Value at Risk: Parametric assumption gaussian ประเมินไว้ค่อนข้างมากทีเดียวจากที่กล่าวมาข้างต้น เป็นเหตุผลให้เราเขียนบทความที่ 2 ที่มาแก้ไขปัญหาการแจกแจงตรงนี้ Cornish-Fisher Expansion – Deal with Fat-tailed

Value at Risk: Cornish-Fisher Expansion

สมการนี้จริงๆอย่างที่บอกในบทความ Part2 ว่าจริงๆสิ่งที่แตกต่างจากสมการบนแค่วิธีคิด z-score เท่านั้นเองครับ โดยใช้สมการนี้

จะเห็นว่าเรามี parameter ตัวใหม่ขึ้นมา 2 คือ k หรือค่า kurtosis และ s หรือ skewness ในที่นี้เราก็ต้อง import ฟังก์ชั่นมาเพิ่มสำหรับ kurtosis ดังนี้ ส่วน skewness มี built-in ใน pandas อยู่แล้ว

จากนั้นเราก็ทำการคำนวณ parameter ที่ต้องใช้ดังนี้

คำนวณค่า z_hat ตามสมการด้านบนเป๊ะๆ ไม่ได้มีอะไรเป็นพิเศษแค่แปลงจากคณิตศาสตร์เป็นโค้ด

จากนั้นนำ z_hat ไปประกอบกันตามสมการแรก

เราแค่เปลี่ยน z เป็น z_hat เท่านั้นเอง

นำมาเขียนให้เป็นฟังก์ชั่น

จะเห็นว่าผลลัพธ์ที่ได้ แค่ความมั่นใจที่ 99% ก็สามารถโปรเจ็ค ไปถึงการตกของตลาดหลักทรัพย์เมื่อวันที่ 20 ก.พ. 2020 ที่ผ่านมาได้แล้วครับ การใช้ cornish fisher สามารถช่วยเราในการประเมินความเสี่ยงได้ดีทีเดียว ถ้าเราใช้ parametric gaussian เฉยๆ อาจจะทำให้เราประเมินความเสี่ยงสำหรับการลงทุนเราต่ำเกินจริงไปเยอะได้ทีเดียว นี่จึงเป็นเหตุผล(เชิงประจักษ์) ว่าทำไมเราจึงควรใช้ cornish fisher ในการประเมินความเสี่ยงครับ

ตารางเปรียบเทียบ cornish-fisher และ parametric gaussian ตั้งแต่ความมั่นใจที่ 95%-99.5%

จากผลรูปนี้ มันไม่ได้แปลว่า cornish-fisher ไม่ได้ประเมินความเสี่ยงสูงกว่าแบบ parametric gaussian เสมอไป มันขึ้นอยู่กับการแจกแจงของข้อมูลด้วย(อย่างที่บอกใน part2 ถ้าการแจกแจงของข้อมูลเป็น gaussian มันก็จะกลายร่างเป็น gaussian ให้เราครับ)

โค้ดทั้งหมด

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import pandas_datareader as pdr
plt.style.use('seaborn')
%matplotlib inline
from scipy.stats import norm
from scipy.stats import kurtosis

stock = pdr.get_data_yahoo('DTAC.BK')
stock['Rets'] = stock['Close'].pct_change()

def value_at_risk(confidence,df):
    mu = df['Rets'].mean()
    sigma = df['Rets'].std()
    return norm.ppf(1-confidence,mu,sigma)

def cornish_fisher (confidence,df):
    mu = df['Rets'].mean()
    sigma = df['Rets'].std() 
    k = kurtosis(df['Rets'].dropna())
    s = df['Rets'].skew()
    z = norm.ppf(1-confidence)
    z_hat = z + (z**2-1)*s/6 + (z**3-3*z)*(k-3)/24 - (2*z**3-5*z)*(s**2)/36
    return mu + z_hat* sigma

value_at_risk(0.99,stock), cornish_fisher(0.99,stock)

ปล. ที่โค้ดตัวอย่างใช้ DTAC ก็เพราะ ณ วันที่เขียน SET index ของ Yahoo finance แสดงข้อมูลแค่วันล่าสุดเท่านั้น ตัวอย่างที่ใช้ด้านบนเราใช้ library fucntion ดึงข้อมูลจาก siamchart มาแสดงใช้ library ดึงคนละอันกับ ตัวอย่าง DTAC แต่เพื่อความสะดวกในการเอาไปใช้ต่อเลยให้ตัวอย่างแบบนี้ไปเผื่อมีคนอยากเอาไปใช้ประเมินกับสินทรัพย์อื่นๆ

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s