📈ทำนายราคาหุ้นด้วย LSTM + Embedding ด้วย Pytorch🔥

Witchapong Daroontham
DATAWIZ
Published in
4 min readApr 21, 2019

การทำ forecast สำหรับข้อมูลประเภท time series สามารถทำได้ทั้งแบบ univariate (feature เดียว) และ multivariate (หลาย feature)… วันนี้เราจะมาทำ forecast ราคาหุ้นแบบ multivariate กัน เพราะราคาหุ้นนั้นขึ้นอยู่กับหลายปัจจัย และไม่ได้สะท้อนอยู่ในราคาทั้งหมด (univariate คือทำนายราคาในอนาคต จากราคาในอดีตเพียงอย่างเดียว) โดย feature ทั้งหลายเหล่านี้ที่จะนำมาเข้า model ได้แก่ Open price (ราคาเปิด), Close price (ราคาปิด), High price (ราคาสูงสุด), Low price (ราคาต่ำสุด), Volume, และ feature ที่สามารถ extract ได้จาก datetime (วันที่ทำการเทรด) ซึ่งเป็นข้อมูลที่สามารถดึงได้สะดวกด้วย API ของ Yahoo Finance… นอกเหนือจาก feature เหล่านี้ เรายังสามารถเพิ่ม feature อื่นๆ ที่น่าสนใจ เช่น ข้อมูล index ที่หุ้นที่เราสนใจอยู่, ข้อมูล index ตลาดอื่นๆ ทั่วโลก, ข้อมูลหุ้นตัวอื่นๆที่อาจจะเกี่ยวข้องกันในตลาด, หรือข้อมูลข่าวสารที่ mention ถึงหุ้นที่เราสนใจ เป็นต้น

Model overview & result

Credit: ขอบคุณพี่ Charin Polpanumas สำหรับ code และ model ตัวอย่าง ที่(90%) ถูกนำมาปรับใช้ในส่วน architecture & training ของ model นี้

Preprocessing:

เราจะแบ่ง feature ออกเป็น 2 กลุ่ม กลุ่มแรก คือ sequential feature ซึ่งเราจะให้ความสำคัญกับลำดับ หรือเวลาของ feature กลุ่มนี้ ได้แก่ Open/Close price, High/Low price, และ Volume เราจะ input ค่าของ feature เหล่านี้เป็นลำดับ เช่น [p_open(t-1), p_close(t-1), p_h(t-1), p_l(t-1), vol(t-1)] , …, [p_open(t-n), p_close(t-n), p_h(t-n), p_l(t-n), vol(t-n)] เราจะ input feature กลุ่มนี้เข้า RNN layer (เราเลือกใช้ LSTM)

กลุ่มที่สอง คือ static feature ซึ่งเป็น feature ที่เราไม่ต้องมีลำดับ ในที่นี้เรากำหนดให้ categorical feature ทั้งหมดที่สร้างมาจาก datetime เป็น static feature สำหรับ input เข้า embedding layer

กำหนด target:

target ของเรา คือ %close price change เทียบกับวันก่อนหน้า โดยเราจะ predict ล่วงหน้า 1 วัน และค่า taget ในอดีตสามารถนำไปรวมอยู่กับ sequential feature ได้ (เหมือนเคส univariate ที่เอา target ในอดีต predict target ในอนาคต)

ทำ feature engineer กับ datetime:

เราสามารถสร้าง feature เพิ่มเติมได้มากมายจากข้อมูล datetime เช่น วันนั้นเป็นวันอะไร เป็นวันที่เท่าไหร่ของปี ใช่ช่วงต้นเดือน หรือสิ้นเดือนไหม เป็นต้น (ถ้าจะ advance ไปอีก อาจจะเอาวันหยุดเข้ามาใส่ แล้วคิดว่าวันนั้นห่างจากวันหยุดที่กำลังจะมาถึงกี่วัน หรือผ่านวันหยุดล่าสุดมาแล้วกี่วัน) โดยเราจะเอา feature เหล่านี้มาเป็น static feature ของเรา

