Harga saham merupakan data time series yang bersifat dinamis, non-linier, dan dipengaruhi oleh berbagai faktor ekonomi maupun sentimen pasar. Dalam analisis time series, salah satu langkah penting sebelum pemodelan lanjutan adalah dekomposisi data untuk memahami struktur dasar yang membentuk pergerakan harga.
Pada artikel ini, dilakukan analisis dekomposisi harga penutupan saham BBCA periode 2015–2025 menggunakan dua pendekatan, yaitu Additive Decomposition klasik dan STL (Seasonal-Trend decomposition using LOESS). Tujuannya adalah membandingkan karakteristik hasil dekomposisi dan menentukan pendekatan yang lebih sesuai untuk data saham.
Apa itu Dekomposisi Time Series?
Dekomposisi time series memisahkan data menjadi tiga komponen utama:
- Trend (T): arah pergerakan jangka panjang
- Seasonal (S): pola berulang dalam periode tertentu
- Residual/Error (R): fluktuasi acak yang tidak dapat dijelaskan
Secara umum, model additive dituliskan sebagai:
Hasil Additive Decomposition
Komponen Trend
Hasil additive decomposition menunjukkan adanya tren naik jangka panjang pada saham BBCA. Namun, pola tren terlihat relatif kaku dan kurang adaptif terhadap perubahan ekstrem, terutama pada periode krisis tahun 2020.
Komponen Musiman
Komponen musiman pada model additive tampak statis dan berulang secara kaku, dengan amplitudo yang relatif konstan sepanjang waktu. Hal ini mengindikasikan bahwa model additive memaksakan adanya pola musiman, meskipun pada data saham pola tersebut tidak selalu nyata.
Komponen Residual
Residual dari additive decomposition menunjukkan variasi yang cukup besar dan mengandung banyak lonjakan ekstrem. Ini menandakan bahwa sebagian besar volatilitas pasar belum terakomodasi dengan baik oleh model.

Gambar-1 Hasil Dekomposisi dengan Metode Additive
Hasil STL Decomposition
Komponen Trend
Berbeda dengan additive, STL menghasilkan tren yang lebih halus dan adaptif. Perubahan rezim pasar seperti krisis COVID-19 dan fase pemulihan pasca-2020 dapat terlihat lebih jelas dan realistis.
Komponen Musiman
Komponen musiman pada STL bersifat dinamis, dengan amplitudo yang berubah mengikuti volatilitas pasar. Pada konteks saham, komponen ini lebih tepat dipahami sebagai fluktuasi jangka pendek daripada musiman kalender yang kaku.
Komponen Residual
Residual hasil STL memiliki variasi yang lebih terkendali dan lebih mendekati noise acak. Hal ini menunjukkan bahwa STL mampu mengekstraksi informasi sistematis dengan lebih baik dibanding additive decomposition.

