Meningkatkan Performa Model Prediksi Harga Saham dengan Relative Strength Index (RSI)

Rizkynindra
14 min readJul 30, 2023

PART #01: INTRODUCTION

Project ini masuk dalam kategori time series prediction. Sebelum membahas lebih dalam, mari kita mengenal terlebih dahulu definisi dari stock market. Stock atau yang juga dikenal dengan istilah ekuitas adalah sebuah keamanan yang mewakili kepemilikan dari bagian kecil dari perusahaan. Stock diperjualbelikan di bursa saham dan merupakan dasar dari terciptanya banyak portfolio investor. Perdagangan saham harus mengikuti aturan pemerintah guna melindungi investor dari penipuan.

Time series sendiri memiliki arti sekumpulan data observasi yang dikoleksi berdasarkan kurun waktu tertentu. Contoh time series yang dulu sering kita jumpai adalah memprediksi jumlah pasien covid. Kala itu, prediksi jumlah pasien covid dapat digunakan oleh para ahli untuk mengambil keputusan kedepannya. Dan prediksinya bisa dalam bentuk harian atau bulanan.

PART #02: LOAD DATASET

dataset yang akan kita gunakan tidak tersedia di Kaggle. Jadi disini kita akan membuat dataset dengan mencarinya dari sumber lain. Dan untuk harga saham yang akan kita prediksi adalah saham google dengan kode “GOOGL”. Datanya kita ambil dari API Yahoo Finance (YFinance). Yfinance menyediakan data market yang disediakan oleh yahoo yang dapat didownload dengan menggunakan perintah dari python.

Langkah awal silakan diinstall terlebih dahulu API YFinance-nya.

Figure 01. Install YFinance

Cukup ketik code pada figure 02 dan tunggu hasilnya sampai semua komponen selesai terinstall. Setelah selesai, kita import library yfinance dan tensorflow.

Figure 02. Import library YFinance

Kemudian, karena harga saham yang akan kita prediksi adalah google maka kita download dulu history data saham milik google. Caranya bisa kalian lihat pada code di figure 03.

Figure 03. Download Data Saham Google

Sebelum beranjak ke tahap berikutnya, mari kita sedikit bedah apa yang ada di dalam kurung tersebut. Yang pertama “GOOGL” adalah kode saham untuk google. Kemudian perintah “start” digunakan untuk menentukan tanggal awal data akan diambil, lalu “end” digunakan untuk menentukan tanggal akhir dari data yang akan diambil. Untuk “end” sendiri bersifat opsional. Jadi jika kalian tidak memasukkan perintah “end” maka data yang kita dapatkan akan berakhir sampai dengan tanggal kalender saat kalian membuat programnya. Selanjutnya “interval” adalah perintah untuk menentukan jangka waktu pengambilan data. Interval bisa berupa waktu harian, mingguan atau bulanan.

Untuk studi kasus ini, data yang digunakan adalah data dari awal tahun januari sampai 28 Februari 2023 dengan interval waktu 1 hari. Selanjutnya Langkah umum yang sering kita lakukan yaitu mengecek shape dari data yang kita miliki.

Figure 04. Cek Data Shape

Terlihat bahwa kita memiliki 794 data dengan 6 fitur yang ada di dalamnya. Selanjutnya mari kita lihat fitur apa saja yang dimiliki oleh dataset ini.

Figure 05. Cek fitur dataset

Disini kita punya fitur ‘Open’, ‘High’, ‘Low’, ‘Close’, dan ‘Volume’. Mari kita pelajari sedikit arti dari fitur — fitur ini. Misalkan kita punya sesi trading dari jam 09:30 sampai jam 16:00. Nah, harga saham di jam 09:30 ini dinamakan ‘Open’ dan harga di jam 16:00 disebut ‘Close’. Nilai High dan Low ditentukan oleh tingkat sentiment masyarakat Ketika saham perusahaan diperdagangkan secara terbuka.

