การคำนวณ Rate Return จากราคาหุ้นย้อนหลัง 10 ปีด้วย Python

เมื่อเราจะลงทุนในหุ้น สิ่งหนึ่งที่เราอยากรู้ก็คือ Rate of Return โดยเฉลี่ยใน 1 ปีของหุ้นแต่ละตัวนั้นเป็นอย่างไร ให้ผลตอบแทนเป็นอย่างไร

บทความนี้ผมเลยอยากมาแบ่งปัน การดึงข้อมูลหุ้นที่เราสนใจ จากเว็บไซต์ Yahoo ด้วย Python มา แล้วเอาข้อมูลมาคำนวณ Simple Rate of Return ง่ายๆมาดูกันว่า หุ้นแต่ละตัวเป็นอย่างไร

ก่อนที่จะไปลงลึกเรื่อง coding เราลองมาทำความเข้าใจเรื่อง ความรู้พื้นฐาน Finance ซักเล็กน้อย

ในการลงทุนต่างๆ บนโลกใบนี้ ไม่ว่าจะเป็น หุ้น(Stock) พันธบัตร(Bonds) หรือ หน่วยการลงทุนอื่นๆ ก็มักจะมีอยู่ 2R ที่ต้องบริหาร คือ Risk & Return มาทำความรู้จักกันซักนิดนะครับ

Return ก็คือ กำไรที่เราจะได้รับจากการลงทุน ส่วนใหญ่ก็จะเทียบกันเป็นปีเช่น 6% ต่อปีสำหรับหุ้นบางตัว หรือ 3%ต่อปี สำหรับพันธบัตร ของรัฐบาลเป็นต้น ซึ่งในบทความนี้ จะ Focus ไปที่การทำคำนวณผลตอบแทน แบบ Return of a single Security (หุ้นเดียว) กับ Return a portfolio of security (คำนวณหลายๆ หุ้นพร้อมกัน) เดี๋ยวเราจะไปเจาะกัน

Risk คือ ความเสี่ยงที่จะทำให้ Portfolio ของเรา Loss นั่นเอง ซึ่งในการวัดความเสี่ยงนั้น แล้วเราจะวัดความเสี่ยงจากอะไรหล่ะ? คำตอบคือ วัดจาก Variance กับ Standard Deviation ซึ่งในบทความถัดๆไป ผมก็จะมาแบ่งปันวิธีคำนวณค่า Variance (S^2) กับ Standard Deviation (S) ด้วย Python ด้วยเช่นกัน

กลับมาที่ Return เราจะมาเริ่มต้นที่ Simple Return ซึ่งมีการคำนวณง่ายๆ คือ

    \[     Simple Return = \frac{Price_l-Price_s}{Price_s} \n = \frac{Price_l}{Price_s}-\frac{Price_s}{Price_s} \n                     = \frac{Price_l}{Price_s} - 1$$ \]

โดยที่
Price_l คือ Price Last ราคาสุดท้ายที่ขาย
Price_s คือ Price Start ราคาที่ซื้อ

ซึ่งในการคำนวณราคาหุ้นแต่ละตัวนั้น เราสามารถเข้าไปข้อมูลย้อนหลังได้ที่ เว็บ finance.yahoo.com อย่างตัวอย่างด้านล่างผม ลองดูข้อมูลของหุ้น CPAll

https://finance.yahoo.com/quote/CPALL.BK/history?p=CPALL.BK

ข้อมูลจาก finance.yahoo.com

ซึ่งจะเป็นข้อมูลย้อนหลัง 1 วัน และ ถ้าเราดูดีๆ จะมีราคา Adj Close ให้อีกด้วย ซึ่ง Adj Close พูดง่ายๆ ก็คือ ราคาที่หักค่าใช้จ่าย เช่น การปันผล ให้กับผู้ถือหุ้น เป็นต้น เราจะไม่ใช้ Close เพราะในนั้นยังมีค่าใช้จ่ายซ่อนอยู่ แล้วเดี๋ยวเราจะดึงเอาตัวเลขนี้มาคำนวณกันครับ

โดยหลักการคำนวณคือ เราจะเอา Adj Close ของทุกวันมาลบวันก่อนหน้า แล้วเก็บเพิ่มอีก 1 Column ชือ daily_rate_return หรือพูดง่ายๆก็คือ เทียบราคากันวันต่อวัน ย้อนหลัง 10 ปี .. เด็ดป๊ะละ

หลังจากนั้น เราก็จะเอาข้อมูลทั้งหมดที่เราได้มาหาค่าเฉลี่ย ซึ่งก็จะเป็นตัวเลขเฉลี่ย 10 ปีที่ผ่านมานั่นเอง พอได้ค่าเฉลี่ยเราก็จะเอามา Simple Rate of Return โดยคูณกับจำนวนวันที่เราต้องการ เช่น เราต้องการรู้ว่า หุ้น CPAll นี้ ให้ผลตอบแทนต่อปี ในช่วงระยะเวลา 10 ปีนี้เท่าไหร่ ก็สามารถทำได้ง่ายๆ โดยการเอาค่าเฉลี่ยที่ได้ มาคูณ 250 วัน (ไม่ใช่ 365 วัน เพราะตลาดหุ้นมีหยุดเสาร์อาทิตย์)