สำหรับรายละเอียดเรื่อง LSTM ติดตามอ่านได้ที่ blog เก่า นี้ เรื่องเดียวกัน แต่ใช้ Keras และไม่มี Embedding layer

หน้าตาโมเดลที่เราใช้จะเป็นแบบนี้

model architecture

ผล prediction

ลองมาดูผล prediction %price change จาก model นี้ ผมใช้ Mean Absolute Error เป็น loss function และได้ค่า error ของ validation set ที่ดีที่สุดอยู่ที่ประมาณ 3% ซึ่งถือว่าไม่ได้ดี เพราะปกติ วันนึงราคาหุ้นเปลี่ยนแปลงจากวันก่อนหน้าอยู่ในช่วง 0–2% เท่านั้นเอง ดังจะเห็นได้จากกราฟ %change ด้านล่างอันแรก ส่วนกราฟ Price ด้านล่างอันที่สอง เป็นการเปรียบเทียบราคาจริงๆ จึงอาจไม่ได้ดูแตกต่างกันน่าเกลียด รุนแรงเท่าไหร่ เพราะ output ของ model เป็น % เทียบราคาวันก่อน ยังไงก็มีราคาวันก่อนหน้าเป็นฐานอยู่แล้ว (สีแดง = prediction, สีน้ำเงิน = ค่าจริง)

Predicted vs True %price change (adjusted close price)
Predicted vs True price (adjusted close price)

ลองรัน simulation เล่นๆ ว่าเราลงทุนด้วยเงิน 1,000,000 บาท ตาม model นี้

ลองมารัน simulation เล่นๆ ว่าถ้าเราตัดสินใจลงทุนตาม model ดังกล่าว ถ้า model ทำนายว่าวันถัดไป %price change > 0 วันนี้เราจะตัดสินใจซื้อ โดยตั้งสมมติฐานว่าสามารถซื้อได้ที่ราคาปิด ซึ่งเป็นตัวอ้างอิง %price change ในวันถัดไป แต่ถ้าในวันถัดไป %price change < 0 วันนี้เราจะตัดสินใจขาย

ปรากฎว่าถ้าเราเริ่มต้นลงทุนตามวิธีด้านบนด้วย model นี้ ตั้งแต่ 2017-05–11 ถึง 2019–04–12 (ซึ่งเป็นช่วงวันที่ของ test set) ด้วยเงิน 1,000,000 บาท ณ วันสุดท้ายของการลงทุน เราจะมีเงินเป็นจำนวน… 1,114,072 บาท คิดเป็นผลตอบแทน 6.75% ต่อปี ซึ่งก็ดีกว่าฝากธนาคารนิดนึง (อย่าใส่ใจกับเลขมากครับ รันทีนึงผลตอบแทนก็ออกมาแบบนึง 🤣🤣🤣)

สรุปง่ายๆ เลยยังไม่เวิร์คครับ ได้เรียนรู้ และได้ลองเฉยๆ!

Pytorch structure

Pytorch logo

Pytorch เป็น framework สำหรับสร้าง ML ประเภท neural network ที่ถูกพัฒนาโดย Facebook ส่วนตัวที่หัดใช้ Pytorch เพราะเรียน course DL for coders v2 ของ FastAI (ส่วนตัวชอบคอร์สนี้มาก เพราะให้เทคนิคที่ลึก และละเอียด) ซึ่งเขียน on top จาก Pytorch อีกที และ Pytorch ก็มี Document พร้อม tutorial บนเว็บที่ดีมาก เลยเลือกใช้ ขั้นตอนการสร้าง neural network model ด้วย Pytorch จะเป็นดังนี้

Dataset & DataLoader:

