9  ข้อมูลอนุกรมเวลา (time series data)

เป็นชุดข้อมูลที่เกี่ยวข้องกับเวลาหรือการเรียงลำดับตามช่วงเวลาที่กำหนดไว้เป็นลำดับแน่นอนไม่สามารถสลับตำแหน่งได้ เช่น ปริมาณการขายรถยนต์รายเดือนในหนึ่งปี, ราคาหุ้นรายวัน ราคาสินทรัพย์ดิจิทัลรายนาที, ปริมาณฝุ่น PM2.5 รายชั่วโมงในพื้นที่จังหวัดเชียงใหม่ เป็นต้น เนื้อหาในบทจะกล่าวถึง การจัดการอนุกรมเวลาที่เป็นอนุกรมเวลาทางการเงินที่ได้รับข้อมูลมาจากฐานข้อมูลด้วยชุดคำสั่ง quantmod ที่ได้รับความนิยมเป็นอย่างมาก โดยผู้อ่านจะต้องทำการเชื่อมอินเตอร์เน๊ตด้วย เพื่อให้สามารถดึงราคาจากฐานข้อมูลได้

9.1 ทำไมต้องใช้ quantmod

quantmod เป็นแพคเกจในภาษาอาร์ที่ช่วยในการวิเคราะห์และจัดการข้อมูลทางการเงินที่เป็นอนุกรมเวลา (time series data) โดยเฉพาะ ซึ่งมีจุดเด่นหลายอย่างดังนี้:

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

การวิเคราะห์ทางเทคนิค: quantmod มีฟังก์ชันที่ช่วยในการวิเคราะห์ทางเทคนิค(technical analysis) และจัดการข้อมูลอนุกรมเวลา ผู้ใช้สามารถสร้างกราฟและดูสัญญาณ (signal) ของข้อมูลได้ โดยมีการสร้างกราฟเบื้องต้นพร้อมกับฟังก์ชันเสริมสำหรับการวิเคราะห์ทางเทคนิค เช่น ค่าเฉลี่ยเคลื่อนที่ (moving averages) และค่าความแปรปรวน (volatility) และกราฟชี้วัดอื่นๆ เช่น RSI

ตัวอย่างกราฟราคาหุ้น PTT

ตัวอย่างกราฟราคาหุ้น PTT

Quantitative Financial Modelling Framework (quantmod)

Quantitative Financial Modelling Framework (quantmod)

การลงชุดคำสั่ง quantmod

install.packages("quantmod")

การเรียกใช้งานชุดคำสั่ง

library(quantmod)

9.1.1 การดึงข้อมูลจากจากฐานข้อมูลด้วยคำสั่ง getSybols( )

getSymbols( Symbols = เวคเตอร์ของชื่อหุ้นที่ต้องการ,
                src = แหล่งข้อมูล,
        periodicity = ประเภทข้อมูล (รายวัน รายสัปดาห์ รายเดือน),
               from = "yyyy-mm-dd",  # "ปีค.ศ. -เดือนที่-วันที่"
                 to = "yyyy-mm-dd")  # "ปีค.ศ. -เดือนที่-วันที่"
getSymbols( )

เป็นคำสั่งสำหรับโหลดข้อมูลราคาหุ้นจากฐานข้อมูลในช่วงวันเวลาที่ต้องการ โดยต้องทำการเชื่อมต่ออินเตอร์เน๊ตด้วย