Gambar-1 Hasil Dekomposisi dengan Metode STL
Perbandingan Additive vs STL
| Aspek | Additive Decomposition | STL Decomposition |
|---|---|---|
| Bentuk model | Additive statis | Additive adaptif |
| Estimasi tren | Kurang halus | Halus dan fleksibel |
| Pola musiman | Kaku dan konstan | Dinamis dan berubah |
| Sensitivitas terhadap outlier | Tinggi | Rendah (robust) |
| Respons terhadap shock pasar | Lemah | Baik |
| Variansi residual | Besar | Lebih kecil |
| Cocok untuk data saham | Kurang sesuai | Sangat sesuai |
| Kelayakan untuk riset | Terbatas | Direkomendasikan |
Secara visual maupun konseptual, STL memberikan hasil yang lebih realistis untuk data keuangan yang volatil.
Kekuatan Tren dan Musiman
Untuk mengukur dominasi masing-masing komponen, digunakan pendekatan berbasis varians:
Trend Strength (TB) mengukur kontribusi tren terhadap variasi data
Seasonal Strength (SB) mengukur kontribusi komponen musiman
- di mana: Var(Rt) adalah varians komponen residual
- Var(Tt + Rt) adalah varians gabungan komponen tren dan residual
- Var(St + Rt) adalah varians gabungan komponen sesional dan residual
| Additive | TSL | |
| TB | 0.997441 | 0.998064 |
| SB | 0.007933 | 0.308799 |
Hasil analisis menunjukkan bahwa TB jauh lebih besar dibanding SB, menandakan bahwa pergerakan harga saham BBCA lebih didominasi oleh tren jangka panjang dibandingkan pola musiman.
Implikasi untuk Machine Learning
Hasil dekomposisi ini memiliki implikasi penting untuk pemodelan lanjutan:
- Trend STL sangat cocok dijadikan fitur utama untuk model RNN, LSTM, atau GRU
- Komponen musiman STL dapat digunakan sebagai fitur tambahan
- Residual sebaiknya tidak digunakan langsung karena bersifat noise
Kesimpulan
Dari analisis yang dilakukan, dapat disimpulkan bahwa:
- Additive decomposition kurang mampu merepresentasikan karakteristik data saham yang volatil.
- STL decomposition memberikan pemisahan komponen yang lebih adaptif dan robust.
- Harga saham BBCA periode 2015–2025 didominasi oleh tren jangka panjang, sementara musiman relatif lemah.
- STL merupakan pendekatan yang lebih tepat sebagai tahap pra-pemrosesan sebelum pemodelan machine learning.
Kode Python
Install Paket Statsmodels
pip install statsmodels –quiet
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sn
import matplotlib.ticker as mticker
from statsmodels.tsa.seasonal import seasonal_decompose
from statsmodels.tsa.seasonal import STL
df=pd.read_csv('bbca_close_2015-2025.csv')
df.set_index('Date', inplace=True)
df.index=pd.to_datetime(df.index)
series=df.Close
decomp_add=seasonal_decompose(series,period=30)
season_add=decomp_add.seasonal
trend_add=decomp_add.trend
residu_add=decomp_add.resid
observer_add=decomp_add.observed
fig, axs=plt.subplots(2,2, figsize=(13,8))
title="Additive Decomposition\n Harga Penutupan Saham BBCA\n Periode 2015–2025"
set_title={'Time Series':{'color':'royalblue','data':series},
'Trend':{'color':'green','data':trend_add},
'Komponen Musiman':{'color':'indigo','data':season_add},
'Komponen Residu/Error':{'color':'darkred','data':residu_add}
}
z=zip(axs.flatten(),set_title.items())
for ax,(t,val) in z:
ax.set_xlabel('Tahun', fontsize=8, fontweight='bold',color='grey')
ax.set_ylabel('Harga Penutupan', fontsize=8, fontweight='bold',color='grey' )
ax.tick_params(axis='y', labelsize=8, colors='blue',grid_color='grey', grid_alpha=0.2 )
ax.tick_params(axis='x', labelsize=8, colors='blue',grid_color='b', grid_alpha=0.2 )
ax.set_title(f"{t} {title}",fontdict={'fontsize':12, 'fontweight':'bold', 'color':val['color']})
ax.plot(val['data'], color=val['color'])
plt.tight_layout()
plt.show()
def decom_tbsb(t,r,s):
df_tb = pd.concat([t, r,s], axis=1)
df_tb.columns = ['trend', 'resid','sesion']
df_tb = df_tb.dropna()
var_resid = np.var(df_tb['resid'], ddof=1)
var_trend_resid = np.var(
df_tb['trend'] + df_tb['resid'],
ddof=1
)
var_sesion_resid=np.var(df_tb['sesion']+df_tb['resid'], ddof=1)
TB = 1 - (var_resid / var_trend_resid)
SB = 1 - (var_resid / var_sesion_resid)
return TB,SB
tb_add,sb_add=decom_tbsb(trend_add,residu_add,season_add)
print(f"Strength of Trend : {tb_add:.5f}")
print(f"Strength of Trend : {sb_add:.5f}")
stl=STL(series,period=30)
res = stl.fit()
season_stl=res.seasonal
trend_stl=res.trend
residu_stl=res.resid
observer_stl=res.observed
fig, axs=plt.subplots(2,2, figsize=(13,8))
title="STL Decomposition\n Harga Penutupan Saham BBCA\n Periode 2015–2025"
set_title={'Time Series':{'color':'royalblue','data':series},
'Trend':{'color':'green','data':trend_stl},
'Komponen Musiman':{'color':'indigo','data':season_stl},
'Komponen Residu/Error':{'color':'darkred','data':residu_stl}
}
z=zip(axs.flatten(),set_title.items())
for ax,(t,val) in z:
ax.set_xlabel('Tahun', fontsize=8, fontweight='bold',color='grey')
ax.set_ylabel('Harga Penutupan', fontsize=8, fontweight='bold',color='grey' )
ax.tick_params(axis='y', labelsize=8, colors='blue',grid_color='grey', grid_alpha=0.2 )
ax.tick_params(axis='x', labelsize=8, colors='blue',grid_color='b', grid_alpha=0.2 )
ax.set_title(f"{t} {title}",fontdict={'fontsize':12, 'fontweight':'bold', 'color':val['color']})
ax.plot(val['data'], color=val['color'])
plt.tight_layout()
plt.show()
tb_stl,sb_stl=decom_tbsb(trend_stl,residu_stl,season_stl)
print(f"Strength of Trend : {tb_stl:.5f}")
print(f"Strength of Trend : {sb_stl:.5f}")
model_decomp={'Additive':{'tb':tb_add,'sb':sb_add},'STL':{'tb':tb_stl,'sb':sb_stl}}
pd.DataFrame(model_decomp)