Disini kita bisa gunakan google sebagai contohnya. Ketika google mengumumkan event promo salah satu produknya, hal ini bisa membuat masyarakat memberikan harga tinggi di esok hari ketika perdagangan saham dibuka. Sebaliknya, jika server google mengalami gangguan atau produk yang mereka pasarkan bermasalah kemudian masyarakat mengeluh di sosial media, ini akan membuat nilai saham google anjlok pada hari berikutnya. Hal — hal seperti inilah salah satu contoh yang mempengaruhi naik turunnya harga saham atau yang dikenal dengan istilah ‘High’ dan ‘Low’.

‘Adj Close’ adalah penyesuaian harga penutupan saham yang masih mencerminkan harga saham tersebut setelah dilakukan beberapa Tindakan. Misalkan harga saham Google senilai USD 1750, tentu akan sangat susah bagi masyarakat untuk membeli 1 saham google. Sehingga dilakukan pemecahan menjadi 100 bagian dan harganya pun dibagi sama rata menjadi USD 17,5 agar mempermudah masyarakat untuk mendapatkan 1 lembar saham dari google. Dan yang terakhir, ‘Volume’ adalah pengukuran seberapa banyak jumlah saham yang diperdagangkan dalam kurun waktu tertentu.

Oke itu tadi penjelasan dari tiap — tiap fitur dari dataset ini. Selanjutnya mari kita lakukan sedikit penyesuaian terhadap dataset ini.

Figure 06. Sort index & Remove Duplicate Item

Selanjutnya kita bisa mengecek data pada tanggal terakhir dari dataset ini dengan menggunakan perintah ‘tail’.

Figure 07. Data pada Tanggal Terakhir

Angka pada perintah tail menunjukkan jumlah data yang akan ditampilkan. Jika angka yang kita tetapkan 5, maka data yang tampil adalah 5 terbawah seperti yang terlihat pada gambar figure 08.

Figure 08. Hasil Data.tail

Langkah berikutnya adalah pengecekan null values dan deskripsi dari dataset.

Figure09. Pengecekan null values
Figure 10. Melihat Detail Dataset

Berikutnya, kita import library dari plotly untuk menampilkan grafik saham google. Dan untuk mode yang digunakan adalah lines dan data yang digunakan adalah ‘Close’.

Figure 11. Cek trend harga saham google.

Hasil dari code diatas bisa dilihat pada grafik dibawah ini. Terlihat bahwa harga ‘Close’ Google berada pada titik terendah pada bulan Maret 2020 dan beranjak meningkat dari awal Tahun 2021 dan mencapai harga tertinggi pada periode Juli 2021 sampai Januari 2022.

Figure 12. Cek Trend pada Close

Kita juga bisa melihat trend dari volume dengan mengetik code pada figure 13.

Figure 13. Cek trend pada Volume

Terlihat bahwa ‘Volume’ memiliki pola yang sama pada beberapa periode. Meskipun demikian, kita tidak bisa melihat trend naik turunnya harga saham dengan melihat ‘Volume’ karena secara definisi ‘Volume’ hanya menggambarkan jumlah pembelian saham pada periode waktu tertentu.

PART #03: DATA PREPROCESSING

Masuk ke tahap data preprocessing, kita import beberapa library tambahan yang dibutuhkan pada project ini yaitu MinMaxScaler, pickle, dan tqdm. MinMaxScaler mengurangi nilai minimum pada feature dan membaginya berdasarkan area. Area yang dimaksud adalah perbedaan jarak antara nilai asli maksimum dan nilai asli minimum. MinMaxScaler tidak mengubah informasi apapun yang terkandung di data asli.

Kemudian pickle adalah modul yang digunakan untuk membuat serial dan de-serializing sebuah struktur objek python. Atau dengan kata lain sebuah proses untuk mengkonversi sebuah objek python menjadi byte stream untuk disimpan ke dalam database.