เอาละก็ถึงเวลาเขียน Code ซักที โดย Code ทั้งหมดเดี๋ยวผมจะไว้ที่ https://github.com/aoddy/python_for_finance ให้นะครับ

import numpy as np
from pandas_datareader import data as wb
import matplotlib.pyplot as plt

# ดึงข้อมูลจากเว็บ Yahoo #
ST = wb.DataReader('CPALL.BK', data_source='yahoo', start='2007-1-1')

# ตรวจสอบข้อมูลว่า ดึงมาได้ถูกต้อง #
ST.tail()

# คำนวณ daily rate return 
# .shift(1) คือการบอกว่าให้เอาค่าวันก่อนหน้านั้น 1 วัน
ST['daily_rate_return'] = ( ST['Adj Close'] / ST['Adj Close'].shift(1)) - 1

# ตรวจสอบข้อมูลว่า ว่ามี Column 'daily_rate_return เพิ่มมาหรือยัง#
ST.tail()

# ดูกราฟซักหน่อยว่า ข้อมูลที่ได้เป็นยังไง
ST['daily_rate_return'].plot(figsize=(8,5))

# หาค่าเฉลี่ย
avg_returns_d = ST['daily_rate_return'].mean()

# เอาค่าเฉลี่ยมาคูณ 250 วัน คือ จำนวนวันทั้งปี
avg_returns_y = avg_returns_d * 250

มาอธิบายรายบรรทัดทีละบรรทัดกันครับ

import numpy as np
from pandas_datareader import data as wb
import matplotlib.pyplot as plt

เป็นการ import package/module ที่จำเป็นมาใช้ เช่น padas_datareader สำหรับใช้อ่านข้อมูล, numpy สำหรับจัดการข้อมูลขนาดใหญ่ และ matplotlib.pyplot ใช้สำหรับ plot graph

# ดึงข้อมูลจากเว็บ Yahoo #
ST = wb.DataReader('CPALL.BK', data_source='yahoo', start='2007-1-1')

อันนี้จะเป็น ในส่วนของการดึงข้อมูลหุ้นจากเว็บไซต์ yahoo สำหรับเพื่อนๆ คนไหนที่อยากดึงหุ้นตัวอื่น ก็สามารถเอาชื่อหุ้นตัวนั้นมาต่อด้วย .BK เช่น PTT.BK เป็นต้น แล้วก็เลือกว่าจะเริ่มดึงข้อมูลจากวันไหน อย่างตัวอย่างผมต้องการดึงข้อมูลย้อนหลัง 10 ปี ผมก็เลยเริ่มต้นที่ 2010-1-1 ซึ่งจริงๆแล้วเราสามารถกำหนดช่วงเวลาจบของข้อมูลได้ด้วยนะครับ ด้วยการเติม ,end=’2020-1-1′ เข้าไป แบบนี้

# ดึงข้อมูลเป็นช่วงที่เราต้องการ
ST = wb.DataReader('CPALL.BK', data_source='yahoo', start='2007-1-1',end='2020-1-1')

เราก็จะได้ช่วงข้อมูลที่เราต้องการ

# ตรวจสอบข้อมูลว่า ดึงมาได้ถูกต้อง #
ST.tail()

ตรงนี้จะเป็นการตรวจสอบว่าเราดึงข้อมูลจากเว็บ yahoo ได้หรือเปล่า ผลลัพธ์ที่ได้จะเป็นแบบนี้

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

ST['daily_rate_return'] = ( ST['Adj Close'] / ST['Adj Close'].shift(1)) - 1

หลังจากนั้นก็ลอง check ข้อมูลดูอีกครั้งว่ามี Column ที่เราต้องการเพิ่มหรือเปล่า

# ตรวจสอบข้อมูลว่า ว่ามี Column 'daily_rate_return เพิ่มมาหรือยัง#
ST.tail()

ผลลัพธ์ที่ได้ก็จะเป็นแบบนี้

หลังจากนั้นเราก็ลองเอาค่า daily_rate_return มา plot เป็น graph ดูว่าข้อมูลเป็นยังไง

กราฟข้อมูลหุ้น CPAll ย้อนหลังตั้งแต่ปี 2007 จนถึงปัจจุบัน (13 มีนาคม 63)

สังเกต กราฟจะเห็นว่า มีค่าทั้งมากกว่า 0 และ น้อยกว่า 0 แสดงว่า return ในบางวันก็มีค่าเป็นลบ หรือขาดทุน นั่นเอง นั่นเลยเป็นเหตุผลว่าทำไมเราถึงต้องนำ ค่าเฉลี่ย มาใช้ในการคำนวณ

# หาค่าเฉลี่ย #
avg_returns_d = ST['daily_rate_return'].mean()

