Stock price prediction by DSEGr.10

DSEsGr.10 Week4

DSEs_G10
botnoi-classroom
4 min readSep 15, 2020

--

Objective: บทความนี้เป็นส่วนหนึ่งของ Data Science Essential ของ Botnoi Classroom หัวข้อ Trend forcasting

photo from : https://www.waterstechnology.com/sites/waterstechnology/files/styles/landscape_750_463/public/2018-11/Trendline-IMD-Analytics.jpg?h=0b9d3c4c&itok=jJh--Zrq ผู้เขียนไม่มีเจตนาละเมิดลิขสิทธิ์

สามารถดู code Colab ของโมเดลการทำนายนี้ได้จาก link: https://colab.research.google.com/drive/1JtjW76_CePUTNsFcpb-tJSngaWXngUF8?authuser=2

ภาพรวมของโปรเจค เป็นการสร้างโมเดลทำนายราคาหุ้นที่คาดว่าจะทำกำไรมากที่สุดในรอบ 7 วัน (ตัวเลข 7 วันที่ถือมาจากโจทย์ที่กำหนดซื้อหุ้นที่ ATO ในวันพฤหัสที่ 17 กันยายน 2563 และต้องการจะขาย ATO ในวันพฤหัสที่ 24 กันยายน 2563) โดยดูจาก feature ข้อมูลการเปลี่ยนแปลงราคาในรอบ 7 วัน ที่สูงที่สุดที่โมเดลทำนายได้ และเลือกหุ้นตัวนั้นเป็นตัวที่เราจะซื้อ(และขาย)เพื่อสร้างกำไรในรอบ 7 วันทำการ ตามที่โจทย์กำหนด โดยข้อมูลที่ใช้ในการ train และ test โมเดลเป็นข้อมูลราคาหุ้นของ SET 100 ในอดีตย้อนหลัง 5 ปีโดยประมาณ ตั้งแต่ช่วงวันที่ 01-01–2016 ถึง 10–09–2020

ขั้นตอนการทำโมเดล prediction เป็นดังนี้
1. Import all necessary packages : เป็นการใส่ดึง library ที่ต้องใช้เข้ามาก่อนได้แก่ pandas_datareader, pandas, matplotlib.pyplot เป็นต้น ซึ่งถ้าไม่ต้องการให้มีข้อความที่รันหลายๆบรรทัดขึ้นมาให้เกะกะสายตาก็สามารถใส่ %%captureไว้บรรทัดบน

2. Get data : เราจะใช้ library pandas_datareader ช่วยในการดึงข้อมูลหุ้นจาก yahoo โดยข้อมูลที่ได้เป็น dataframeได้แก่ Date, High, Low, Open, Close, Volume, และ Adj Close โดยกำหนดให้ดึงข้อมูลระหว่างช่วงวันที่ 01–07–2015 ถึง 10–09–2020 ซึ่งจะเห็นว่าเราดึงข้อมูลก่อนช่วง 01–01–2016 เพราะหลังจากขั้นตอนนี้เราต้องการสร้าง feature ที่เป็น indicator บางตัวให้กับโมเดล เพื่อให้ค่าที่ได้ตรงกับโปรแกรมที่ใช้ในการเทรดหุ้น จึงจำเป็นต้องดึงข้อมูลก่อนหน้า 01–01–2016 มาใช้ หากไม่ทำเช่นนี้ข้อมูล indictor บางส่วนขาดหายไป ทำให้ model มีความคลาดเคลื่อนได้

จากนั้นเราต้องการรายชื่อหุ้นดัชนี set100 ขั้นตอนการดึงข้อมูลเราใช้การ Web Scraping ดึงข้อมูลดัชนี SET100 จากเว็ปไซต์ตลาดหลักทรัพย์แห่งประเทศไทย https://marketdata.set.or.th/mkt/sectorquotation.do?sector=SET100&language=th&country=TH โดยใช้ library BeautifulSoup จากนั้นสร้าง list symbol เพื่อเก็บรายชื่อหุ้นทั้งหมดจากการทำ Web Scraping และนำไปเรียกข้อมูลหุ้นผ่าน pandas-datareader

ดัชนี SET100 จากตลาดหลักทรัพย์แห่งประเทศไทย
dataframe ที่ได้จากการทำ Web Scraping

3. Cleansing & transformation : ส่วนนี้เราจะทำการกำจัดข้อมูลที่คิดว่าไม่ได้ใช้ประโยชน์ออกไปได้แก่ ราคา Adj Close ซึ่งเป็นราคาที่เกิดจาก coperate action เช่น การจ่ายเงินปันผล แตกพาร์ ซึ่งในโปเจคนี้เราไม่สนใจ