Lalu ada tqdm yang fungsinya cukup simple yaitu membuat sebuah progress bar pada python. Jadi, tahap awal dari data preprocessing ini silakan ketik code dibawah untuk mengimport library — library ini.

Figure 14. Import MinMaxScaler, Pickle, dan tqdm

Selanjutnya kita ambil feature ‘Close’ dan ‘Volume’ saja. Disini saya tampilkan cuma 5 data saja ya, kalau kalian mau lebih boleh — boleh aja.

Figure 15. Ambil feature ‘Close’ dan ‘Volume’

Kemudian kita atur untuk alokasi testing datanya. Disini saya pakai data dengan rentang waktu dari bulan Oktober 2022 sebagai testing datanya. Jadi bisa dibilang kita pakai data dari 5 bulan terakhir (Oktober 2022 — Februari 2023) untuk dilakukan pengujian terhadap model kita nantinya.

Figure 16. Alokasi Testing Data

Selanjutnya kita buat sebuah fungsi yang mengambil data frame dan feature length dan mengembalikannya ke ‘features’ dan ‘targets’.

Figure 17. Membuat fungsi features dan target

Pada baris pertama, ‘data’ adalah dataset yang kita miliki yang berisi ‘Close’ dan ‘Volume’. Kemudian ‘feature_length’ adalah jumlah data point yang akan kita tentukan. Selanjutnya kita jalankan fungsi tersebut dengan mengetik code berikut ini.

Figure 18. Membuat features dan target

Sekalian kita bisa langsung cek shape dari X dan Y yang telah kita buat.

Figure 19. Cek shape dari X dan Y

Kita punya data berbentuk 3 dimensi pada X dan 1 dimensi pada Y. dimensi pertama adalah jumlah data yang kita miliki, dimensi kedua adalah feature_length yang kita pilih, dan dimensi ketiga adalah jumlah kolom dari data yang kita filter. Selanjutnya kita bagi features dan target tersebut dengan train test split.

Figure 20. Split features dan target dengan train test split

Langsung dilanjutkan dengan pengecekan shape masing — masing.

Figure 21. Cek shape train & test data

Karena kita memiliki 3 dimensi sedangkan scaler hanya berfungsi terhadap fitur 2 dimensi. Maka kita buatkan sebuah fungsi agar scaler bisa berfungsi pada data yang memiliki lebih dari 2 dimensi.

Figure 22. Multidimension Scaler

Selanjutnya, mari kita fit-kan training dan testing data kita.

Figure 23. Fit transform feature
Figure 24. Fit transform target

Untuk ‘target’, kita tambahkan perintah reshape agar datanya menjadi 2 dimensi. Selanjutnya Langkah seperti biasa, kita cek Kembali masing — masing shape-nya.

Figure 25. Cek shape training dan testing data

Sebelum masuk ke pembuatan model, Langkah terakhir kita buat 2 fungsi yang bertujuan untuk menyimpan objek dan memanggil kembali objek tersebut.

Figure 26. Fungsi Save dan load object.

PART #04: CREATE MODEL

Sekarang kita sudah memasuki tahap pembuatan model. Pada tahap ini, kita menambahkan library ModelCheckpoint dan ReduceLROnPlateau. ReduceLROnPlateau berfungsi untuk menggurangi learning rate ketika tidak ada peningkatan pada nilai validation loss.

Figure 27. Konfigurasi Model

Pada studi kasus kali ini, kita menggunakan ‘elu’ sebagai activationnya. Berbeda dengan ‘relu’. ‘Elu’ memiliki nilai negatif yang mendorong nilai rata — rata activation mendekati 0. Untuk penggunaannya sama saja dengan relu yaitu kita tinggal panggil saja activationnya.

Figure 28. Membuat model dengan activation ‘elu’

Untuk optimizernya kita akan gunakan SGD pada studi kasus ini karena setelah saya melakukan percobaan dengan membandingkan SGD dan Adam, SGD performanya lebih baik.