ส่วนนี้ทำหน้าที่สำหรับ load ข้อมูลให้ model โดย class Dataset จะทำหน้าที่ ouput feature & target ออกมาทีละชุด สำหรับทำ model training เราจะใช้ class Dataset ด้วยวิธีการ inherit และ เขียน method __getitem__ เพื่อเรียกข้อมูลโดยใช้ index และ __len__ เพื่อ return ขนาดของ Dataset เมื่อเรียกใช้ builtin function len ของ Python ในการหาขนาดของ Dataset ส่วน class DataLoader ช่วย load ข้อมูลจาก Dataset ออกมาเป็น batch ตามขนาด batch size ที่เรากำหนด (1 batch คือ 1 รอบที่ neural network จะ ทำ backprop, gradient descend, และ weight update)

ตัวอย่าง Dataset & DataLoader

Model:

ส่วนนี้ก็คือ โครงสร้างของ neural network เราจะสร้าง class สำหรับ model โดย inherit จาก class nn.Module ซึ่งมี 2 method ที่เราต้องเขียน คือ __init___ สำหรับกำหนดโครงสร้างว่า model ของเรามี layer อะไรบ้าง และ config ค่า dimension ต่างๆ อย่างไร และ __forward___ สำหรับกำหนดว่าในขั้นตอน forward propagation ข้อมูลที่ input มาจาก Dataloader จะเข้ามาที่ layer ไหน และแต่ละ layer เชื่อมต่อกันอย่างไร

ตัวอย่าง model

Training:

มาถึงส่วนสุดท้ายสำหรับการสร้าง neural network ด้วย Pytorch อันได้แก่การทำ training ด้วยการเขียน for loop ตามจำนวน epoch ที่ต้องการทำ training ในขั้นตอนนี้เราต้องกำหนด loss function และ optimizer สำหรับ model นี้เราจะใช้ MSE และ Adam optimizer ตามลำดับ

ในแต่ละ epoch ก็จะมี nested for loop ข้างในอีกที สำหรับ batch training โดยขั้นตอนในการ training จะเป็นไปตามลำดับ คือ (i) ทำ forward propagation (ii) คิดค่า loss (iii) ทำ back propagation และ update weight

ตัวอย่าง training

Prospect work

เราจะปรับปรุง model สำหรับทำ forecast แบบ multivariate ได้อย่างไร? แน่นอนว่า model LSTM เพียงลำพังยังมีข้อจำกัด คือ ความจำในระยะยาวยังค่อนข้างจำกัด และ output ที่ออกมาบางครั้งให้ค่าที่กระโดดไปจากวันก่อนๆ ค่อนข้างมาก

รู้จักกับ LSTNet

LSTNet คือ model สำหรับ mutivariate time series ที่มีอะไรเพิ่มเติมมาจาก LSTM model พื้นฐาน 3 อย่าง

  1. มี CNN layer วางอยู่ก่อน RNN layer ซึ่ง convolutional filter ใน layer นี้จะทำหน้าที่หาความสัมพันธ์ระหว่าง feature ในเวลาเดียวกัน และเวลาต่างๆกัน
  2. นอกจากจะมี RNN layer แบบธรรมดา แล้วยังมี RNN layer ที่ต่อกันแบบ skip connection คือ แทนที่จะต่อ RNN unit กันเป็นลำดับต่อกัน ก็ไปต่อกับ RNN unit ที่อยู่ถัดไป p unit แทน
  3. มี AR layer มา integrate กับ output จาก RNN layer เพื่อให้ได้ output ที่ไม่กระโดดไปจากค่าในวันก่อนนัก
ref: https://modelzoo.co/model/lstnet

อ่าน original paper + code LSTNet:

https://github.com/laiguokun/LSTNet

Code เต็ม:

HAPPY LEARNING!

--

--

Witchapong Daroontham
DATAWIZ

Data scientist at Central Technology Organization — CTO, Bangkok & life long learner