1 1. Παρουσίαση του Dataset

Το dataset περιέχει ιστορικές ημερήσιες τιμές της μετοχής της Microsoft (MSFT):

  • Date: Ημερομηνία συναλλαγής
  • Open: Τιμή ανοίγματος
  • High: Υψηλότερη τιμή ημέρας
  • Low: Χαμηλότερη τιμή ημέρας
  • Close: Τιμή κλεισίματος
  • Adj Close: Προσαρμοσμένη τιμή κλεισίματος
  • Volume: Όγκος συναλλαγών
MSFT <- read.csv("MSFT.csv")

#Φόρτωση βιβλιοθηκών
library(ggplot2)   # Για οπτικοποίηση

# Μετατροπή της στήλης Date σε ημερομηνία
MSFT$Date <- as.Date(MSFT$Date)
# Τα δεδομένα
head(MSFT)
##         Date     Open     High      Low    Close Adj.Close     Volume
## 1 1986-03-13 0.088542 0.101563 0.088542 0.097222  0.061434 1031788800
## 2 1986-03-14 0.097222 0.102431 0.097222 0.100694  0.063628  308160000
## 3 1986-03-17 0.100694 0.103299 0.100694 0.102431  0.064725  133171200
## 4 1986-03-18 0.102431 0.103299 0.098958 0.099826  0.063079   67766400
## 5 1986-03-19 0.099826 0.100694 0.097222 0.098090  0.061982   47894400
## 6 1986-03-20 0.098090 0.098090 0.094618 0.095486  0.060337   58435200
# Βασικά στατιστικά
summary(MSFT[, c("Open", "High", "Low", "Close", "Volume")])
##       Open                High                Low           
##  Min.   :  0.08854   Min.   :  0.09201   Min.   :  0.08854  
##  1st Qu.:  4.05078   1st Qu.:  4.10205   1st Qu.:  4.02734  
##  Median : 26.82000   Median : 27.10000   Median : 26.52000  
##  Mean   : 41.32494   Mean   : 41.76089   Mean   : 40.87849  
##  3rd Qu.: 40.03500   3rd Qu.: 40.44375   3rd Qu.: 39.50000  
##  Max.   :344.62000   Max.   :349.67001   Max.   :342.20001  
##      Close               Volume         
##  Min.   :  0.09028   Min.   :2.304e+06  
##  1st Qu.:  4.07520   1st Qu.:3.461e+07  
##  Median : 26.84000   Median :5.203e+07  
##  Mean   : 41.33563   Mean   :5.875e+07  
##  3rd Qu.: 39.93750   3rd Qu.:7.265e+07  
##  Max.   :343.10998   Max.   :1.032e+09

2 2. Προετοιμασία Δεδομένων για Συσταδοποίηση

Για τη συσταδοποίηση θα χρησιμοποιήσουμε τρία χαρακτηριστικά που περιγράφουν την κίνηση της μετοχής κάθε ημέρα:

  • daily_return: Ημερήσια απόδοση (%)
  • volatility: Εύρος τιμής ημέρας (High - Low)
  • volume_scaled: Κανονικοποιημένος όγκος
# Υπολογισμός χαρακτηριστικών
MSFT$daily_return <- c(NA, diff(MSFT$Close) / MSFT$Close[-nrow(MSFT)] * 100)
MSFT$volatility   <- MSFT$High - MSFT$Low

# Αφαίρεση NA (πρώτη γραμμή)
MSFTclean <- MSFT[!is.na(MSFT$daily_return), ]

# Επιλογή χαρακτηριστικών
features <- MSFTclean[, c("daily_return", "volatility", "Volume")]

# Κανονικοποίηση (scale) για την συσταδοποίηση
features_scaled <- scale(features)

cat("Διαστάσεις δεδομένων για clustering:", dim(features_scaled), "\n")
## Διαστάσεις δεδομένων για clustering: 9082 3

3 3. Ιεραρχική Συσταδοποίηση (Hierarchical Clustering)

Η ιεραρχική συσταδοποίηση ομαδοποιεί τις παρατηρήσεις σταδιακά, χτίζοντας ένα δέντρο (dendogram). Λόγω του μεγάλου αριθμού παρατηρήσεων, χρησιμοποιούμε δείγμα 300 ημερών για να είναι το δέντρο αναγνώσιμο.

# Δείγμα 300 παρατηρήσεων για το dendogram
set.seed(42)
sample_idx <- sample(nrow(features_scaled), 300)
sample_data <- features_scaled[sample_idx, ]

# Υπολογισμός αποστάσεων (Euclidean)
dist_matrix <- dist(sample_data, method = "euclidean")

# Ιεραρχική συσταδοποίηση με μέθοδο Ward
hc <- hclust(dist_matrix, method = "ward.D2")

# Dendogram
plot(hc,
     main  = "Ιεραρχική Συσταδοποίηση MSFT",
     xlab  = "Παρατηρήσεις",
     ylab  = "Απόσταση",
     labels = FALSE,   # δεν θα φαίνονται ετικέτες λόγω πολλώ παρατηρήσεων
     cex.main = 1.2)

# Προσθήκη ορίου για 3 συστάδες
rect.hclust(hc, k = 3, border = c("red", "blue", "green"))
legend("topright",
       legend = c("Συστάδα 1", "Συστάδα 2", "Συστάδα 3"),
       fill   = c("red", "blue", "green"),
       cex    = 0.8)

# Κόβουμε το δέντρο σε 3 συστάδες
hc_clusters <- cutree(hc, k = 3)