Figure 29. Optimizer dengan SGD

Selanjutnya mari kita fit-kan model kita. Untuk settingannya, saya hanya menggunakan 10 epochs karena datanya juga ga banyak — banyak banget.

Figure 30. Fit the model

Seperti biasa, tunggu saja prosesnya hingga selesai. Karena epochs kita sedikit seharusnya ga akan memakan banyak waktu untuk prosesnya. Kalau sudah selesai, jangan lupa kita load modelnya dengan perintah load_weights.

Figure 31. Load weights

Setelah di load, langsung aja kita deklarasikan perintah untuk memprediksinya dengan perintah predict.

Figure 32. Predict the model

Kalau kalian ingat, sebelumnya kita telah men-scaled nilai targetnya sebelum pembuatan model. Maka sekarang hasil prediksinya kita scaled juga agar Langkah yang kita lakukan tetap konsisten.

Figure 33. Scaled hasil prediksi
Figure 34. Shape dari hasil prediksi

Dilanjutkan dengan menampilkan shape-nya (figure 34), disini hasil prediksinya berbentuk 2 dimensi. Nah, disini yang kita butuhkan hanya 1 dimensi saja. Jadi kita gunakan fungsi squeeze untuk mengubah dimensinya menjadi 1 dimensi aja.

Figure 35. Squeeze pada predictions & actual

Selanjutnya kita tampilkan hasil prediksi dari model yang sudah kita buat dengan nilai aslinya sebagai perbandingan performa dari model kita. Disini tipe grafik yang kita gunakan adalah garis (lines). Code dan hasilnya bisa kalian lihat pada figure 36 dan 37 dibawah ini.

Figure 36. Menampilkan hasil prediksi dengan grafik
Figure 37. Grafik perbandingan nilai prediksi dengan nilai aktual

Garis berwarna merah menunjukkan hasil prediksi sedangkan yang berwarna biru menunjukkan nilai aktual. Disini terlihat bahwa grafik dari hasil prediksi masih belum bisa mengimbangi atau menyesuaikan ritme dari nilai aktual. Kita bisa cek performa grafiknya menggunakan keseluruhan dataset tapi sebelum itu kita perlu gabung dulu training data dengan testing datanya. Kita bisa gunakan perintah concatenate untuk penggabungannya, dan selanjutnya langkahnya sama dengan apa yang kita lakukan setelah load weights. Jadi silakan di ketik code — code dibawah ini.

Figure 38. Step by step menampilkan grafik data dataset yang utuh

Hasil dari sejumlah code pada figure 38 bisa kalian lihat di figure 39 dibawah ini. Secara keseluruhan bisa kalian lihat bahwa nilai prediksinya sedikit mampu mengikuti ritme dari nilai aktualnya hanya saja tidak signifikan. Jadi pada part berikutnya kita akan bahas fitur apa yang bisa kita gunakan untuk meningkatkan performa model kita.

Figure 39. Grafik perbandingan nilai prediksi dengan nilai aktual pada dataset utuh

PART #05: EVALUATE MODEL

Pada part ini, kita akan menambahkan satu feature ke dalam dataset untuk mengimprove performa prediksinya. Fitur yang akan kita ambil adalah Relative Strength Index atau RSI. RSI adalah sebuah indicator yang digunakan dalam analisis teknikal. RSI mengukur kecepatan dan besarnya perubahan harga sekuritas untuk mengevaluasi kondisi overvalued atau undervalued pada sekuritas tersebut.

Untuk pengambilan datanya sendiri kita masih tetap menggunakan sumber dari Yahoo Finance jadi langsung aja diketik code dibawah ini.

Figure 40. Ambil data RSI Google