Symbols : เช่น \("\)PTT.BK\("\) \("\)PTT.BK\("\) (สามารถค้นหาได้จาก https://finance.yahoo.com)

src : เช่น \("\)yahoo\("\), \("\)FRED\("\)

periodicity : สามารถเลือก \("\)daily\("\) \("\)weekly\("\) หรือ \("\)monthly\("\)

from : วันเริ่มต้น Year-month-day (2020-11-31)

to : วันสิ้นสุด: Year-month-day (2022-12-31)

วัตถุที่ได้จากคำสั่ง getSymbols( ) เป็นแบบ xts หรือกรอบข้อมูลแบบพิเศษที่มีชื่อของแต่แถวเป็นวันดือนปี

ตัวอย่าง

getSymbols(Symbols = "PTT.BK",
           src = "yahoo",         
           periodicity = "daily",
           from = "2022-12-25",  
           to = "2023-01-07")    
[1] "PTT.BK"

หรือดาวน์โหลดข้อมูลหุ้นมาหลายตัวก็ได้

getSymbols(Symbols = c("PTT.BK","AOT.BK"),
           src = "yahoo",         
           periodicity = "daily",
           from = "2022-06-01",  
           to = "2023-03-31")    
[1] "PTT.BK" "AOT.BK"
ช่วงที่เวลาที่เลือก

สำหรับช่วงเวลาที่เลือก จากคำสั่งภายใน from และ to จากฐานข้อมูลไม่จำเป็นที่ข้อมูลที่ได้ จะเป็นตามวันเวลาที่เลือก เพราะในฐานข้อมูลอาจจะไม่มีข้อมูลในช่วงเวลาของหัวและท้ายที่ต้องการก็ได้

ข้อมูลทางการเงินจาก yahoo finance จะมีตัวแปรภายใน 6 ตัวคือ

colnames(PTT.BK)
[1] "PTT.BK.Open"     "PTT.BK.High"     "PTT.BK.Low"      "PTT.BK.Close"   
[5] "PTT.BK.Volume"   "PTT.BK.Adjusted"
  • ราคาเปิด (Open)

  • ราคาสูงสุด (High)

  • ราคาต่ำสุด (Low)

  • ราคาปิด (Close)

  • ปริมาณการซื้อขาย (Volume)

  • ราคาปิดที่ปรับปรุงแล้ว (Adjusted)

ถ้าไม่จำเป็นไม่ควรเปลี่ยนชื่อตัวแปรภายในวัตถุชนิดนี้จากชุดคำสั่ง quantmod เพราะจะส่งผลต่อการใช้คำสั่งอื่นๆ ที่เกี่ยวข้องกับชุดคำสั่ง quantmod ได้

9.1.2 ชุดคำสั่ง xts

xts (eXtensible Time Series) เป็นชุดคำสั่งที่ใช้ในภาษาอาร์ เพื่อการจัดการและสร้างกราฟสำหรับข้อมูลอนุกรมเวลา (time series data) โดยมีลักษณะที่เน้นการจัดเก็บและการจัดการข้อมูลที่สอดคล้องกับเวลา เพื่อใช้การจัดเก็บข้อมูลในรูปแบบตารางที่มีป้ายกำกับเวลา (timestamped data) ซึ่งช่วยให้ง่ายต่อการทำงานกับข้อมูลอนุกรมเวลา ถ้าดึงข้อมูลจากฐานข้อมูลด้วยชุดคำสั่ง quantmod จะได้วัตถุออกแบบเป็นข้อมูลแบบ xts

library(xts)

9.1.3 การจัดการข้อมูลอนุกรมเวลาแบบ xts

getSymbols(Symbols = c("PTT.BK"),
           src = "yahoo",         
           periodicity = "daily",
           from = "2022-12-25",  
           to = "2023-01-05") 
[1] "PTT.BK"

วัตถุแบบ xts สามารถใช้คำสั่งจากวัตถุแบบกรอบข้อมูล แบบเมตริกซ์ หรือเวคอเตอร์ได้ เช่น

ต้องการดูราคาปิด สามารถใช้คำสั่งแบบกรอบข้อมูล

PTT.BK$PTT.BK.Low
           PTT.BK.Low
2022-12-26      31.50
2022-12-27      32.25
2022-12-28      32.25
2022-12-29      32.50
2022-12-30      32.75
2023-01-03      32.75
2023-01-04      32.00

หรือเมตริกซ์ได้

PTT.BK[, 3]
           PTT.BK.Low
2022-12-26      31.50
2022-12-27      32.25
2022-12-28      32.25
2022-12-29      32.50
2022-12-30      32.75
2023-01-03      32.75
2023-01-04      32.00

ข้อมูลบางเวลา และบางตัวแปร

PTT.BK[2:3, 3:4]
           PTT.BK.Low PTT.BK.Close
2022-12-27      32.25        32.50
2022-12-28      32.25        32.75

การนำบางตัวแปรออกไป

# การเปลียนแปลงข้อมูลในตัวแปรเดิม
PTT.BK <- PTT.BK[, 1:4]
PTT.BK
           PTT.BK.Open PTT.BK.High PTT.BK.Low PTT.BK.Close
2022-12-26       31.50       32.25      31.50        32.25
2022-12-27       32.50       32.75      32.25        32.50
2022-12-28       32.50       32.75      32.25        32.75
2022-12-29       32.75       33.00      32.50        32.75
2022-12-30       33.00       33.50      32.75        33.25
2023-01-03       33.00       33.50      32.75        32.75
2023-01-04       32.50       32.50      32.00        32.00

คุณสมบัติสำคัญของวัตถุข้อมูลแบบ xts คือ การเลือกข้อมูลตามช่วงเวลาของข้อมูลที่ต้องการด้วยคำสั่งที่เข้าใจง่าย

xts.oject["ช่วงเวลาที่ต้อง"] # หน่วยปี หรือ เดือน หรือ วัน
# หรือ
xts.object["วันเดือนปีที่ต้องการเริ่ม/วันเดือนที่ต้องการสุดท้าย"]
หมายเหตุ
  • ถ้าไม่กำหนดวันเดือนปีที่ต้องการเริ่ม จะเป็นเลือกข้อมูลวันแรกของวัตถุ

  • ถ้าไม่กำหนดวันเดือนปีที่ต้องการสุดท้าย จะเป็นเลือกข้อมูลวันสุดท้ายของวัตถุ

เลือกข้อมูลรายปี

PTT.BK["2023"]
           PTT.BK.Open PTT.BK.High PTT.BK.Low PTT.BK.Close
2023-01-03        33.0        33.5      32.75        32.75
2023-01-04        32.5        32.5      32.00        32.00

เลือกข้อมูลรายเดือน

PTT.BK["2022-12"]
           PTT.BK.Open PTT.BK.High PTT.BK.Low PTT.BK.Close
2022-12-26       31.50       32.25      31.50        32.25
2022-12-27       32.50       32.75      32.25        32.50
2022-12-28       32.50       32.75      32.25        32.75
2022-12-29       32.75       33.00      32.50        32.75
2022-12-30       33.00       33.50      32.75        33.25

เลือกข้อมูลรายวัน

PTT.BK["2022-12-28"]
           PTT.BK.Open PTT.BK.High PTT.BK.Low PTT.BK.Close
2022-12-28        32.5       32.75      32.25        32.75

การเลือกข้อมูลจากปีเดือนที่กำหนด จนถึงปีเดือนที่กำหนด

PTT.BK["2022-12/2023-01"]
           PTT.BK.Open PTT.BK.High PTT.BK.Low PTT.BK.Close
2022-12-26       31.50       32.25      31.50        32.25
2022-12-27       32.50       32.75      32.25        32.50
2022-12-28       32.50       32.75      32.25        32.75
2022-12-29       32.75       33.00      32.50        32.75
2022-12-30       33.00       33.50      32.75        33.25
2023-01-03       33.00       33.50      32.75        32.75
2023-01-04       32.50       32.50      32.00        32.00

ตัวอย่างการเลือกข้อมูลจากวันแรกที่มี จนถึงวันที่กำหนด

PTT.BK["/2023-01-03"]
           PTT.BK.Open PTT.BK.High PTT.BK.Low PTT.BK.Close
2022-12-26       31.50       32.25      31.50        32.25
2022-12-27       32.50       32.75      32.25        32.50
2022-12-28       32.50       32.75      32.25        32.75
2022-12-29       32.75       33.00      32.50        32.75
2022-12-30       33.00       33.50      32.75        33.25
2023-01-03       33.00       33.50      32.75        32.75

ตัวอย่างการเลือกจากวันที่กำหนดจนถึงข้อมูลตัวสุดท้าย

PTT.BK["2023-12-27/"]
     PTT.BK.Open PTT.BK.High PTT.BK.Low PTT.BK.Close

9.1.4 คำสั่ง first( )

คือคำสั่งในการเลือกข้อมูล “n หน่วย” แรก

โดยที่ n เลือกเลขจำนวนเต็มบวกตั้งแต่ 1, 2, 3, …

หน่วย คือ day week month quarter หรือ year

first(PTT.BK, "2 day")
           PTT.BK.Open PTT.BK.High PTT.BK.Low PTT.BK.Close
2022-12-26        31.5       32.25      31.50        32.25
2022-12-27        32.5       32.75      32.25        32.50
first(PTT.BK, "1 week")
           PTT.BK.Open PTT.BK.High PTT.BK.Low PTT.BK.Close
2022-12-26       31.50       32.25      31.50        32.25
2022-12-27       32.50       32.75      32.25        32.50
2022-12-28       32.50       32.75      32.25        32.75
2022-12-29       32.75       33.00      32.50        32.75
2022-12-30       33.00       33.50      32.75        33.25

9.1.5 คำสั่ง last( )

คือคำสั่งในการเลือกข้อมูล “n หน่วย” สุดท้าย

โดยที่ n เลือกเลขจำนวนเต็มบวกตั้งแต่ 1, 2, 3, …

หน่วย คือ day week month quarter หรือ year

# select the last week
last(PTT.BK, "3 day")
           PTT.BK.Open PTT.BK.High PTT.BK.Low PTT.BK.Close
2022-12-30        33.0        33.5      32.75        33.25
2023-01-03        33.0        33.5      32.75        32.75
2023-01-04        32.5        32.5      32.00        32.00
# select the last 2 weeks
last(PTT.BK, "1 week")
           PTT.BK.Open PTT.BK.High PTT.BK.Low PTT.BK.Close
2023-01-03        33.0        33.5      32.75        32.75
2023-01-04        32.5        32.5      32.00        32.00

9.1.6 คำสั่งการเรียกข้อมูลจากรายวัน เป็นรายสัปดาห์ รายเดือน รายสามเดือน หรือรายปี

ก็คือ to.weekly( ) to.monthly( ) to.quarterly( ) to.yearly( )

รายวันเป็นรายสัปดาห์

to.weekly(PTT.BK)
           PTT.BK.Open PTT.BK.High PTT.BK.Low PTT.BK.Close
2022-12-30        31.5        33.5       31.5        33.25
2023-01-04        33.0        33.5       32.0        32.00

รายวันเป็นรายเดือน

to.monthly(PTT.BK)
         PTT.BK.Open PTT.BK.High PTT.BK.Low PTT.BK.Close
Dec 2022        31.5        33.5       31.5        33.25
Jan 2023        33.0        33.5       32.0        32.00

นอกจากนี้ ยังใช้คำสั่งเดียวกัน

  • เปลี่ยนรายสัปดาห์เป็นรายเดือน หรือรายสามเดือน หรือรายปี

  • เปลี่ยนรายเดือนเป็นรายสามเดือน หรือรายปี

  • เปลี่ยนรายสามเดือนเป็นรายปีได้

คำสั่งเพิ่มเติมจากชุดคำสั่ง xts จากศึกษาได้จาก คู่มือ Ryan & Ulrich (2023b)

ถ้าต้องการเลือกช่วงเวลาสนใจ ก็สามารถต่อท้ายคำสั่งเรียนรู้มาก่อนหน้าได้ทันที เช่น

to.monthly(PTT.BK)["2023-01"]
         PTT.BK.Open PTT.BK.High PTT.BK.Low PTT.BK.Close
Jan 2023          33        33.5         32           32

9.2 การสร้างกราฟจากข้อมูลอนุกรมเวลาแบบ xts

ข้อมูลอนุกรมเวลา สามารถใช้สร้างกราฟได้หลากหลายประเภท เช่นกราฟเส้น กราฟแท่ง หรือกราฟสำหรับการวิเคราะห์ทางเทคนิค เช่นกราฟแท่งเทียน การวิเคราะห์แนวโน้ม ระยะสั้น กลาง และยาว ด้วย SMA (Simple Moving Average) เป็นต้น

9.2.1 กราฟเส้น (line chart)

ดึงข้อมูลที่ต้องการเพื่อสร้างกราฟ

# ดึงข้อมูล PTT.BK รายวันจากช่วงเวลาที่กำหนด
getSymbols(Symbols = c("PTT.BK","AOT.BK"),
           src = "yahoo",         
           periodicity = "daily",
           from = "2022-06-01",  
           to = "2023-03-31")    

แล้วใช้คำสั่ง plot( ) วาดกราฟทีละเส้นในวัตถุข้อมูลแบบ xts เช่นต้องการสร้างกราฟเส้นของราคาปิดรายวันด้วยเส้นสีแดงพร้อมใส่ชื่อกราฟที่ต้องการ

plot(x = AOT.BK$AOT.BK.Close, 
         col = "red", 
         main = "The daily closing price of AOT")

  • x คือตัวแปรภายในวัตถุ xts

  • col คือการเลือกกำหนดสีที่ต้องการ

  • main คือชื่อกราฟที่ต้องการ

ถ้าพิจารณา เลือกกำหนดช่วงเวลาที่ต้องการ สามารถใช้คำสั่ง subset และใช้วิธีการเลือกช่วงเวลาของวัตถุแบบ xts ได้โดยไม่ต้องใช้เครื่องหมาย [ ] เช่น

plot(x = AOT.BK$AOT.BK.Close, 
         col = "red", 
         main = "The daily closing price of AOT",
       subset = "2022-10/2023-02")

ถ้าวาดกราฟหลายเส้นบนกราฟเดียวกันสามารถใช้คำสั่ง plot( ) ตามปกติ และตามด้วยคำสั่ง lines( ) สำหรับข้อมูลที่ 2 (lines( ) สำหรับข้อมูลชุดที่ 3, 4, … ถ้ามี) และใช้คำสั่ง addLegend( ) สำหรับการสร้าง legend ขึ้นมา

# กราฟราคาปิดของ AOT
plot(x = AOT.BK$AOT.BK.Close, 
         col = "red", 
         main = "The daily closing price of AOT and PTT")
# กราฟราคาปิดของ PTT
lines(x = PTT.BK$PTT.BK.Close, 
         col = "blue")
# เพิ่ม legend เพื่อบอกว่ากราฟเส้นสีน้ำแดงและสีนำเป็นหุ้นใด
addLegend( legend.loc = "topright", 
           legend.names = c("AOT", "PTT"),
                   col = c("red", "blue"),
                   lty = c(1,1))

สำหรับคำสั่งภายใน legend.loc สามารถเลือกใช้ค่าได้ดังนี้ \("\)bottomright\("\) \("\)bottom\("\) \("\)bottomleft\("\) \("\)left\("\) \("\)topleft\("\) \("\)top\("\) \("\)topright\("\) \("\)right\("\) หรือ \("\)center\("\)

9.2.2 กราฟแท่ง (bar plot)

ทำได้โดยการเพิ่มคำสั่งภายใน คือ type = \("\)h\("\)

plot(x = PTT.BK$PTT.BK.Close, 
         col = "red", 
         main = "The daily closing price od PTT",
         type = "h")

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

9.2.3 กราฟเส้นแบบมีพื้นที่ใต้เส้น (Area under the curve)

จากข้อมูล จำเป็นจะกำหนดสร้างขอบเขตสูงสุด (upper) และขอบเขตต่ำสุด (lower) ก่อน โดยขอบเขตสูงสุดก็คือ ราคาบนกราฟเส้นทุกตัว และขอบเขตต่ำสุดก็คือราคาที่ต่ำที่สุดในกราฟเส้นนั้นเอง

# สร้างตัวแปรชื่อ shade โดยกำหนดให้เป็น xts ของราคาปิด
shade <- PTT.BK$PTT.BK.Close
# สร้างตัวแปร lower เพื่อกำหนดค่าต่ำสุด
shade$lower <- min(PTT.BK$PTT.BK.Close)
# เปลี่ยนชื่อตัวแปรภายในตัวแปรเป็น upper
names(shade)[1] <- "upper"

ใช้คำสั่งจาก plot( ) และตามด้วยคำสั่ง addPolygon( ) ดังนี้

plot(x = PTT.BK$PTT.BK.Close, 
         col = "red", 
         main = "The daily closing price od PTT")
addPolygon(shade ,col = "pink",on = -1)

หมายเหตุ ผู้อ่านไม่จำเป็นต้องใช้ตัวแปรชื่อว่า shade ตามผู้เขียน

ถ้าต้องการให้เป็นสีโปรงแสง อย่าลืมใช้คำสั่ง transparent( ) จากชุดคำสั่ง yarrr

plot(x = PTT.BK$PTT.BK.Close, 
         col = "red", 
         main = "The daily closing price od PTT")
addPolygon(shade ,
           col = yarrr::transparent(orig.col = "pink",trans.val = 0.5),
           on = -1)

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

# สร้างตัวแปรชื่อ shade โดยกำหนดให้เป็น xts ของราคาปิด
shade <- PTT.BK$PTT.BK.Close
# สร้างตัวแปร lower เพื่อกำหนดค่าต่ำสุด
shade$lower <- min(PTT.BK$PTT.BK.Close)
# เปลี่ยนชื่อตัวแปรภายในตัวแปรเป็น upper
names(shade)[1] <- "upper"
# กำหนดตัวแปร upper เป็นค่าคงที่ ด้วยค่าสูงสุด
shade$upper <- max(PTT.BK$PTT.BK.Close)

เช่นถ้าสนใจ ช่วงเวลา Nov 2022 - Jan 2023 จะได้

plot(x = PTT.BK$PTT.BK.Close, 
         col = "red", 
         main = "The daily closing price od PTT")
addPolygon(shade["2022-11/2023-01"] ,
           col = yarrr::transparent(orig.col = "pink",trans.val = 0.5),
           on = -1)

เมื่อผู้อ่าน ทำตามมาได้ถึงจุดนี้แล้ว ผู้เขียนแนะนำให้ศึกษาเพิ่มเติมด้วยตนเองในการเพิ่มข้อความลงไปบนกราฟ หรือเพิ่มเส้นตรงที่ต้องการเข้าไป

9.2.4 กราฟวิเคราะห์ทางเทคนิค

กราฟแท่งเทียนใช้คำสั่ง chartSeries( )

chartSeries(PTT.BK) 

หมายเหตุ

ห้ามเปลี่ยนแปลงชื่อตัวแปรของข้อมูล xts ที่ได้จาก quantmod เช่น

colnames(PTT.BK)
[1] "PTT.BK.Open"     "PTT.BK.High"     "PTT.BK.Low"      "PTT.BK.Close"   
[5] "PTT.BK.Volume"   "PTT.BK.Adjusted"

ห้ามเปลี่ยนชื่อ

เปลี่ยนพื้นหลังเป็นสีขาว เพิ่มคำสั่ง theme = chartTheme(\("\)white\("\))

chartSeries(PTT.BK, theme = chartTheme("white")) 

มีให้เลือก 2 สีเท่านั้น

9.2.5 ตัวชีวัดทางเทคนิค

สามารถเลือกกราฟทางเทคนิคที่ต้องได้ดังนี้

Function Indicator
addADX( ) เพิ่ม Directional Movement Index
addBBands( ) เพิ่ม Bollinger Bands to Chart
addCCI( ) เพิ่ม Commodity Channel Index
addExpiry( ) เพิ่ม Contract Expiration Bars to Chart
addSMA( )
addEMA( )
addWMA( ) เพิ่ม Moving Average to Chart ( )
addEVWMA( )
addZLEMA( )
addMACD( ) เพิ่ม Moving Average Convergence Divergence
to Chart
addROC( ) เพิ่ม Rate of Change to Chart
addRSI( ) เพิ่ม Relative Strength Index to Chart
addSAR( ) เพิ่ม Parabolic Stop and Reversal to Chart
addSMI( ) เพิ่ม Stochastic Momentum Indicator to Chart

ตัวอย่าง

chartSeries(PTT.BK, theme = chartTheme("white"), TA = NULL)
addSMA(7, col = "red") # แนวโน้มระยะสั้น
addSMA(30, col = "blue") # แนวโน้มระยะกลาง
addSMA(99, col = "green") # แนวโน้มระยะยาว

9.2.6 การวาดกราฟของกลุ่มย่อยใน xts

ก็คือใช้คำสั่ง subset โดยวิธีการเลือกกลุ่มย่อยก็สามารถทำได้ตามหัวข้อที่ผ่านมา

plot(PTT.BK$PTT.BK.Close, 
         col = "red", 
         main = "PTT daily closing price", 
         subset = "2023")

plot(PTT.BK$PTT.BK.Close, 
         col = "red", 
         main = "PTT daily closing price", 
         subset= "2022-10-01/2023-02-28")

chartSeries(PTT.BK, theme = chartTheme("white"), 
            TA = NULL, subset ="2023")
addSMA(7, col = "red") # short trend
addSMA(30, col= "blue") # median trend
addSMA(99, col = "green") # long trend

9.2.7 คำสั่งที่น่าสนใจจาก quantmod

ถ้า x คือข้อมูล xts ที่ได้จาก quantmod

Op(x) # ราคาเปิด
Hi(x) # ราคาสูงสุด
Lo(x) # ราคาต่ำสุด
Cl(x) # ราคาปิด
Vo(x) # ปริมาณการซื้อขาย
Ad(x) # ราคาปิดที่ปรับแล้ว

เช่น ถ้าต้องการราคาปิดของ PTT ไปให้ตัวแปรใหม่ชื่อ PTT.BK.close สามารถใช้คำสั่ง Cl( )

PTT.BK.close <- Cl(PTT.BK)
head(PTT.BK.close)
           PTT.BK.Close
2022-06-01        38.25
2022-06-02        38.00
2022-06-06        38.25
2022-06-07        38.00
2022-06-08        38.00
2022-06-09        37.75

9.3 ปัญหาข้อมูลสูญหาย

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

getSymbols(Symbols = "SCB.BK",
           src = "yahoo",         
           periodicity = "daily",
           from = "2022-04-20",  
           to = "2022-04-30")    
Warning: SCB.BK contains missing values. Some functions will not work if
objects contain missing values in the middle of the series. Consider using
na.omit(), na.approx(), na.fill(), etc to remove or replace them.
[1] "SCB.BK"
SCB.BK[, 1:4]
           SCB.BK.Open SCB.BK.High SCB.BK.Low SCB.BK.Close
2022-04-20        68.0       87.75       66.0         81.5
2022-04-21          NA          NA         NA           NA
2022-04-22          NA          NA         NA           NA
2022-04-25          NA          NA         NA           NA
2022-04-26          NA          NA         NA           NA
2022-04-27       120.0      121.50      113.0        114.0
2022-04-28       112.5      113.50      111.5        112.5
2022-04-29       113.5      115.00      113.0        115.0

จะเห็นได้ว่าข้อมูลวันที่ 21 22 และ 25 และ 26 หายไป แสดงค่า NA

วิธีที่ 1 คือการตัดข้อมูลสูญหายทิ้งไปด้วยคำสั่ง na.omit( )

na.omit(SCB.BK)[, 1:4]
           SCB.BK.Open SCB.BK.High SCB.BK.Low SCB.BK.Close
2022-04-20        68.0       87.75       66.0         81.5
2022-04-27       120.0      121.50      113.0        114.0
2022-04-28       112.5      113.50      111.5        112.5
2022-04-29       113.5      115.00      113.0        115.0

วิธีที่ 2 แทนด้วยค่าก่อนวันที่ข้อมูลสูญหาย

na.locf.default(SCB.BK)[, 1:4]
           SCB.BK.Open SCB.BK.High SCB.BK.Low SCB.BK.Close
2022-04-20        68.0       87.75       66.0         81.5
2022-04-21        68.0       87.75       66.0         81.5
2022-04-22        68.0       87.75       66.0         81.5
2022-04-25        68.0       87.75       66.0         81.5
2022-04-26        68.0       87.75       66.0         81.5
2022-04-27       120.0      121.50      113.0        114.0
2022-04-28       112.5      113.50      111.5        112.5
2022-04-29       113.5      115.00      113.0        115.0

วิธีที่ 3 แทนด้วยค่าหลังวันที่ข้อมูลสูญหาย

na.locf.default(SCB.BK, fromLast = TRUE)[, 1:4]
           SCB.BK.Open SCB.BK.High SCB.BK.Low SCB.BK.Close
2022-04-20        68.0       87.75       66.0         81.5
2022-04-21       120.0      121.50      113.0        114.0
2022-04-22       120.0      121.50      113.0        114.0
2022-04-25       120.0      121.50      113.0        114.0
2022-04-26       120.0      121.50      113.0        114.0
2022-04-27       120.0      121.50      113.0        114.0
2022-04-28       112.5      113.50      111.5        112.5
2022-04-29       113.5      115.00      113.0        115.0
ผลลัพธ์ของคำสั่ง

เนื่องจากผลลัพธ์จากคำสั่งข้างต้นยังคงรักษาประเภทของวัตถุเดิมเอาไว้ ทำให้สามารถใช้คำสั่งที่เกี่ยวข้องกับการแสดงผล คือ [ ] ต่อได้ทันที

สำหรับวิธีอื่นๆ ขอให้ผู้อ่านศึกษาด้วยตนเอง เช่นคำสั่ง

na.aggregate( )
# หรือ
na.approx( )

9.4 การรวมอนุกรมเวลาจาก xts เป็นตารางเดียวกัน

เช่น ถ้าต้องการรวมข้อมูลเฉพาะราคาปิดของ PTT และ AOT

PTT.BK.close <- Cl(PTT.BK)

AOT.BK.close <- Cl(AOT.BK)

สามารถทำได้โดยใช้คำสั่ง merge( )

PTT.AOT.close <-merge(PTT.BK.close, AOT.BK.close)
first(PTT.AOT.close, 7)
           PTT.BK.Close AOT.BK.Close
2022-06-01        38.25        69.50
2022-06-02        38.00        69.25
2022-06-06        38.25        69.50
2022-06-07        38.00        68.50
2022-06-08        38.00        69.00
2022-06-09        37.75        68.50
2022-06-10        37.50        68.75

ถ้าข้อมูล 2 ชุดมีจำนวนวันไม่เท่ากันและอาจจะมีวันที่ไม่ตรงกัน เนื่องจากข้อมูลมาจากคนละตลาด ทำให้มีวันหยุดที่ไม่ตรงกัน เช่น ต้องการต้องการข้อมูลดัชนีตลาดหลักทรัพย์ตอนปิดตลาดของไทย (\("\)^SET.BK\("\)) และตลาดหลักทรัพย์ของมาเลเซีย (\("\)^KLSE\("\))

getSymbols(Symbols = c("^SET.BK","^KLSE"),
           src = "yahoo",         
           periodicity = "daily",
           from = "2022-12-01",  
           to = "2022-12-10") 
[1] "SET.BK" "KLSE"  
SET <- Cl(SET.BK)
SET
           SET.BK.Close
2022-12-01      1648.44
2022-12-02      1641.63
2022-12-06      1632.97
2022-12-07      1622.28
2022-12-08      1620.49
2022-12-09      1623.13
KLSE <- Cl(KLSE)
KLSE
           KLSE.Close
2022-12-01    1491.51
2022-12-02    1481.80
2022-12-05    1471.56
2022-12-06    1471.55
2022-12-07    1466.88
2022-12-08    1465.93
2022-12-09    1477.19

จะเห็นว่าตลาดไทย หยุดวันที่ 5 ธ.ค. ด้วย เมื่อต้องการรวมข้อมูลทั้ง 2 ชุดเข้าด้วยกัน สามารถใช้คำสั่ง merge( ) ได้

merge(SET, KLSE)
           SET.BK.Close KLSE.Close
2022-12-01      1648.44    1491.51
2022-12-02      1641.63    1481.80
2022-12-05           NA    1471.56
2022-12-06      1632.97    1471.55
2022-12-07      1622.28    1466.88
2022-12-08      1620.49    1465.93
2022-12-09      1623.13    1477.19

หลังจากก็สามารถคำสั่งเกี่ยวกับข้อมูลที่ค่า NA ได้ต่อไป

ถ้าทำการสร้างกราฟ ทำได้โดย

getSymbols(Symbols = c("^SET.BK","^KLSE"),
           src = "yahoo",         
           periodicity = "daily",
           from = "2022-01-01",  
           to = "2022-12-31") 
[1] "SET.BK" "KLSE"  
SET <- Cl(SET.BK)
KLSE <- Cl(KLSE)
SET.KLSE <- merge(SET, KLSE)
SET.KLSE <- na.omit(SET.KLSE)

plot(SET.KLSE, col = c("red","blue"), 
              main = "The market in dex of SET and KLSE")

addLegend(legend.loc = "bottomleft", legend.names = c("SET", "KLSE"),
                 col = c("red", "blue"), lwd = 1)

จากกราฟจะสังเกตุได้ว่าทั้งสองตลาดมีเคลื่อนไหวไปในแนวทางเดียวกัน

ในกรณีที่ต้องการจะแยกออกมาเป็น 2 กราฟในภาพเดียวสามารถทำได้ดังนี้

plot(SET.KLSE, col = c("red","blue"), 
              main = "The market in dex of SET and KLSE", 
       multi.panel = TRUE)

กราฟจะใช้ได้ดีในกรณีที่ข้อมูลของแต่ละตัวแปร มีความแตกต่างกันมาก

9.5 การหาอัตราผลตอบแทนตามรายเวลาของข้อมูลแบบ xts

สมมุติเราพิจารณาราคาปิดเป็นหลักในการวิเคราะห์หาผลตอบแทนายวันจากหุ้น PTT.BK สามารถใช้คำสั่ง dailyReturn( )

# นำข้อมูลสูญหายออกไป
PTT.BK <- na.omit(PTT.BK)
# คำนวณอัตราผลตอบแทนรายวัน
PTT.return <-dailyReturn(Cl(PTT.BK))
# แสดงอัตราผลตอบแทนรายวันของ 7 วันแรก
first(PTT.return, 7)
           daily.returns
2022-06-01   0.000000000
2022-06-02  -0.006535948
2022-06-06   0.006578947
2022-06-07  -0.006535948
2022-06-08   0.000000000
2022-06-09  -0.006578947
2022-06-10  -0.006622517

กราฟของอัตราผลตอบแทน

plot(PTT.return, col = "blue")

ถ้าสร้างเป็นกราฟแท่ง

plot(PTT.return, col = "blue", type = "h")

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

plot(PTT.return, 
     col = ifelse(PTT.return$daily.returns>=0, yes = "blue", no = "red"), 
     type = "h")

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

plot(PTT.BK.close, col = "red", main = "PTT daily price")

addSeries(PTT.return, 
     col = ifelse(PTT.return$daily.returns>=0, yes = "blue", no = "red"), 
     type = "h", main ="PTT daily return")

9.6 ฟังก์ชันน่าสนใจสำหรับการวิเคราะห์ทางเศรษฐมิติเบื้องต้น

คำสั่ง diff( ) เป็นแปลงข้อมูลผลต่างของค่าปัจจุบันกับกับค่า ย้อนหลัง ไป n lag

เช่น ผลต่างของข้อมูล 1 วัน

diff.PTT.close <- diff(PTT.BK.close, lag = 1)
first(diff.PTT.close, "5 day")
           PTT.BK.Close
2022-06-01           NA
2022-06-02        -0.25
2022-06-06         0.25
2022-06-07        -0.25
2022-06-08         0.00

9.6.1 คำสั่ง acf( ) และ pacf( )

คำสั่ง acf( ) คือคำสั่งการคำนวณสหสัมพันธ์ (autocorrelation)

acf(PTT.BK.close, plot = FALSE)

Autocorrelations of series 'PTT.BK.close', by lag

    0     1     2     3     4     5     6     7     8     9    10    11    12 
1.000 0.965 0.929 0.890 0.849 0.805 0.758 0.717 0.682 0.645 0.610 0.576 0.553 
   13    14    15    16    17    18    19    20    21    22    23 
0.529 0.506 0.486 0.468 0.456 0.441 0.423 0.402 0.386 0.366 0.349 

ถ้าต้องการ กราฟให้กำหนดค่าเป็น plot = TRUE จะได้

acf(PTT.BK.close, plot = TRUE)

คำสั่ง pacf( ) คือคำสั่งการคำนวณสหสัมพันธ์บางส่วน (partial autocorrelation)

pacf(PTT.BK.close, plot = FALSE)

Partial autocorrelations of series 'PTT.BK.close', by lag

     1      2      3      4      5      6      7      8      9     10     11 
 0.965 -0.040 -0.068 -0.037 -0.058 -0.077  0.057  0.094 -0.079  0.003 -0.002 
    12     13     14     15     16     17     18     19     20     21     22 
 0.124 -0.044 -0.007  0.033  0.002  0.052 -0.035 -0.030 -0.105  0.095 -0.059 
    23 
 0.047 

ถ้าต้องการ กราฟให้กำหนดค่าเป็น plot = TRUE จะได้

pacf(PTT.BK.close, plot = TRUE)

9.6.2 คำสั่ง periodReturn( )

คือการแปลงข้อมูลรายวันเป็นอัตราผลตอบแทน รายวัน รายสัปดาห์ รายเดือน รายสามเดือน และรามปี

# นำค่า NA ออกจากข้อมูล
PTT.BK <- na.omit(PTT.BK)
# เลือกใช้ "daily", "weekly", "monthly", "quarterly", "yearly"
PTT.daily.return <-  periodReturn(PTT.BK, period = "daily") 
first(PTT.daily.return, "5 day")
           daily.returns
2022-06-01   0.006578947
2022-06-02  -0.006535948
2022-06-06   0.006578947
2022-06-07  -0.006535948
2022-06-08   0.000000000

สำหรับคำสั่งอื่นๆ ในชุดคำสั่ง quantmod ผู้สนใจสามารถศึกษาได้จากคู่มือการใช้ Ryan & Ulrich (2023a)

9.7 ชุดคำสั่ง forecast

ชุดคำสั่งสำหรับข้อมูลอนุกรมเวลา ที่สามารถวาดกราฟได้เป็นออกด้วยชุดคำสั่งจาก ggplot2 จากวัตถุแบบ xts รวมถึงมีชุดคำสั่งสำหรับวิเคราะห์อนุกรมเวลาแบบต่างๆ

การติดตั้งชุดคำสั่ง forecast

install.packages("forecast")

การเรียกใช้ชุดคำสั่ง forecast

library(forecast)

9.7.1 คำสั่ง autoplot( )

คือการการวาดกราฟเส้นของวัตถุแบบ xts ออกมาเป็นกราฟของ ggplot2

autoplot(PTT.BK$PTT.BK.Close)

สามารถใช้คำสั่งของ ggplot2 เข้าไปเปลี่ยนแปลงแก้ไขได้กราฟที่สร้างได้

autoplot(PTT.BK$PTT.BK.Close) +
  geom_line(color ="red") +
  labs(x = "Date",
       y = "Closed price",
       title = "Closed price of PTT")

9.7.2 กราฟ acf และ pacf

สำหรับชุดคำสั่ง forecast สามารถวาดกราฟ acf และ pacf จากคำสั่ง ggAcf( ) และ ggPacf( ) ตามลำดับ

ggAcf(PTT.BK$PTT.BK.Close)

ggPacf(PTT.BK$PTT.BK.Close)

ถ้าต้องการเปลี่ยนแปลงองค์ประกอบภายในกราฟ สามารถในคำสั่งจาก ggplot2 เข้ามาแก้ไข เปลี่ยนแปลงกราฟได้ตามต้องการ เช่น การใช้ theme แบบอื่นๆ เป็นต้น

ผู้ที่สนใจศึกษา ชุดคำสั่ง forecast สามารถศึกษาเพิ่มเติมได้จากหนังสือ R. J. Hyndman & Athanasopoulos (2018) เพิ่มเติม และศึกษารายละเอียดของแต่ละคำสั่งได้จาก R. Hyndman et al. (2023) และ R. J. Hyndman & Khandakar (2008)