จัดการข้อมูลอย่าง Quants [Part2: จัดการ Missing Value และ คำนวณ Statistics สำหรับข้อมูลทั้งตลาด]

บทความชุดนี้เราจะมาเอาใจสายลงทุนกัน ด้วยบทความชุด “จัดการข้อมูลอย่าง Quants” ซึ่งจะประกอบไปด้วย 3 บทความด้วยกัน ดังนี้

1.จัดการข้อมูลอย่าง Quants [Part 1: ดึงข้อมูลหุ้น S&P500 ทั้ง 500 ตัว]

2. หลากหลายวิธีกับการจัดการกับ “Missing Value”

3. จัดการข้อมูลอย่าง Quant [Part2: จัดการ Missing Value และ คำนวณ Statistics สำหรับข้อมูลทั้งตลาด

บทความทั้งหมดจะเป็น Tutorial สำหรับผู้ที่สนใจการดึงข้อมูลหุ้นเพื่อการลงทุนแบบไม่เสียค่าใช้จ่าย! อ่านไปด้วย Coding ไปด้วยได้เลยครับ

บทความที่ 3 นี้ นี้เป็นตัวต่อจากบทความที่แล้ว ฉะนั้นเราคาดหวังว่าผู้อ่านจะมีไฟล์ “sp500_data.xlsx” ที่เราทำกันมาในบทความที่ 1 กันแล้วนะครับ ถ้าท่านใดยังไม่มีไฟล์ สามารถอ่านวิธีการจัดการดาวน์โหลดข้อมูล และสร้างไฟล์ได้ที่ บทความที่ 1 “จัดการข้อมูลอย่าง Quants [Part 1: ดึงข้อมูลหุ้น S&P500 ทั้ง 500 ตัว]” ตามลิงก์ด้านบนได้เลยครับ

มาเริ่มกันเลยครับ

import pandas as pd
import warnings
warnings.filterwarnings('ignore')

df = pd.read_excel("sp500_data.xlsx")
df.date = pd.to_datetime(df.date)
df = df.set_index('date')
df

เริ่มด้วยimport library ที่จำเป็นและดึงไฟล์ excel sp500_data.xlsx ทำการแปลง date เป็น datetime และ set ให้มันเป็น index

ตอนนี้เราอยากรู้ว่าหุ้นที่เราดึงมาชุดนี้ มีหุ้นอะไรบ้างซึ่งมันก็มีบอกอยู่แล้วใน Columns

print(df.columns)
tickers = df.columns[::5]
print("\n", tickers)

ปัญหาคือเรามี columns 5 อันต่อ 1 หุ้น เราต้องการแค่ชื่อมันอันละตัว df.columns[::5] เพื่อเลือกเฉพาะ ชื่อหุ้น xxx open มา

tickers = [s.strip(' open') for s in tickers]
tickers

ตัดคำว่า open ออกเพื่อให้ได้แต่ชื่อของหุ้นเพื่อนำไปใช้ในการเรียกชื่อคอลัมเพื่อรำไปคำนวณสถิติ/ตั้งชื่อ columns ต่อ

จัดการกับ Missing Value

จากบทความที่แล้ว เราได้พูดถึงการจัดการ Missing Value

เราได้เรียนรู้วิธีการรับมือกับ missing Values กันไปแล้วมามายหลายรูปแบบ ทั้งแบบง่ายที่สุด dropna ทิ้งไป หรือ เติมข้อมูลที่ว่านั่นด้วยวิธีเติมข้อมูลไปข้างหน้า forward fill และ เติมข้อมูลย้อนหลัง backward fill แน่นอนว่ามี lookahead bias สำหรับรายละเอียดว่าทำไมบางครั้งเราก็สามารถยอมรับ bias ได้นั้นสามารถอ่านได้ในบทความด้านบนครับ มีทั้งวิธีที่ละเอียดกว่านั้นอีกด้วย สำหรับบทความนี้เราจะใช้วิธีง่ายๆก่อน

data = df.copy()
data.fillna(method="ffill", inplace=True) 
data.fillna(method="bfill", inplace=True) 

ขั้นแรกจะเติมข้อมูลด้วยการเติมไปข้างหน้าต่อก่อนครับ จากนั้นค่อยมาเติมถอยหลังการลำดับการเติมแบบนี้ การเติมด้วยวิธีถอยหลังที่จะก่อให้เกิด bias นั้นเกิดได้แค่กรณีเดียว คือ ไม่มีดาต้าตั้งแต่วันแรกของข้อมูล (NA 10 12 15 ก็จะโดนเติมเป็น 10 10 12 15)เพราะถ้าวันแรกมีข้อมูล ก็จะโดนการเติมแบบไปข้างหน้าเติมจนหมดไม่มีทางได้ใช้การเติมถอยหลังได้เลย(10 NA NA 15 16 ก็จะเป็น 10 10 10 15 16 )

คำนวณ สถิติที่ต้องใช้

for inst in instrument:
    data["{} % ret".format(inst)] = data["{} close".format(inst)] / data["{} close".format(inst)].shift(1) - 1
    data["{} % ret vol".format(inst)] = data["{} % ret".format(inst)].rolling(25).std() 
    data["{} active".format(inst)] = data["{} close".format(inst)] != data["{} close".format(inst)].shift(1)

data

เราจะมาสถิติที่ต้องใช้กัน 3 อย่าง

  • คำนวณ return จาก close ของวันนี้และ close ของเมื่อวาน หรือ return รายวันแบบหยาบสำหรับหุ้นทั้งหมด
  • คำนวณ volatility หรือความผันผวนของหุ้นแต่ละตัวจาก return
  • คำนวณแบบหยาบว่าหุ้นนั้นๆยังมีการเทรดกันอยู่หรือไม่ ด้วยการเช็คง่ายๆว่าราคามันมีการเคลื่อนไหวไหม ซึ่งแน่นอนว่าหยาบมาก หุ้นอาจจะมีการเทรดอยู่แต่ราคาปิดวันนี้เท่ากับราคาปิดเมื่อวานย่อมเป็นไปได้ แต่เราจะคำนวณเพื่อมาเปรียบเทียบว่าช่วงไหนที่หุ้นนั้นๆไม่มีเทรดนานๆ คือราคาไม่เปลี่ยนแปลงหลายวันมากๆ เราจะได้มี columns เพื่อเช็คว่ายังควรนำหุ้นที่ว่าไปพิจรณาเทรดหรือไม่
plt.figure(figsize=(15, 10))

for ticker in tickers:
    plt.plot((1+data["{} % ret".format(ticker)]).cumprod(), label=ticker)
    
plt.title("sample of S&P500")    
plt.legend()
plt.show()
plt.figure(figsize=(15, 10))

for ticker in tickers:
    plt.plot(data["{} % vol".format(ticker)], label=ticker)
    
plt.title("sample of S&P500 volatility")    
plt.legend()
plt.show()

เราจะเห็นว่าจากการดู volatility ของหุ้นทำให้เราพอจะเห็นแล้วว่าหุ้นตัวไหนไม่มี active ที่เห็นด้วยตาเปล่า 2 ตัว เพราะไม่มี volatility เพราะเค้าเป็นหุ้นที่ไม่มีข้อมูลในวันแรก(และอีกหลายวันต่อมา) คือพวกที่เข้าตลาดช้ากว่าหุ้นอื่นใน sample ชุดนี้นี่เอง เลยโดนเติมด้วยการเติมย้อนหลัง เมื่อมีค่าเดียวกันหมดมันเลยไม่มี volatility

data.to_excel("sp500_fill.xlsx")

เรียบร้อยแล้วครับ หลังจากนั้นเราก็สามารถจัดการ Save ข้อมูลที่ถูกเติมเต็มเรียบร้อยแล้วเก็บไว้เพื่อใช้งานต่อไป

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

หลังจากที่อ่านบทความชุดนี้ทั้ง 3 บทความกันแล้ว ผมก็หวังเป็นอย่างยิ่งว่าจะเป็นประโยชน์ และช่วยทุกท่านได้ ถ้าในอนาคตจำเป็นต้องรับมือกับเจ้าข้อมูลที่ไม่สมบูรณ์นะครับ ก่อนจบบทความ ผมขอสรุป ลิงก์สำหรับอ่านบทความทั้งหมดไว้อีกรอบด้านล่างนะครับ

LINKS

1.จัดการข้อมูลอย่าง Quants [Part 1: ดึงข้อมูลหุ้น S&P500 ทั้ง 500 ตัว]

2. หลากหลายวิธีกับการจัดการกับ “Missing Value”

3. จัดการข้อมูลอย่าง Quants [Part2: จัดการ Missing Value และ คำนวณ Statistics สำหรับข้อมูลทั้งตลาด]

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 )

Facebook photo

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

Connecting to %s