Baris ke-3 pada code adalah waktu dimulainya pengambilan data. Disini saya mengambil data dari bulan Agustus 2004. Kemudian baris ke 6 menunjukkan periode dari RSI itu sendiri. Nilai terbaik dari periode RSI berkisar antara 2–6 dan nilai standar yang pas untuk segala situasi adalah 14. Pada studi kasus ini, semua rentang nilai tersebut sudah saya coba dan hasil terbaik yang saya dapatkan adalah di angka 5. Kemudian baris ke 7 sampai 13 adalah rumus untuk menghitung nilai RSI nya. Jujur saya tidak terlalu paham mengenai perhitungannya jadi saya ga bisa banyak menjelaskan terkait rumusnya disini (maklum bukan pakar ekonomi, #haha).

Oke, setelah kita mendapatkan data RSI-nya langsung aja kita konversi menjadi sebuah dataframe dengan tanggal (date) sebagai indexnya dan nilai RSI sebagai valuenya.

Figure 41. Konversi data RSI ke bentuk dataframe

Bila kalian perhatikan, date pada RSI ini masih berisi data waktu (00:00:00–04:00), ini akan kita hapus supaya sama dengan tipe data date pada data sebelumnya.

Figure 42. Menghapus waktu pada date

Nantinya datanya akan berubah seperti pada figure 43 dibawah ini.

Figure 43. Data RSI Fix

Setelah datanya sesuai, selanjutnya kita gabungkan data awal dengan data yang sudah berisi RSI dengan menggunakan perintah merge. Dan hasil akhir dari datanya akan berisikan fitur ‘Close’, ‘Volume’, dan ‘RSI’.

Figure 44. Menggabungkan Data Dengan Merge

Selanjutnya kita akan latih ulang (re-train) modelnya dengan data baru yang berisikan RSI. Untuk codenya sendiri sebenarnya sama dengan code training sebelumnya. Langkahnya diawali dengan penentuan rentang waktu untuk test dataset. Sama seperti sebelumnya, disini kita atur waktunya dari bulan Oktober 2022.

Figure 45. Menentukan Testing Data

Berhubung Langkah selanjutnya sama dengan Langkah sebelumnya. Jadi disini saya hanya akan menampilkan baris codingannya saja yang bisa kalian ikuti baris per barisnya. Nanti diakhir akan saya jelaskan kesimpulan dari hasil yang kita dapat.

Figure 46. Membuat fungsi Fitur dan Target
Figure 47. Membuat Features dan Target
Figure 48. Cek Shape dari X dan Y
Figure 49. Split features dan target dengan train test split
Figure 50. Cek shape train & test data
Figure 51. Multidimension Scaler
Figure 52. Fit transform feature
Figure 53. Fit transform target
Figure 54. Cek shape training dan testing data
Figure 55. Fungsi Save dan load object

Langkah — Langkah diatas adalah Langkah untuk mengkonfigurasi ulang training dan testing data. Selanjutnya adalah tahapan untuk membuat ulang modelnya. Tahapan ini juga Langkah — langkahnya sama dengan Langkah pembuatan model sebelumnya (sebelum adanya RSI). Jadi silakan kalian lanjut lagi mengcoding baris — baris code dibawah ini sampai akhir.

Figure 56. Step by Step re-build the model

Dan akhirnya kita tiba di akhir baris coding. Gambar terakhir dari figure 56 adalah hasil prediksi dari dataset yang telah kita tambahkan RSI. Untuk lebih jelasnya, disini saya bandingkan hasil tersebut dengan hasil dari dataset yang tanpa RSI melalui figure 57 dibawah.

Figure 57. Nilai Prediksi sebelum (atas) dan sesudah (bawah) ditambah RSI

Jika kalian perhatikan, area yang saya highlight dengan kotak warna hijau adalah area yang kita prediksi. Terlihat bahwa kurva nilai prediksi dari dataset yang berisi RSI sudah mulai bisa mengikuti kurva nilai aktual. Ini membuktikan bahwa data RSI berpengaruh besar dalam pembuatan model time series harga saham walaupun memang masih belum bisa menyerupai persis seperti nilai aktualnya.

--

--

Rizkynindra
Rizkynindra

Responses (1)