dataframe ของตัวอย่างดัชนีหุ้น SCB ที่ดึงมาจาก yahoo
dataframe ข้อมูลย้อนหลังของหุ้น SCB ที่ดึงมาจาก yahoo

4. Feature engineering : เราเริ่มจากการสร้างข้อมูลพื้นฐาน ดังนี้
-value มูลค่าของของดัชนีหุ้นนั้น โดยเอาราคาปิด (close) คูณกับปริมาณ (volume)
-%change ทิศทางของดัชนีหุ้นที่มีการเปลี่ยนแปลงจากวันก่อนหน้า
-7 days %change เป็นทิศทางการเปลี่ยนแปลงของหุ้นในอีก 7 วันทำการถัดไป ซึ่งตัวนี้สำคัญเพราะเราจะใช้ในโมเดลเพื่อทำนายว่าเราจะสร้างกำไรได้เท่าไหร่ในอีก 7 วันทำการ ถัดไปเป็นการหาคุณลักษณะของข้อมูลที่เรามีอยู่ ซึ่งเราจะใช้ตัวนี้เป็น label ของโมเดลในภายหลัง
จากนั้นเรา import library อีกตัวหนึ่งเข้ามาคือ talib ใช้ในการสร้าง indicator หุ้น

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

Indicator แต่ละตัวที่เราเอามาสร้างโดยยกรูปแบบมาจากหนังสือการ trade หุ้น และได้มีการสร้าง feature เพิ่มเติมเพื่อบอกขนาดและทิศทางของ indicator แต่ละตัว

โดยประเภท indicator ที่เราใส่ไปเป็นดังนี้

1. Trend Indicator เป็น feature อื่นๆที่เป็น indicator ของหุ้น ได้แก่
-Exponential Moving Averages (EMA) ดูในช่วงเวลา 5, 10, 20 วันย้อนหลัง
-Moving Average Convergence/Divergence (MACD)

2. Momentum Indicator
-Stochastic Oscillator Slow
-Relative Strength Index (RSI)

3. Volatility Indicator
-Average Directional Movement Index (ADX)
-Average True Range (ATR)

feature ทั้งหมดที่มีคือ 39 ตัว ดังนี้ [‘High’, ‘Low’, ‘Open’, ‘Close’, ‘Volume’, ‘Value’, ‘%Change’, ‘7d %Change’, ‘EMA5’, ‘EMA10’, ‘EMA20’, ‘trend5’, ‘trend10’, ‘trend20’, ‘strength5_10’, ‘strength5_20’, ‘strength10_20’, ‘strengthC_5’, ‘strengthC_10’, ‘strengthC_20’, ‘MACD’, ‘Signal’, ‘Hist’, ‘trendMACD’, ‘trendSignal’, ‘trendHist’, ‘strengthMACD’, ‘slowK’, ‘slowD’, ‘trendK’, ‘trendD’, ‘strengthK_D’, ‘RSI’, ‘trendRSI’, ‘ADX’, ‘trendADX’, ‘strengthADX’, ‘ATR’, ‘trendATR’]

ขั้นตอนต่อไปเราจะทำการลบข้อมูลที่เราเอามาใช้ช่วยในการคิดค่า indicator ช่วงก่อนหน้า 01- 01–2016 ออก เพื่อให้สอดคร้องกับช่วงเวลาที่เรากำหนดไว้

แต่ก็จะเห็นว่ามีหุ้นบางตัวที่เพิ่งเข้ามาในตลาดหลังช่วงวันที่ 01–01–2016 และเราจะทำการเติมข้อมูลตรงส่วนที่ไม่มีนั้นด้วยค่า 0 เพื่อให้สอดคล้องกับโปรแกรมที่ใช้ในการเทรดหุ้น เช่น หุ้น WHAUP เริ่มมีข้อมูลตั้งแต่ปี 2017 เป็นต้น

ทำการ plot กราฟเลียนแบบการแสดงผลโปรแกรมที่ใช้ในการเทรดหุ้น ได้หน้าตาออกมาประมาณนี้ ซึ่งกราฟที่ plot จะมีค่า feature ต่างๆเป็นแกน y และวันที่เป็นแกน x

5. Prediction model : เป็นการจับเอาชุด dataframe ที่เตรียมไว้มาแบ่งเป็นชุดสำหรับ train ตัว model และแบ่งอีกส่วนนึงมาเป็นชุดสำหรับ test ตัว model ว่าสามารถทำนายผลได้แม่นยำมากน้อยแค่ไหน โดยเทียบ label จากโมเดลกับ label จริงของชุด test ซึ่งจะวัดผลจากค่า error ที่เกิดขึ้น เราแบ่งสัดส่วนชุดข้อมูลเป็น 80:20