# เอาค่าเฉลี่ยมาคูณ 250 วัน คือ จำนวนวันทั้งปี
avg_returns_y = avg_returns_d * 250
# ผลลัพธ์ คือ 0.0012917674252375202

# Simple Rate Return ต่อ 1 ปี
print (str(round(avg_returns_y * 100, 5)) + ' %')

พอ Code ด้านบน พอเราได้ ค่าเฉลี่ย avg_returns_d เราก็เอาค่านั้นมาคูณ 250 วัน ก็จะได้ annual rate return หรือ อัตราผลตอบแทนต่อปี ของหุ้น CPAll คือ 32.39449 % ต่อปี

ยังไม่จบ โดยปกติแล้วยังมีวิธีการคำนวณ return อีกแบบหนึ่งที่ชื่อว่า Logarithm Return โดยสูตรการคำนวณคือ

    \[     Logarithm Return = log(\frac{Price_t}{Price_{t-1}}) \]

โดยที่
Price_t คือ Price ณ เวลา t
Price_{t-1} คือ Price ณ เวลา t-1 ** ภาษาบ้านเราก็คือ ราคาก่อนหน้านั่นเอง

ก่อนที่จะไปหาคำตอบว่าเราควรใช้ สูตรไหน ระหว่าง Simple Return กับ Logarithmic Return มาดู Python code ก่อนดีกว่า

import numpy as np
from pandas_datareader import data as wb
import matplotlib.pyplot as plt

# ดึงข้อมูลจากเว็บ Yahoo #
ST = wb.DataReader('CPALL.BK', data_source='yahoo', start='2007-1-1')

# ตรวจสอบข้อมูลว่า ดึงมาได้ถูกต้อง #
ST.tail()

# ใช้สูตรที่เราได้มา
ST['log_return'] = np.log(ST['Adj Close'] / ST['Adj Close'].shift(1))

# ตรวจสอบข้อมูลว่า ดึงมาได้ถูกต้อง #
ST.tail()

# Plot Graph ดู
ST['log_return'].plot(figsize=(8,5))

# หาค่าเฉลี่ย #
log_return_d = ST['log_return'].mean()
log_return_d

# เอาค่าเฉลี่ยมาคูณ 250 วัน คือ จำนวนวันทั้งปี
log_return_a = log_return_d * 250
log_return_a

# Logarithmic Rate Return ต่อ 1 ปี
print (str(round(log_return_a * 100, 5)) + ' %')

สำหรับ Code ด้านบนมีเพียงบรรทัดเดียวที่ต่างจาก Code ชุดแรก คือ

ST['log_return'] = np.log(ST['Adj Close'] / ST['Adj Close'].shift(1))

ซึ่งเป็นการใช้ฟังก์ชั่น logarithm ของ numpy ในการหาค่า และ ผลของ Logarithmic Return คือ 27.80279 % ซึ่งเมื่อเทียบกับ Simple Return แล้วค่า Logarithmic Return จะน้อยกว่าเสมอ

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

กลับมาที่คำถามที่ค้างไว้ ว่าระหว่าง “Simple Return” กับ “Logarithmic Return” เราจะเลือกใช้อันไหน ซึ่งผมก็ลองหาข้อมูลจากหลายๆแหล่ง มีการถกเถียงกันพอสมควร ของคนไทยก็มี ของต่างประเทศก็มี บางมหาลัยมีถึงขั้นวิจัยกันเลยทีเดียว เช่น

ส่วนตัวผมอ่านแล้วก็สรุปด้วยตัวเองได้ว่า

  1. หากต้องการวิเคราะห์หุ้น หรือ ข้อมูลเปรียบเทียบ หุ้นหลายๆตัวพร้อมกัน ใน Time Frame เดียวกัน เช่นในช่วง 2 ปีเดียวกัน ผมจะใช้ Simple Return เพราะ เป้าหมายคือ เปรียบเทียบหุ้นแต่ละตัว
  2. แต่ถ้าหากต้องการวิเคราะห์ เป็นตัวๆ ก็จะใช้ Logarithmic Return แทน เพราะ มีเรื่องเวลามาเกี่ยวข้อง

เป็นอันจบเรื่อง การหา อัตราผลตอบแทน (Rate Return) ในหุ้น ในบทความถัดๆไป ผมก็จะค่อยๆ เพิ่มเนื้อหาไปเรื่อยๆ ไม่ว่า จะเป็น การหาอัตราผลตอบแทนของ portfolio (เพราะจริงๆแล้วเราไม่ได้ลงทุนหุ้นแค่ตัวเดียว แต่ เราจะแบ่งลงทุนในหุ้นแต่ละตัว) รวมไปถึงเรื่องของการคำนวณ Risk

ไม่ได้เขียน Blog นาน บทความนี้เขียนแล้วสะใจมากๆ ได้กลับไปคิด ไปลองความรู้สมัย ม.ปลาย พวก เศษส่วน, Log, ln อีกด้วย

Comments

comments