# Κατανομή παρατηρήσεων ανά συστάδα
table(hc_clusters)
## hc_clusters
##   1   2   3 
## 265  17  18
# Οπτικοποίηση συστάδων (daily_return & volatility)
plot(sample_data[, "daily_return"],
     sample_data[, "volatility"],
     col  = hc_clusters,
     pch  = 19,
     cex  = 0.6,
     main = "Ιεραρχική Συσταδοποίηση: Απόδοση vs Μεταβλητότητα",
     xlab = "Ημερήσια Απόδοση (scaled)",
     ylab = "Μεταβλητότητα (scaled)")

legend("topright",
       legend = paste("Συστάδα", 1:3),
       col    = 1:3,
       pch    = 19,
       cex    = 0.8)

3.1 Σχολιασμός

Από το δενδρλογραμμα και το scatter plot παρατηρούμε ότι:

  • Συστάδα 1 (Κόκκινη): Ημέρες με μικρή κίνηση άρα χαμηλή μεταβλητότητα και απόδοση κοντά στο 0.
  • Συστάδα 2 (Μαύρη/Μπλε): Ημέρες με θετικές αποδόσεις άρα ανοδικές μέρες της μετοχής.
  • Συστάδα 3 (Πράσινη): Ημέρες με ακραία κίνηση πχ.υψηλή μεταβλητότητα ή μεγάλες πτώσεις άρα περίοδοι αστάθειας.

4 4. Συσταδοποίηση με K-Means

Ο αλγόριθμος K-means χωρίζει τα δεδομένα σε k συστάδες ελαχιστοποιώντας την διακύμανση. Εφαρμόζω K-means σε όλο το dataset.

4.1 4.1 Επιλογή Αριθμού Συστάδων (Elbow Method)

# Elbow method: υπολογισμός WSS για k = 1 έως 8
set.seed(42)
wss <- sapply(1:8, function(k) {
  kmeans(features_scaled, centers = k, nstart = 10)$tot.withinss
})

# Γράφημα Elbow
plot(1:8, wss,
     type  = "b",
     pch   = 19,
     col   = "steelblue",
     main  = "Elbow Method",
     xlab  = "Αριθμός Συστάδων (k)",
     ylab  = "Συνολική Διακύμανση (WSS)")

abline(v = 3, lty = 2, col = "red")
text(3.2, max(wss)*0.9, "k=3", col = "red")

4.2 4.2 K-Means (k=3)

set.seed(42)
km <- kmeans(features_scaled, centers = 3, nstart = 25)

# Αποτελέσματα
cat("Κατανομή παρατηρήσεων ανά συστάδα:\n")
## Κατανομή παρατηρήσεων ανά συστάδα:
print(table(km$cluster))
## 
##    1    2    3 
## 1645 6889  548
cat("\nΜέσοι όροι (scaled) ανά συστάδα:\n")
## 
## Μέσοι όροι (scaled) ανά συστάδα:
print(round(km$centers, 3))
##   daily_return volatility Volume
## 1        0.937     -0.200  1.269
## 2       -0.220     -0.204 -0.255
## 3       -0.049      3.169 -0.605
# Οπτικοποίηση K-Means
plot(features_scaled[, "daily_return"],
     features_scaled[, "volatility"],
     col  = km$cluster,
     pch  = 19,
     cex  = 0.4,
     main = "K-Means Απόδοση vs Μεταβλητότητα",
     xlab = "Ημερήσια Απόδοση (scaled)",
     ylab = "Μεταβλητότητα (scaled)")

# Κέντρα συστάδων
points(km$centers[, "daily_return"],
       km$centers[, "volatility"],
       col = 1:3,
       pch = 8,
       cex = 2.5,
       lwd = 2)

legend("topright",
       legend = c(paste("Συστάδα", 1:3), "Κέντρα"),
       col    = c(1:3, 1),
       pch    = c(19, 19, 19, 8),
       cex    = 0.8)

# Κατανομή ημερήσιας απόδοσης ανά συστάδα
MSFTclean$cluster_km <- km$cluster

boxplot(daily_return ~ cluster_km,
        data  = MSFTclean,
        col   = c("salmon", "lightblue", "lightgreen"),
        main  = "Ημερήσια Απόδοση ανά Συστάδα (K-Means)",
        xlab  = "Συστάδα",
        ylab  = "Ημερήσια Απόδοση (%)",
        names = paste("Συστάδα", 1:3))

abline(h = 0, lty = 2, col = "gray50")

4.3 Σχολιασμός:

Τα αποτελέσματα του K-means έχουν τρεις ξεκάθαρες ομάδες συμπεριφοράς της μετοχής:

  • Συστάδα με αρνητικές αποδόσεις: Ημέρες πτώσης
  • Συστάδα με ουδέτερες/μικρές αποδόσεις: Η πλειονότητα των ημερών
  • Συστάδα με θετικές αποδόσεις: Ημέρες ανόδου

5 5. Σύγκριση Μεθόδων & Συμπεράσματα

km_sample <- km$cluster[sample_idx]

cat("Ιεραρχική vs K-Means:\n")
## Ιεραρχική vs K-Means:
print(table(Hierarchical = hc_clusters, KMeans = km_sample))
##             KMeans
## Hierarchical   1   2   3
##            1  44 217   4
##            2  12   5   0
##            3   0   4  14

5.1 Συμπεράσματα:

Και οι δύο μέθοδοι (ιεραρχική και K-means) κατέληξαν σε παρόμοια αποτελέσματα, επιβεβαιώνοντας την αξιοπιστία της ανάλυσης. Η K-means είναι πιο αποδοτική για μεγάλα datasets, ενώ η ιεραρχική παρέχει το πλεονέκτημα της οπτικής αναπαράστασης μέσω του dendogram.