import library math เข้ามา เพื่อช่วยในการคำนวณ และเราทำการแบ่งข้อมูลโดยกำหนดให้ชื่อตัวแปร ‘_X_train’ เป็น feature และ ‘_y_train’ เป็น label ที่โมเดลจะเอาไปเรียนรู้ ส่วน ‘_X_test’ เป็น feature ชุดทดสอบ และ ‘_y_test’ เป็นค่า label ของชุดทดสอบ

Split Train and Test data

หลังจากแบ่งเส็รจเราจะทำการ fit model กับชุดข้อมูล เรา import library sklearn.linear_model โดยโมเดลที่เลือกมาทำนายคือ LinearRegression และทำการทดสอบการทำนายโดยกำหนดตัวแปรขึ้นมาอีกหนึ่งตัวคือ ‘_y_hat’ เป็นผลที่โมเดลทำนายออกมาได้ โดยใช้ข้อมูลชุดทดสอบ

Fitting model to data

ซึ่งจากที่กล่าวข้างต้น ค่า error ของตัว label ที่เป็น ‘_y_hat’ เทียบกับ ‘_y_test’ จะเป็นตัวบอกค่าความแม่นยำของ model โดยเราเทียบค่าต่างในรูป root mean square error (rmse) แปรผลโดยมีเกณฑ์ว่า ค่า rmse ยิ่งเข้าใกล้ 0 ยิ่งดี นั่นคือโมเดลทำนายแม่นยำ แสดงค่าความผิดพลาดออกมาน้อย
ตัว code ทำโดยการ import library sklearn.metrics และเรียกใช้ mean_squared_error, import library math เรียกใช้ sqrt

ตัวอย่างที่ทดลองให้ดูคือหุ้น SCB ได้ค่า rmse 3.648 เทียบกับค่าเฉลี่ยของ rmse ทั้ง SET100 ที่ 3.743 ใกล้เคียงกัน ตีความว่าเกาะกลุ่มกับหุ้นตัวอื่นๆ แต่ก็ไม่จัดว่าดีเพราะค่าออกห่างจาก 0 ไปค่อนข้างเยอะ

เปรียบเทียบความแม่นยำของ model โดยดูจากค่า error rmse

6. Result & Visualize : การแสดงผลลัพท์ที่ได้จาก model linear regression ในการทำนายราคาหุ้น โดย plot กราฟแสดงค่าของราคาหุ้น Predicted price เทียบกับ Actual price จากชุดข้อมูล test

ยกตัวอย่าง หุ้น SCB จะเห็นว่าค่าทำนายที่ได้จาก model จะใกล้เคียงกับค่าจริงเฉพาะช่วงเวลาที่มีการเปลี่ยนแปลงไม่มากเท่านั้น

Prodicted price vs. Actual price

7. Stock scanning : เป็นส่วนที่สำคัญที่สุดของโปรเจคนี้เพราะจะเป็นการแสดงค่าออกมาว่าหุ้นตัวไหนน่าจะให้ผลตอบแทนดีที่สุดในอีก 7 วันทำการถัดไป ซึ่งในส่วนของการเขียน code จะใช้คำสั่ง for loop ดึงค่า _y_hat ของหุ้นทุกตัวออกมา จากนั้นเอามาจัดลำดับใหม่โดยให้ค่าเรียงจากมากไปน้อย เราจะได้รายชื่อหุ้นที่น่าจะมีราคาเปลี่ยนแปลงในช่วง 7 วันทำการถัดไปที่สูงที่สุดออกมา คือ TVO ที่ราคาปิดสูงขึ้น 12.87% ในวันที่ 24 กันยายน 2563 เทียบกับราคาปิดของวันที่ 15 กันยายน 2563

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

สรุป

  • หุ้นใน SET100 ตัวที่ model ทำนายว่าจะได้กำไรสูงสุดในวันที่ 24 กันยายน 2563 คือ หุ้น TVO
  • ค่า rmse ที่ได้ออกมาจาก LinearRegression model คือ 3.643 ซึ่งมีค่าค่อนข้างสูง แสดงว่าโมเดลอาจจะมีความแม่นยำน้อย ประสิทธิภาพยังไม่ดีมากนัก
  • ระยะเวลาที่เอามาคำนวณ indicator ไม่เหมาะสมกับระยะเวลาที่ต้องการถือหุ้น
  • การมีข้อมูลทุกสิ้นวันอาจจะไม่พอ นั่นคือข้อมูล 7 วันอาจจะน้อยเกินไป อาจจะต้องมีข้อมูลรายสัปดาห์เพื่อให้เห็นภาพรวมแนวโน้มหลัก (primary trend) หรือ ข้อมูลรายชั่วโมงเพื่อให้เห็นแนวโน้มที่เล็กลงมา (secondary trend) มาประกอบการตัดสินใจ

--

--