Laporan Proyek Sains Data 1#
Analisis dan Prediksi Harga Bitcoin (BTC) Menggunakan Data Historis sebagai Dasar Pengambilan Keputusan Investasi#
PENDAHULUAN#
Latar Belakang#
Bitcoin (BTC; simbol: ₿) adalah cryptocurrency pertama yang terdesentralisasi, menggunakan teknologi blockchain untuk mencatat transaksi secara aman dan terbuka sejak diperkenalkan pada 2008 oleh Satoshi Nakamoto. Sebagai pelopor aset digital, Bitcoin menggunakan mekanisme proof of work (PoW) untuk mengamankan jaringan, meski sering dikritik karena konsumsi listriknya yang tinggi. Selain sebagai mata uang, Bitcoin lebih sering dianggap sebagai instrumen investasi, dengan El Salvador menjadi negara pertama yang mengadopsinya sebagai alat pembayaran sah pada 2021. Namun, sifatnya yang pseudonim dan volatilitasnya yang tinggi menarik perhatian regulator dan memicu larangan di beberapa negara, meskipun popularitasnya terus meningkat.
Nilai Bitcoin cenderung sangat fluktuatif, dengan perubahan yang signifikan dalam waktu singkat. Beragam faktor seperti sentimen pasar global, tingkat penerimaan teknologi, kebijakan pemerintah, dan kondisi ekonomi dunia menjadi pemicu utama volatilitas tersebut. Ketidakstabilan ini sering kali menyulitkan investor dalam mengelola portofolio mereka secara optimal.
Sebagai solusi, teknologi kecerdasan buatan seperti machine learning dapat dimanfaatkan untuk mengatasi tantangan ini. Dengan memanfaatkan data historis, metode ini mampu menghasilkan prediksi harga yang lebih akurat, mengurangi ketidakpastian, dan mendukung pengambilan keputusan investasi yang lebih bijaksana dan strategis. Bitcoin terus menjadi inovasi yang merevolusi cara pandang dunia terhadap keuangan digital, menciptakan peluang besar sekaligus tantangan baru dalam ekosistemnya.
Tujuan#
Proyek ini bertujuan untuk mengembangkan model prediksi harga cryptocurrency Bitcoin (BTC) berdasarkan data historis. Melalui analisis ini, diharapkan dapat membantu investor dalam membuat keputusan investasi yang lebih tepat serta memberikan wawasan mengenai potensi pergerakan harga Bitcoin untuk memaksimalkan keuntungan dan mengelola risiko secara lebih efektif.
Rumusan Masalah#
- Bagaimana mengembangkan model prediksi harga Bitcoin (BTC) yang dapat diandalkan dengan menggunakan data historis, dan bagaimana hasil prediksi tersebut dapat membantu dalam pengambilan keputusan investasi yang lebih strategis di pasar cryptocurrency?
METODOLOGI#
Data Understanding#
a. Sumber Data#
Data yang digunakan pada proyek ini diambil dari platform Yahoo Finance, yang beralamat di https://finance.yahoo.com/quote/BTC-USD/. Platform ini menyediakan informasi harga Bitcoin (BTC) yang mencakup data historis harga Bitcoin terhadap dolar AS (USD) dari berbagai periode waktu. Informasi ini termasuk harga penutupan, perubahan harga harian, dan berbagai fitur analisis pasar. Dalam proyek ini, digunakan data harga Bitcoin yang tersedia dalam format CSV, mencakup periode dari tanggal 2020 Januari 01 hingga 2024 Desember 06.
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import MinMaxScaler
from sklearn.ensemble import GradientBoostingRegressor
from sklearn.linear_model import LinearRegression, Ridge
from sklearn.metrics import mean_squared_error, r2_score, mean_absolute_percentage_error
import seaborn as sns
import matplotlib.pyplot as plt
# Membaca data
#Mengambil dan menampilkan data
df = pd.read_csv('https://raw.githubusercontent.com/chacalala/psd/refs/heads/main/bitcoin.csv')
pd.options.display.float_format = '{:.0f}'.format
print(df.head())
Date Open High Low Close Adj Close Volume
0 2020-01-01 7195 7254 7175 7200 7200 18565664997
1 2020-01-02 7203 7212 6935 6986 6986 20802083465
2 2020-01-03 6984 7414 6915 7345 7345 28111481032
3 2020-01-04 7345 7427 7310 7411 7411 18444271275
4 2020-01-05 7410 7544 7400 7411 7411 19725074095
Di sini, perubahan dilakukan agar kolom Date bisa diproses dengan benar sebagai tanggal. Dengan mengubahnya ke format datetime, kita bisa lebih mudah melakukan perbandingan atau analisis berdasarkan waktu. Kemudian, menjadikan Date sebagai indeks membuat data lebih mudah dicari berdasarkan tanggal, dan menyortirnya memastikan data tersusun dengan urutan waktu yang benar.
# mengubah kolom 'Date' dalam format datetime
df['Date'] = pd.to_datetime(df['Date'])
# Mengatur kolom 'Date' sebagai indeks
df.set_index('Date', inplace=True)
# Mensortir data berdasarkan kolom Date dari terkecil ke terbesar
df = df.sort_values(by='Date')
df
Open | High | Low | Close | Adj Close | Volume | |
---|---|---|---|---|---|---|
Date | ||||||
2020-01-01 | 7195 | 7254 | 7175 | 7200 | 7200 | 18565664997 |
2020-01-02 | 7203 | 7212 | 6935 | 6986 | 6986 | 20802083465 |
2020-01-03 | 6984 | 7414 | 6915 | 7345 | 7345 | 28111481032 |
2020-01-04 | 7345 | 7427 | 7310 | 7411 | 7411 | 18444271275 |
2020-01-05 | 7410 | 7544 | 7400 | 7411 | 7411 | 19725074095 |
... | ... | ... | ... | ... | ... | ... |
2024-12-02 | 97276 | 98153 | 94483 | 95865 | 95865 | 72680784305 |
2024-12-03 | 95855 | 96297 | 93630 | 96002 | 96002 | 67067810961 |
2024-12-04 | 95988 | 99207 | 94660 | 98768 | 98768 | 77199817112 |
2024-12-05 | 98742 | 103900 | 91999 | 96594 | 96594 | 149218945580 |
2024-12-06 | 97074 | 102040 | 96515 | 99921 | 99921 | 94534772658 |
1802 rows × 6 columns
b. Deskripsi Dataset#
Dataset ini terdiri dari 8 fitur atau kolom, dan 2230 record atau baris. Berikut adalah penjelasan setiap atribut:
- Date: Tanggal data harga aset koin (format YYYY-MM-DD)
- Open: Harga pembukaan aset koin pada tanggal tersebut
- High: Harga tertinggi yang dicapai pada tanggal tersebut
- Low: Harga terendah aset koin pada tanggal tersebut
- Close: Harga penutupan aset koin pada tanggal tersebut
- Adj Close: Harga penutupan yang sudah disesuaikan dengan pembagian aset koin, dividen, dan corporate actions lainnya
- Volume: Jumlah aset koin yang diperdagangkan pada tanggal tersebut
Selanjutnya, memeriksa informasi tentang dataset untuk melihat jumlah baris dan kolom, serta tipe data dari masing-masing kolom. Ini membantu kita memastikan bahwa semua data sudah lengkap dan tidak ada yang hilang. Selain itu, kita juga ingin mengetahui ukuran data untuk melihat berapa banyak baris dan kolom yang ada. Dari hasil ini, kita bisa tahu bahwa dataset memiliki 1802 baris dan 6 kolom, dengan data yang lengkap dan tipe data yang sesuai.
df.info()
print('Ukuran data ', df.shape)
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 1802 entries, 2020-01-01 to 2024-12-06
Data columns (total 6 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Open 1802 non-null float64
1 High 1802 non-null float64
2 Low 1802 non-null float64
3 Close 1802 non-null float64
4 Adj Close 1802 non-null float64
5 Volume 1802 non-null int64
dtypes: float64(5), int64(1)
memory usage: 98.5 KB
Ukuran data (1802, 6)
c. Eksplorasi Data#
Setelah itu, melihat apakah didalam data set tersebut ada missing value.
df.isnull().sum()
Open 0
High 0
Low 0
Close 0
Adj Close 0
Volume 0
dtype: int64
Setelah dilakukan pengecekan dan ternyata tidak ada missing value maka langkah selanjutnya yaitu membuat visualisasi tren data untuk setiap kolom dalam dataset. Dengan menggunakan `matplotlib` dan `seaborn`, kita akan menggambar grafik garis untuk setiap kolom, dengan tanggal sebagai sumbu X dan nilai kolom sebagai sumbu Y. Setiap grafik akan menampilkan tren perubahan nilai kolom tersebut seiring waktu, lengkap dengan label sumbu dan judul yang menjelaskan kolom yang sedang dianalisis. Grafik ini juga akan dilengkapi dengan grid dan rotasi sumbu X agar lebih mudah dibaca.
import matplotlib.pyplot as plt
import seaborn as sns
for col in df:
plt.figure(figsize=(7, 3))
sns.lineplot(data=df, x='Date', y=col)
plt.title(f'Trend of {col}')
plt.xlabel('Date')
plt.ylabel(col)
plt.grid(True)
plt.xticks(rotation=45)
plt.show()
![_images/3dd59809f7cbaf97731264f31621901d4695eb41b3e182cd0d8b45a6ac7db6c7.png](_images/3dd59809f7cbaf97731264f31621901d4695eb41b3e182cd0d8b45a6ac7db6c7.png)
![_images/ed2a820ed152e5c444173b1b4f29d6e777e46056bf8182622ce2328be69548c2.png](_images/ed2a820ed152e5c444173b1b4f29d6e777e46056bf8182622ce2328be69548c2.png)
![_images/9c3d00f97d4743cb7117ab8ef3b2ab93301fbe4510e99faa97d2754ea8a155da.png](_images/9c3d00f97d4743cb7117ab8ef3b2ab93301fbe4510e99faa97d2754ea8a155da.png)
![_images/d229c6875477abdc12a78eb12888e6c55f3dcc1edb89754d5ae016e9c7856a56.png](_images/d229c6875477abdc12a78eb12888e6c55f3dcc1edb89754d5ae016e9c7856a56.png)
![_images/3b934d1ad2809502f002dbcccb3bd9d942980eb5643636b874f1669d7bbe3afb.png](_images/3b934d1ad2809502f002dbcccb3bd9d942980eb5643636b874f1669d7bbe3afb.png)
![_images/6e2a04e34b0beaae2b30696f191a3781f1931055260ef071db380974526b573c.png](_images/6e2a04e34b0beaae2b30696f191a3781f1931055260ef071db380974526b573c.png)
Selanjutnya melakukan pengecekan struktur dataset
df.info()
print('Ukuran data ', df.shape)
<class 'pandas.core.frame.DataFrame'>
DatetimeIndex: 1802 entries, 2020-01-01 to 2024-12-06
Data columns (total 6 columns):
# Column Non-Null Count Dtype
--- ------ -------------- -----
0 Open 1802 non-null float64
1 High 1802 non-null float64
2 Low 1802 non-null float64
3 Close 1802 non-null float64
4 Adj Close 1802 non-null float64
5 Volume 1802 non-null int64
dtypes: float64(5), int64(1)
memory usage: 98.5 KB
Ukuran data (1802, 6)
Setelah itu, di sini kita akan menganalisis hubungan antar fitur dalam dataset. Heatmap ini membantu kita memahami korelasi antara kolom-kolom yang ada, apakah ada hubungan yang kuat, lemah, atau tidak ada korelasi sama sekali. Ini dapat memberikan wawasan penting untuk analisis lebih lanjut atau pembuatan model, seperti memilih fitur yang relevan atau mendeteksi multikolinearitas.
correlation_matrix = df.corr()
plt.figure(figsize=(7, 3))
sns.heatmap(correlation_matrix, annot=True, cmap='coolwarm', linewidths=0.5)
plt.title('Heatmap Korelasi Antar Fitur')
plt.show()
![_images/e437f758fa4c84a5fcd10d400e4e5dec718de12611f0219962a507a65066c5d1.png](_images/e437f758fa4c84a5fcd10d400e4e5dec718de12611f0219962a507a65066c5d1.png)
Hasil korelasi pada heatmap ini menunjukkan hubungan antara fitur-fitur dalam data. Nilai korelasi berkisar dari -1 sampai 1, di mana 1 berarti hubungan sangat kuat dan positif, 0 berarti tidak ada hubungan, dan -1 berarti hubungan sangat kuat namun negatif. Pada heatmap ini, terlihat bahwa fitur "Open," "High," "Low," "Close," dan "Adj Close" memiliki korelasi sempurna (1), yang menunjukkan bahwa nilai-nilai ini sangat saling terkait. Namun, fitur "Volume" memiliki korelasi yang lemah (sekitar 0,26-0,27) terhadap fitur-fitur lainnya, yang berarti perubahan pada "Volume" tidak terlalu berhubungan dengan perubahan pada fitur lainnya.
Data Preprocessing#
a. Penghapusan Kolom yang Tidak Relevan dan Verifikasi Dataset#
Menghapus kolom Volume dan Adj Close dari dataset, kolom-kolom tersebut dihilangkan karena mungkin tidak relevan untuk analisis atau pemodelan selanjutnya. Kemudian, kita akan melihat lima baris pertama dari dataset yang telah diperbarui untuk memastikan perubahan yang dilakukan.
df = df.drop(columns=['Volume', 'Adj Close'])
df.head()
Open | High | Low | Close | |
---|---|---|---|---|
Date | ||||
2020-01-01 | 7195 | 7254 | 7175 | 7200 |
2020-01-02 | 7203 | 7212 | 6935 | 6986 |
2020-01-03 | 6984 | 7414 | 6915 | 7345 |
2020-01-04 | 7345 | 7427 | 7310 | 7411 |
2020-01-05 | 7410 | 7544 | 7400 | 7411 |
b. Rekayasa Fitur#
Dalam penelitian ini, tujuan kita adalah memprediksi harga Close pada hari berikutnya, sehingga kita memerlukan variabel baru sebagai target. Fitur ini berguna untuk mengetahui sejauh mana harga saham bisa turun, yang memungkinkan investor untuk membeli aset pada harga yang lebih rendah dan meningkatkan peluang keuntungan ketika harga saham naik kembali.
df['Close Target'] = df['Close'].shift(-1)
df = df[:-1]
df.head()
Open | High | Low | Close | Close Target | |
---|---|---|---|---|---|
Date | |||||
2020-01-01 | 7195 | 7254 | 7175 | 7200 | 6986 |
2020-01-02 | 7203 | 7212 | 6935 | 6986 | 7345 |
2020-01-03 | 6984 | 7414 | 6915 | 7345 | 7411 |
2020-01-04 | 7345 | 7427 | 7310 | 7411 | 7411 |
2020-01-05 | 7410 | 7544 | 7400 | 7411 | 7769 |
Tabel ini menunjukkan data harga saham harian yang mencakup harga pembukaan (Open), harga tertinggi (High), harga terendah (Low), dan harga penutupan (Close). Selain itu, terdapat kolom Close Target yang merupakan prediksi harga penutupan untuk hari berikutnya. Misalnya, pada 2020-01-01, harga penutupan adalah 7200.2, sementara prediksi harga penutupan untuk 2020-01-02 adalah 6985.5, yang lebih rendah dari harga penutupan hari itu.
c. Normalisasi Data#
Melakukan normalisasi data pada fitur dan target bertujuan untuk mengubah nilai-nilai dalam dataset ke rentang yang seragam, biasanya antara 0 dan 1. Dalam kode ini, `MinMaxScaler` digunakan untuk menormalisasi fitur (Open, High, Low, Close) dan target (Close Target). Fitur dinormalisasi menggunakan scaler_features.fit_transform() dan target menggunakan scaler_target.fit_transform(). Hasil normalisasi kemudian digabungkan dengan pd.concat() menjadi satu dataframe df_normalized, yang siap digunakan dalam model machine learning. Normalisasi membantu model belajar lebih efektif dengan skala data yang konsisten.
# Inisialisasi scaler untuk fitur (input) dan target (output)
scaler_features = MinMaxScaler()
scaler_target = MinMaxScaler()
# Normalisasi fitur (Open, High, Low,, 'Close' Close Target-4, Close Target-5)
df_features_normalized = pd.DataFrame(scaler_features.fit_transform(df[['Open', 'High', 'Low', 'Close']]),
columns=['Open', 'High', 'Low', 'Close'],
index=df.index)
# Normalisasi target (Close Target)
df_target_normalized = pd.DataFrame(scaler_target.fit_transform(df[['Close Target']]),
columns=['Close Target'],
index=df.index)
# Gabungkan kembali dataframe yang sudah dinormalisasi
df_normalized = pd.concat([df_features_normalized, df_target_normalized], axis=1)
Modelling#
a. Pembagian Data#
Selanjutnya, melakukan pembagian data menjadi data training dan data testing dengan menggunakan train_test_split, di mana 80% data digunakan untuk training dan 20% untuk testing. Proses ini dilakukan dengan opsi shuffle=False agar data tetap terurut berdasarkan urutan aslinya. Setelah pembagian, data training (X_train dan y_train) digunakan untuk melatih model, sedangkan data testing (X_test dan y_test) digunakan untuk menguji kinerja model yang telah dilatih.
# Mengatur fitur (X) dan target (y)
X = df_normalized[['Open', 'High', 'Low', 'Close']]
y = df_normalized['Close Target']
# Membagi data menjadi training dan testing (60% training, 40% testing)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4, shuffle=False)
b. Penyusunan Model#
Pada tahap ini, dilakukan percobaan dengan menggunakan tiga model utama, yaitu Regresi Linear, Ridge Linear , dan Gradient Boosting. Selain itu, untuk meningkatkan akurasi dan kinerja model, diterapkan juga teknik ensemble dengan metode bagging
# List model regresi
models = {
"Linear Regression": LinearRegression(),
"Ridge Regression": Ridge(alpha=1.0),
"Gradient Boosting" : GradientBoostingRegressor(random_state=32),
}
# Dictionary untuk menyimpan hasil evaluasi
results = {}
# Iterasi setiap model
for name, model in models.items():
# Latih model
model.fit(X_train, y_train)
# Prediksi pada data uji
y_pred = model.predict(X_test)
# Evaluasi
mse = mean_squared_error(y_test, y_pred)
rmse = np.sqrt(mse)
mape = mean_absolute_percentage_error(y_test, y_pred) * 100 # Dalam persen
# Simpan hasil evaluasi
results[name] = {"RMSE": rmse, "MAPE": mape}
# Kembalikan hasil prediksi ke skala asli
y_pred_original = scaler_target.inverse_transform(y_pred.reshape(-1, 1))
y_test_original = scaler_target.inverse_transform(y_test.values.reshape(-1, 1))
# Plot hasil prediksi
plt.figure(figsize=(15, 6))
plt.plot(y_test.index, y_test_original, label="Actual", color="blue")
plt.plot(y_test.index, y_pred_original, label=f"Predicted ({name})", color="red")
# Tambahkan detail plot
plt.title(f'Actual vs Predicted Values ({name})')
plt.xlabel('Date')
plt.ylabel('Harga')
plt.legend()
plt.grid(True)
# Tampilkan plot
plt.show()
# Tampilkan hasil evaluasi
print("HASIL EVALUASI MODEL")
for model, metrics in results.items():
print(f"{model}:\n RMSE: {metrics['RMSE']:.2f}\n MAPE: {metrics['MAPE']:.2f}%\n")
![_images/4c108291c27c1259e778e6159a4e3ac3f3c6e8a72ab3af0c5d1e540c11711c1e.png](_images/4c108291c27c1259e778e6159a4e3ac3f3c6e8a72ab3af0c5d1e540c11711c1e.png)
![_images/f614140f6980c0113faf57595a26c742c5f0ddc2b67cb6cb408a91c34fb408a7.png](_images/f614140f6980c0113faf57595a26c742c5f0ddc2b67cb6cb408a91c34fb408a7.png)
![_images/743447163e3b9c4b39452d08874990584c224c1414dba6087039b57f9b7d2aaf.png](_images/743447163e3b9c4b39452d08874990584c224c1414dba6087039b57f9b7d2aaf.png)
HASIL EVALUASI MODEL
Linear Regression:
RMSE: 0.01
MAPE: 2.01%
Ridge Regression:
RMSE: 0.02
MAPE: 2.21%
Gradient Boosting:
RMSE: 0.06
MAPE: 4.21%
Kesimpulan#
Berdasarkan hasil percobaan dengan beberapa model, metode Linear Regression menunjukkan performa terbaik dengan nilai RMSE sebesar 0.01 dan MAPE sebesar 2.01%.
DEPLOYMENT#
Hasil deployment dapat dilihat melalui tautan berikut: https://huggingface.co/spaces/Alifiacaca/projek1_prediksibtc