Dokumen ini mengembangkan analisis di Excel (statistik deskriptif, histogram, dan ANOVA satu faktor) ke dalam R. Alur yang diikuti:
Letakkan file JKSE_2026_Aug_Oct.csv di folder yang sama
dengan file .Rmd ini, lalu klik Knit.
jkse <- read.csv("JKSE_2026_Aug_Oct.csv", check.names = FALSE)
jkse$Date <- as.Date(jkse$Date)
jkse <- jkse[order(jkse$Date), ] # urut dari terlama ke terbaru
rownames(jkse) <- NULL
high <- jkse$High
low <- jkse$Low
n <- nrow(jkse)
head(jkse)
Data berisi 58 hari perdagangan dari 03 August 2026 sampai 23 October 2026. Volume pada 23 Oktober 2026 kosong dan tidak dipakai dalam analisis ini.
Fungsi SKEW() dan KURT() di Excel memakai
koreksi sampel, sehingga dibuat ulang agar hasilnya identik.
KURT() menghasilkan excess kurtosis (distribusi
normal = 0).
skew_excel <- function(x) {
n <- length(x); m <- mean(x); s <- sd(x)
n / ((n - 1) * (n - 2)) * sum(((x - m) / s)^3)
}
kurt_excel <- function(x) {
n <- length(x); m <- mean(x); s <- sd(x)
n * (n + 1) / ((n - 1) * (n - 2) * (n - 3)) * sum(((x - m) / s)^4) -
3 * (n - 1)^2 / ((n - 2) * (n - 3))
}
mode_excel <- function(x) {
tb <- table(x)
if (max(tb) == 1) NA else as.numeric(names(tb)[which.max(tb)])
}
deskriptif <- function(x) {
c(Mean = mean(x), `Standard Error` = sd(x) / sqrt(length(x)),
Median = median(x), Mode = mode_excel(x), `Standard Deviation` = sd(x),
`Sample Variance` = var(x), Kurtosis = kurt_excel(x), Skewness = skew_excel(x),
Range = diff(range(x)), Minimum = min(x), Maximum = max(x),
Sum = sum(x), Count = length(x))
}
tabel_deskriptif <- data.frame(High = deskriptif(high), Low = deskriptif(low))
knitr::kable(round(tabel_deskriptif, 4), format.args = list(big.mark = ","))
| High | Low | |
|---|---|---|
| Mean | 6,284.8924 | 6,179.4345 |
| Standard Error | 51.1233 | 54.9295 |
| Median | 6,389.4550 | 6,284.5150 |
| Mode | NA | NA |
| Standard Deviation | 389.3436 | 418.3308 |
| Sample Variance | 151,588.4477 | 175,000.6227 |
| Kurtosis | 2.2780 | 2.2172 |
| Skewness | -1.6208 | -1.6157 |
| Range | 1,699.6300 | 1,734.7800 |
| Minimum | 5,012.8700 | 4,907.3700 |
| Maximum | 6,712.5000 | 6,642.1500 |
| Sum | 364,523.7600 | 358,407.2000 |
| Count | 58.0000 | 58.0000 |
Skewness kedua variabel sekitar -1,6 (condong ke
kiri) dan excess kurtosis sekitar 2,2 (ekor lebih tebal
dari normal). Mode bernilai NA karena tidak ada nilai yang
berulang (di Excel muncul sebagai #N/A).
long <- data.frame(
Date = rep(jkse$Date, 2),
Harga = c(high, low),
Group = factor(rep(c("High", "Low"), each = n), levels = c("High", "Low"))
)
ggplot(long, aes(Date, Harga, colour = Group)) +
geom_line(linewidth = 0.9) +
labs(title = "High dan Low JKSE", x = NULL, y = "Indeks") +
theme_minimal(base_size = 12)
bins <- seq(4750, 7000, by = 250)
ggplot(long, aes(Harga, fill = Group)) +
geom_histogram(breaks = bins, colour = "white") +
facet_wrap(~ Group) +
labs(title = "Histogram High dan Low (bin 250)", x = "Indeks", y = "Frekuensi") +
theme_minimal(base_size = 12) + theme(legend.position = "none")
Tabel frekuensi (setara Analysis ToolPak > Histogram; setiap bin berarti nilai ≤ batas atas):
frekuensi <- function(x) as.numeric(table(cut(x, c(-Inf, 5000, seq(5250, 6750, 250), Inf))))
tabel_bin <- data.frame(
Bin = c(seq(5000, 6750, 250), "More"),
High = frekuensi(high),
Low = frekuensi(low)
)
knitr::kable(tabel_bin)
| Bin | High | Low |
|---|---|---|
| 5000 | 0 | 2 |
| 5250 | 1 | 3 |
| 5500 | 5 | 1 |
| 5750 | 0 | 0 |
| 6000 | 2 | 7 |
| 6250 | 12 | 11 |
| 6500 | 17 | 25 |
| 6750 | 21 | 9 |
| More | 0 | 0 |
ggplot(long, aes(sample = Harga)) +
stat_qq() + stat_qq_line(colour = "red") +
facet_wrap(~ Group) +
labs(title = "Q-Q Plot High dan Low", x = "Kuantil teoritis", y = "Kuantil sampel") +
theme_minimal(base_size = 12)
Titik-titik yang menyimpang dari garis merah, terutama di ujung kiri, menunjukkan data tidak normal.
Hipotesis: H₀ = data berdistribusi normal. H₀ ditolak jika p-value ≤ 0,05.
Uji Jarque-Bera dihitung dari skewness (S) dan excess kurtosis (K):
\[JB = \frac{n}{6}\left(S^2 + \frac{K^2}{4}\right)\]
Statistik ini mengikuti distribusi chi-square dengan df = 2, karena ada dua komponen yang diuji (skewness dan kurtosis).
jarque_bera <- function(x) {
n <- length(x)
S <- skew_excel(x); K <- kurt_excel(x)
jb <- n / 6 * (S^2 + K^2 / 4)
c(JB = jb, df = 2, `p-value` = pchisq(jb, df = 2, lower.tail = FALSE))
}
hasil_norm <- data.frame(
Variabel = c("High", "Low"),
Shapiro_W = c(shapiro.test(high)$statistic, shapiro.test(low)$statistic),
Shapiro_p = c(shapiro.test(high)$p.value, shapiro.test(low)$p.value),
JB = c(jarque_bera(high)["JB"], jarque_bera(low)["JB"]),
JB_p = c(jarque_bera(high)["p-value"], jarque_bera(low)["p-value"])
)
knitr::kable(hasil_norm, digits = c(0, 4, 10, 2, 10))
| Variabel | Shapiro_W | Shapiro_p | JB | JB_p |
|---|---|---|---|---|
| High | 0.8202 | 6.287e-07 | 37.93 | 5.8e-09 |
| Low | 0.8191 | 5.907e-07 | 37.11 | 8.7e-09 |
Nilai kritis chi-square (df = 2, α = 5%) adalah 5.99.
Kesimpulan: JB High = 37.93 dan JB Low = 37.11, keduanya jauh di atas nilai kritis, dan uji Shapiro-Wilk juga memberi p-value jauh di bawah 0,05. Jadi High dan Low tidak berdistribusi normal.
Hipotesis: H₀ = varians kedua kelompok sama.
var.test(high, low) # F-test (setara F-Test Excel)
##
## F test to compare two variances
##
## data: high and low
## F = 0.86622, num df = 57, denom df = 57, p-value = 0.5895
## alternative hypothesis: true ratio of variances is not equal to 1
## 95 percent confidence interval:
## 0.5127044 1.4634772
## sample estimates:
## ratio of variances
## 0.8662166
bartlett.test(Harga ~ Group, data = long)
##
## Bartlett test of homogeneity of variances
##
## data: Harga by Group
## Bartlett's K-squared = 0.29113, df = 1, p-value = 0.5895
# Levene / Brown-Forsythe (berbasis median) tanpa paket tambahan
long$dev <- abs(long$Harga - ave(long$Harga, long$Group, FUN = median))
summary(aov(dev ~ Group, data = long))
## Df Sum Sq Mean Sq F value Pr(>F)
## Group 1 11067 11067 0.113 0.738
## Residuals 114 11213835 98367
P-value ketiga uji di atas > 0,05, sehingga asumsi homogenitas varians terpenuhi.
Hasil berikut setara dengan Data Analysis > Anova: Single Factor di Excel.
model <- aov(Harga ~ Group, data = long)
tabel_anova <- summary(model)
tabel_anova
## Df Sum Sq Mean Sq F value Pr(>F)
## Group 1 322520 322520 1.975 0.163
## Residuals 114 18615577 163295
ss <- tabel_anova[[1]]$`Sum Sq`
eta2 <- ss[1] / sum(ss)
fcrit <- qf(0.95, 1, nrow(long) - 2)
F hitung = 1.975, F kritis = 3.924, p-value = 0.1626, dan eta squared = 0.017. Angka-angka ini sama dengan hasil di Excel.
Karena F hitung < F kritis (p > 0,05), ANOVA menyimpulkan tidak ada perbedaan rata-rata antara High dan Low. Namun kesimpulan ini tidak dapat dipercaya, karena:
| Masalah | Alternatif |
|---|---|
| Tidak normal | Kruskal-Wallis |
| Varians tidak homogen | ANOVA Welch |
| Data berpasangan | Paired t-test / Wilcoxon signed-rank |
kruskal.test(Harga ~ Group, data = long)
##
## Kruskal-Wallis rank sum test
##
## data: Harga by Group
## Kruskal-Wallis chi-squared = 3.7349, df = 1, p-value = 0.05329
oneway.test(Harga ~ Group, data = long, var.equal = FALSE)
##
## One-way analysis of means (not assuming equal variances)
##
## data: Harga and Group
## F = 1.9751, num df = 1.00, denom df = 113.42, p-value = 0.1626
t.test(high, low, paired = TRUE)
##
## Paired t-test
##
## data: high and low
## t = 16.261, df = 57, p-value < 2.2e-16
## alternative hypothesis: true mean difference is not equal to 0
## 95 percent confidence interval:
## 92.47114 118.44472
## sample estimates:
## mean difference
## 105.4579
wilcox.test(high, low, paired = TRUE, exact = FALSE)
##
## Wilcoxon signed rank test with continuity correction
##
## data: high and low
## V = 1711, p-value = 3.599e-11
## alternative hypothesis: true location shift is not equal to 0
selisih <- high - low
Rata-rata selisih harian (High − Low) adalah 105.5 poin, dengan Cohen’s d berpasangan = 2.14. Kedua uji berpasangan memberi p-value sangat kecil, jadi High secara signifikan lebih tinggi daripada Low. Ini berbeda dengan kesimpulan ANOVA dan lebih masuk akal, karena High memang selalu ≥ Low pada hari yang sama.
Harga bersifat tren sehingga hampir selalu gagal uji normalitas. Analisis yang lebih bermakna dilakukan pada log return harian harga penutupan (Close).
jkse$Return <- c(NA, diff(log(jkse$Close)))
ret <- na.omit(jkse$Return)
ringkas <- c(n = length(ret), Mean = mean(ret), SD = sd(ret),
Skewness = skew_excel(ret), Kurtosis = kurt_excel(ret))
round(ringkas, 5)
## n Mean SD Skewness Kurtosis
## 57.00000 -0.00248 0.02131 -3.00718 18.51988
shapiro.test(ret)
##
## Shapiro-Wilk normality test
##
## data: ret
## W = 0.71449, p-value = 3.221e-09
round(jarque_bera(ret), 6)
## JB df p-value
## 900.5011 2.0000 0.0000
ggplot(data.frame(Return = ret), aes(Return)) +
geom_histogram(aes(y = after_stat(density)), bins = 15,
fill = "steelblue", colour = "white") +
stat_function(fun = dnorm, args = list(mean = mean(ret), sd = sd(ret)),
colour = "red", linewidth = 1) +
labs(title = "Distribusi return harian JKSE vs kurva normal",
x = "Log return", y = "Densitas") +
theme_minimal(base_size = 12)
Return harian juga tidak normal: skewness -3.01 dan excess kurtosis 18.5 menunjukkan ekor yang sangat tebal. Penyebabnya adalah penurunan tajam pada pertengahan Oktober 2026 (misalnya 16 Oktober, saat Close turun dari 5.863,78 ke 5.185,10). Hal ini umum pada return saham.
sessionInfo()
## R version 4.5.1 (2025-06-13 ucrt)
## Platform: x86_64-w64-mingw32/x64
## Running under: Windows 11 x64 (build 26200)
##
## Matrix products: default
## LAPACK version 3.12.1
##
## locale:
## [1] LC_COLLATE=English_Indonesia.utf8 LC_CTYPE=English_Indonesia.utf8
## [3] LC_MONETARY=English_Indonesia.utf8 LC_NUMERIC=C
## [5] LC_TIME=English_Indonesia.utf8
##
## time zone: Asia/Jakarta
## tzcode source: internal
##
## attached base packages:
## [1] stats graphics grDevices utils datasets methods base
##
## other attached packages:
## [1] ggplot2_4.0.0
##
## loaded via a namespace (and not attached):
## [1] vctrs_0.6.5 cli_3.6.5 knitr_1.50 rlang_1.1.6
## [5] xfun_0.53 generics_0.1.4 S7_0.2.0 jsonlite_2.0.0
## [9] labeling_0.4.3 glue_1.8.0 htmltools_0.5.8.1 sass_0.4.10
## [13] scales_1.4.0 rmarkdown_2.29 grid_4.5.1 tibble_3.3.0
## [17] evaluate_1.0.5 jquerylib_0.1.4 fastmap_1.2.0 yaml_2.3.10
## [21] lifecycle_1.0.4 compiler_4.5.1 dplyr_1.1.4 RColorBrewer_1.1-3
## [25] pkgconfig_2.0.3 rstudioapi_0.17.1 farver_2.1.2 digest_0.6.37
## [29] R6_2.6.1 tidyselect_1.2.1 pillar_1.11.1 magrittr_2.0.4
## [33] bslib_0.9.0 withr_3.0.2 tools_4.5.1 gtable_0.3.6
## [37] cachem_1.1.0