PCA στα δεδομένα απόδοσης μετοχών S&P 500

1
PCA στα δεδομένα απόδοσης μετοχών S&P 500

Αυτή η ανάρτηση είναι μια διασκεδαστική άσκηση για την εφαρμογή PCA (τα περισσότερα στο πλαίσιο tidyverse) σε δεδομένα μετοχών από εταιρείες του δείκτη S&P 500. Με την PCA σε δεδομένα μετοχών από τον S&P 500, μπορούμε ενδεχομένως να κάνουμε πολλά ενδιαφέροντα πράγματα, αλλά θα επικεντρωθούμε σε πολύ απλά πράγματα και θα προσπαθήσουμε να δούμε εάν η PCA αποτυπώνει τις γενικές τάσεις της εταιρείας από τα αποτελέσματα της PCA.

Θα χρησιμοποιήσουμε το πακέτο Tidyquant R για να αποκτήσουμε πρόσβαση σε δεδομένα τιμών μετοχών χρησιμοποιώντας το R και θα χρησιμοποιήσουμε το prcomp() για να εκτελέσουμε PCA χρησιμοποιώντας το πλαίσιο tidyverse με τη βοήθεια του πακέτου σκούπας.

Θα ξεκινήσουμε με τη λήψη ημερήσιων δεδομένων τιμών μετοχών για περίπου 500 εταιρείες στον χρηματιστηριακό δείκτη S&P 500 για το έτος 2022. Στη συνέχεια θα εξερευνήσουμε λίγο τα δεδομένα και θα υπολογίσουμε τις ημερήσιες αποδόσεις μετοχών για κάθε εταιρεία.

Στη συνέχεια, θα προχωρήσουμε και θα εφαρμόσουμε PCA στα ημερήσια δεδομένα επιστροφής για το έτος 2022 και θα προσπαθήσουμε να κατανοήσουμε τους υπολογιστές.

Αρχικά, ας φορτώσουμε τα πακέτα που χρειάζονται.


library(tidyquant)
library(broom)
library(tidyverse)
theme_set(theme_bw(16))

Εταιρείες στον δείκτη S&P 500

Ο δείκτης S&P 500 περιέχει συνήθως περίπου 500 εταιρείες στον δείκτη του. Στο τέλος του 2022, υπάρχουν 503 εταιρείες στον δείκτη S&P 500.

Μπορούμε να λάβουμε τη λίστα με όλες τις εταιρείες στον δείκτη S&P 500, χρησιμοποιώντας τη συνάρτηση tq_index() του tidyquant. Καθορίζουμε το όνομα του ευρετηρίου, εδώ „SP500“ ως το όρισμα στο tq_index() του tidyquant. Μας δίνει λεπτομερείς πληροφορίες σχετικά με τις εταιρείες του δείκτη S&P 500, συμπεριλαμβανομένης της επωνυμίας μετοχών, της βαρύτητας των εταιρειών στον δείκτη όπως μετράται με βάση την κεφαλαιοποίηση της αγοράς και τον ευρύ τομέα στον οποίο ανήκει.


# get S&P 500 index coopanies info
tq_index("SP500") %>% head()

## Getting holdings for SP500
## # A tibble: 10 × 8
##    symbol company      identifier sedol weight sector shares_held local_currency
##    <chr>  <chr>        <chr>      <chr>  <dbl> <chr>        <dbl> <chr>         
##  1 AAPL   Apple Inc.   03783310   2046… 0.0587 Infor…   165455870 USD           
##  2 MSFT   Microsoft C… 59491810   2588… 0.0520 Infor…    82480670 USD           
##  3 AMZN   Amazon.com … 02313510   2000… 0.0232 Consu…    98203210 USD           
##  4 BRK.B  Berkshire H… 08467070   2073… 0.0177 Finan…    19935340 USD           
##  5 GOOGL  Alphabet In… 02079K30   BYVY… 0.0162 Commu…    66088936 USD           
##  6 JNJ    Johnson & J… 47816010   2475… 0.0147 Healt…    28960104 USD           

Ας αποθηκεύσουμε τις πληροφορίες για τις εταιρείες του S&P 500 σε μια μεταβλητή για μελλοντική χρήση.


stock_list_tbl <- tq_index("SP500") %>%
  arrange(symbol) 

Εξερευνώντας λίγο τα δεδομένα εταιρειών του S&P 500, ας δούμε τον αριθμό των εταιρειών σε κάθε τομέα χρησιμοποιώντας ένα απλό barplot.


stock_list_tbl %>% 
  count(sector, sort=TRUE) %>%
  ggplot(aes(y=reorder(sector,n),
             x=n, fill=sector))+
  geom_col()+
  labs(y=NULL, 
       subtitle= "2022 S&P 500 Companies Count by Sector")+
  theme(legend.position = "none") 
ggsave("SP500_index_company_counts_by_sector.png") 
Καταμέτρηση εταιρειών του δείκτη S&P 500 2022 ανά κλάδο
Καταμέτρηση εταιρειών του δείκτη S&P 500 2022 ανά κλάδο

Ακολουθεί μια ματιά στις 15 κορυφαίες εταιρείες του δείκτη S&P 500 με βάση το βάρος τους.


stock_list_tbl %>% 
  arrange(desc(weight))%>%
  head(15) %>%
  mutate(company=gsub(" Corporation", "", company),
         company=gsub(" Inc.","", company),
         company=gsub(" Limited","", company),
         company=gsub(" Company","", company),
         company=gsub(" Inc.","", company),
         company=gsub(" Incorporated","", company)) %>%
  ggplot(aes(y=reorder(company,weight),
             x=weight, fill=sector))+
  geom_col()+
  labs(y=NULL)+
  scale_x_continuous(labels=scales::percent_format())
ggsave("SP500_index_company_weight_top15.png")  
Οι 15 κορυφαίες εταιρείες στον S&P 500 (ανά κεφαλαιοποίηση αγοράς)
Οι 15 κορυφαίες εταιρείες στον S&P 500 (ανά κεφαλαιοποίηση αγοράς)


Πώς να λάβετε δεδομένα τιμών μετοχών για μια εταιρεία

Μπορούμε να πάρουμε την τιμή της μετοχής οποιασδήποτε εισηγμένης αμερικανικής εταιρείας χρησιμοποιώντας τη συνάρτηση tidyquant tq_get(). Στο παρακάτω παράδειγμα, καθορίζουμε ticker για την Apple και επίσης καθορίζουμε τις ημερομηνίες έναρξης και λήξης που χρειαζόμαστε τα δεδομένα αποθεμάτων. Εδώ λαμβάνουμε τα δεδομένα τιμών μετοχών της Apple για ολόκληρο το έτος 2022.

Για κάθε εταιρεία που καθορίζουμε παίρνουμε την τιμή της μετοχής στο άνοιγμα, την υψηλή, τη χαμηλή και την προσαρμοσμένη τιμή όπως φαίνεται παρακάτω.


tq_get("AAPL", from = "2022-01-01", to="2023-01-01") %>% 
  head()

## # A tibble: 6 × 8
##   symbol date        open  high   low close    volume adjusted
##   <chr>  <date>     <dbl> <dbl> <dbl> <dbl>     <dbl>    <dbl>
## 1 AAPL   2022-01-03  178.  183.  178.  182. 104487900     181.
## 2 AAPL   2022-01-04  183.  183.  179.  180.  99310400     179.
## 3 AAPL   2022-01-05  180.  180.  175.  175.  94537600     174.
## 4 AAPL   2022-01-06  173.  175.  172.  172   96904000     171.
## 5 AAPL   2022-01-07  173.  174.  171.  172.  86709100     171.
## 6 AAPL   2022-01-10  169.  172.  168.  172. 106765600     171.

Ας γράψουμε μια μικρή συνάρτηση για να πάρουμε την τιμή της μετοχής μιας εταιρείας. Αντί να λαμβάνουμε όλα τα δεδομένα από τη συνάρτηση tq_get(), κρατάμε μόνο τρεις στήλες από την έξοδο της tq_get().


get_stock_price <- function(ticker = "AAPL"){
  tq_get(ticker, from = "2022-01-01", to="2023-01-01") %>%
    select(symbol, date, adjusted)
}

Εδώ είναι μια άλλη συνάρτηση για να λάβετε όλες τις μετοχές για τις εταιρείες του δείκτη S&P 500 χρησιμοποιώντας τη συνάρτηση tq_index() στο πακέτο tidyquant R.


get_stock_tickers <- function(stock_index= "SP500"){
  tq_index(stock_index) %>%
    select(symbol,company,weight) %>%
    arrange(symbol) 
 }

Επιτρέψτε μας να πάρουμε όλες τις μετοχές από τον δείκτη S&P 500 και να καθαρίσουμε λίγο τα ονόματα των μετοχών.


sp500_tickers <- get_stock_tickers()
sp500_tickers <- sp500_tickers %>% 
  mutate(symbol= gsub("\\.","-",symbol)) 

sp500_tickers %>% head()

## # A tibble: 6 × 3
##   symbol company                         weight
##   <chr>  <chr>                            <dbl>
## 1 A      Agilent Technologies Inc.     0.00142 
## 2 AAL    American Airlines Group Inc.  0.000280
## 3 AAP    Advance Auto Parts Inc.       0.000290
## 4 AAPL   Apple Inc.                    0.0587  
## 5 ABBV   AbbVie Inc.                   0.00907 
## 6 ABC    AmerisourceBergen Corporation 0.000829

Πώς να λάβετε δεδομένα τιμών μετοχών για όλες τις εταιρείες του δείκτη S&P 500

Με όλα τα εταιρικά tickers, είμαστε τώρα έτοιμοι να λάβουμε τα δεδομένα τιμών μετοχών για όλες τις εταιρείες του S&P 500. Και πάλι, θα χρησιμοποιήσουμε τη συνάρτηση tq_get() του tidyquant για να λάβουμε τα δεδομένα μετοχών. Εδώ, αντί για το ticker μιας εταιρείας, θα χρησιμοποιήσουμε όλα τα tickers από τον δείκτη S&P 500.

Καθορίζουμε επίσης την ημερομηνία έναρξης και λήξης για το έτος 2022, αφού θέλουμε τα δεδομένα για ολόκληρο το 2022.


# get SP500 companies stock price data
sp500_2022 <- tq_get(sp500_tickers %>% pull(symbol),
                    from = "2022-01-01",
                    to= "2023-01-01") 

Εφόσον η tq_get() ανακτά τα δεδομένα μέσω Διαδικτύου χρησιμοποιώντας την υπηρεσία Yahoo, μπορεί να χρειαστεί λίγος χρόνος για να ολοκληρωθεί για να λάβετε τις τιμές μετοχών σε περισσότερες από 500 εταιρείες για ένα χρόνο. Όταν ολοκληρωθεί, τα δεδομένα εξόδου θα φαίνονται ίδια με πριν, αλλά τώρα για όλες τις εταιρείες.


# S&P 500 companyies stock price data
sp500_2022 %>% head()

## # A tibble: 6 × 8
##   symbol date        open  high   low close  volume adjusted
##   <chr>  <date>     <dbl> <dbl> <dbl> <dbl>   <dbl>    <dbl>
## 1 A      2022-01-03  159   159.  154.  156. 1606300     155.
## 2 A      2022-01-04  155.  156.  150.  151. 2234000     150.
## 3 A      2022-01-05  151.  153.  149.  149. 2370500     148.
## 4 A      2022-01-06  149.  150.  146.  149. 2298300     148.
## 5 A      2022-01-07  149.  150.  145.  145. 2058600     144.
## 6 A      2022-01-10  143.  145.  141.  145. 2548100     144.

Μπορούμε να βεβαιωθούμε ότι έχουμε κατεβάσει όλα τα δεδομένα τιμών μετοχών των εταιρειών.


sp500_2022  %>% dim()

 126002      8

Έχουμε πάνω από 120.000 σειρές δεδομένων τιμών μετοχών. Και κοιτάζοντας την ουρά των δεδομένων. Δεδομένου ότι έχουμε ταξινομήσει τα εταιρικά tickers, βλέπουμε δεδομένα από μια εταιρεία που ξεκινά με το Z.


sp500_2022  %>% tail()

## # A tibble: 6 × 8
##   symbol date        open  high   low close  volume adjusted
##   <chr>  <date>     <dbl> <dbl> <dbl> <dbl>   <dbl>    <dbl>
## 1 ZTS    2022-12-22  144.  145.  142.  145. 1541800     145.
## 2 ZTS    2022-12-23  145.  146.  144.  146. 1017900     146.
## 3 ZTS    2022-12-27  146.  146.  144.  145.  957900     145.
## 4 ZTS    2022-12-28  145.  147.  144.  144. 1443900     144.
## 5 ZTS    2022-12-29  145.  149.  145.  148. 1298900     148.
## 6 ZTS    2022-12-30  147.  148.  145.  147. 1249500     147.

Πώς να υπολογίσετε τις ημερήσιες αποδόσεις για όλες τις εταιρείες του δείκτη S&P 500

Θα υπολογίσουμε τις ημερήσιες αποδόσεις για κάθε ημέρα και για κάθε εταιρεία χρησιμοποιώντας προσαρμοσμένη τιμή για μια ημέρα με. συνάρτηση tq_transmute() του tidyquant.

Εφαρμόζουμε την tq_transmute() για κάθε εταιρεία στο S&P 500 χρησιμοποιώντας τη συνάρτηση group_by(). Και η tq_transmute() παίρνει τέσσερα ορίσματα όπως φαίνεται παρακάτω. Καθορίζουμε την tq_transmute() να χρησιμοποιεί „προσαρμοσμένη“ τιμή μετοχής για τον υπολογισμό των ημερήσιων αποδόσεων και επίσης μετονομάζουμε τη στήλη επιστροφής σε „daily_return“.


sp500_daily_return <- sp500_2022  %>% 
  group_by(symbol) %>%
  tq_transmute(select     = adjusted,
                 mutate_fun = periodReturn, 
                 period     = "daily", 
                 col_rename = "daily_return") 

Και τα δεδομένα ημερήσιας επιστροφής που προκύπτουν είναι μια τακτοποιημένη πλακέτα που μοιάζει με αυτό.


sp500_daily_return %>% head()

## # A tibble: 6 × 3
## # Groups:   symbol [1]
##   symbol date       daily_return
##   <chr>  <date>            <dbl>
## 1 A      2022-01-03    0        
## 2 A      2022-01-04   -0.0338   
## 3 A      2022-01-05   -0.0171   
## 4 A      2022-01-06    0.00350  
## 5 A      2022-01-07   -0.0266   
## 6 A      2022-01-10    0.0000690

Πώς να υπολογίσετε τις εβδομαδιαίες/μηνιαίες/ετήσιες αποδόσεις για όλες τις εταιρείες στον δείκτη S&P 500

Εάν ενδιαφέρεστε να υπολογίσετε άλλες αποδόσεις όπως, εβδομαδιαία, μηνιαία ή ετήσια, μπορούμε να χρησιμοποιήσουμε τη συνάρτηση tq_transmute() του tidyquant με παρόμοιο τρόπο, αλλά αυτή τη φορά αλλάζουμε το όρισμα «period» σε «εβδομαδιαία» και μετονομάζουμε σωστά τη στήλη επιστροφής.

Ο παρακάτω κωδικός λαμβάνει εβδομαδιαίες αποδόσεις εταιρειών στον δείκτη S&P 500.


sp500_weekly_return <- sp500_2022  %>% 
  group_by(symbol) %>%
  tq_transmute(select     = adjusted,
                 mutate_fun = periodReturn, 
                 period     = "weekly", 
                 col_rename = "weekly_return")

sp500_weekly_return %>% head()

## # A tibble: 6 × 3
## # Groups:   symbol [1]
##   symbol date       weekly_return
##   <chr>  <date>             <dbl>
## 1 A      2022-01-07      -0.0724 
## 2 A      2022-01-14      -0.00324
## 3 A      2022-01-21      -0.0496 
## 4 A      2022-01-28      -0.00327
## 5 A      2022-02-04       0.0296 
## 6 A      2022-02-11      -0.0278

Εδώ χρησιμοποιούμε την ίδια στρατηγική χρησιμοποιώντας «period=monthly» και λαμβάνουμε μηνιαίες αποδόσεις εταιρειών στον δείκτη S&P 500.


sp500_monthly_return <- sp500_2022  %>% 
  group_by(symbol) %>%
  tq_transmute(select     = adjusted,
                 mutate_fun = periodReturn, 
                 period     = "monthly", 
                 col_rename = "monthly_return")
sp500_monthly_return %>% head()
## # A tibble: 6 × 3
## # Groups:   symbol [1]
##   symbol date       monthly_return
##   <chr>  <date>              <dbl>
## 1 A      2022-01-31        -0.110 
## 2 A      2022-02-28        -0.0643
## 3 A      2022-03-31         0.0151
## 4 A      2022-04-29        -0.0973
## 5 A      2022-05-31         0.0695
## 6 A      2022-06-30        -0.0689

Και μπορούμε επίσης να λάβουμε ετήσιες αποδόσεις εταιρειών στον δείκτη S&P 500 με τον ακόλουθο κωδικό.


sp500_annual_return <- sp500_2022  %>% 
  group_by(symbol) %>%
  tq_transmute(select     = adjusted,
                 mutate_fun = periodReturn, 
                 period     = "yearly", 
                 col_rename = "annual_return")
sp500_annual_return %>% head()
## # A tibble: 6 × 3
## # Groups:   symbol [6]
##   symbol date       annual_return
##   <chr>  <date>             <dbl>
## 1 A      2022-12-30       -0.0374
## 2 AAL    2022-12-30       -0.322 
## 3 AAP    2022-12-30       -0.357 
## 4 AAPL   2022-12-30       -0.282 
## 5 ABBV   2022-12-30        0.240 
## 6 ABC    2022-12-30        0.265

PCA για τις Ημερήσιες Επιστροφές εταιρειών S&P 500

Ας προχωρήσουμε στην εκτέλεση PCA στις ημερήσιες αποδόσεις των εταιρειών στον δείκτη S&P 500. Αρχικά, ας αναδιαμορφώσουμε την τακτοποιημένη/μεγάλη φόρμα ημερήσιας επιστροφής δεδομένων σε ευρεία φόρμα, με εταιρείες σε σειρές και ημερομηνίες σε στήλες. Χρησιμοποιούμε pivot_wider για να αναδιαμορφώσουμε. Και μετατρέπουμε επίσης την πλατιά πλακέτα που προκύπτει σε μήτρα.


sp500_dmat <-  sp500_daily_return %>%
  pivot_wider(names_from="date", values_from = daily_return) %>%
  select(-`2022-01-03`) %>%
  column_to_rownames("symbol") %>%
  as.matrix()

Και ο ημερήσιος πίνακας αποδόσεων του S&P 500 μοιάζει με αυτό.


sp500_mat[1:5,1:5]

##        2022-01-04   2022-01-05   2022-01-06    2022-01-07    2022-01-10
## A    -0.033806308 -0.017130581  0.003499327 -0.0266229247  6.899386e-05
## AAL   0.014400000 -0.017875920 -0.005888651  0.0382337641 -2.541494e-02
## AAP   0.001140383 -0.002531108  0.021991956 -0.0147320356 -1.663232e-02
## AAPL -0.012691475 -0.026600016 -0.016693182  0.0009883834  1.160615e-04
## ABBV -0.001919791  0.005252839 -0.004710368 -0.0025881284  1.119520e-02

Πριν προχωρήσουμε, ας αφαιρέσουμε τυχόν δεδομένα που λείπουν στον πίνακα επιστροφής. Χωρίς να σταθούμε στους λόγους έλλειψης, απλώς προσδιορίζουμε τις σειρές με τιμές που λείπουν και αφαιρούμε τις σειρές από τον πίνακα επιστροφής SP500.



na_ind <- which(apply(sp500_dmat,1,function(x){sum(is.na(x))})>0)
na_ind

##  CEG GEHC 
##   89  199

sp500_mat <- sp500_dmat[-na_ind,]

dim(sp500_mat)
## [1] 501 250

Αφού αφαιρέσαμε τις δύο εταιρείες με τιμές που λείπουν, έχουμε 501 εταιρείες από τον δείκτη S&P 500 στον πίνακα ημερήσιων δεδομένων επιστροφής.

Στην PCA, μας ενδιαφέρει για τις εταιρείες και όχι για την απόδοση του δείκτη με την πάροδο του χρόνου. Επομένως, μεταφέρετε τον πίνακα πριν εφαρμόσετε τη συνάρτηση scale() για να κεντράρετε και να κλιμακώσετε τα δεδομένα. Μετά την κλιμάκωση εκτελούμε PCA χρησιμοποιώντας τη συνάρτηση prcomp() στο R.


pca_fit <-  sp500_mat %>%
  t() %>%
  scale() %>%
  prcomp()

Έχουμε αποθηκεύσει τα αποτελέσματα PCA σε μια μεταβλητή που ονομάζεται pca_fit. Και αυτή είναι η δομή του αντικειμένου αποτελέσματος PCA.


str(pca_fit )
## List of 5
##  $ sdev    : num [1:250] 14.87 5.54 4.68 3.76 3.01 ...
##  $ rotation: num [1:501, 1:250] -0.0514 -0.0457 -0.0388 -0.0548 -0.027 ...
##   ..- attr(*, "dimnames")=List of 2
##   .. ..$ : chr [1:501] "A" "AAL" "AAP" "AAPL" ...
##   .. ..$ : chr [1:250] "PC1" "PC2" "PC3" "PC4" ...
##  $ center  : Named num [1:501] 3.02e-18 -2.21e-17 1.45e-17 -2.84e-17 6.91e-18 ...
##   ..- attr(*, "names")= chr [1:501] "A" "AAL" "AAP" "AAPL" ...
##  $ scale   : Named num [1:501] 0.0223 0.0354 0.0235 0.0225 0.0141 ...
##   ..- attr(*, "names")= chr [1:501] "A" "AAL" "AAP" "AAPL" ...
##  $ x       : num [1:250, 1:250] -9.27 14.59 -2.85 2.48 4.48 ...
##   ..- attr(*, "dimnames")=List of 2
##   .. ..$ : chr [1:250] "2022-01-04" "2022-01-05" "2022-01-06" "2022-01-07" ...
##   .. ..$ : chr [1:250] "PC1" "PC2" "PC3" "PC4" ...
##  - attr(*, "class")= chr "prcomp"

Οικόπεδο οθόνης από Ημερήσιες Επιστροφές εταιρειών S&P 500

Θα χρησιμοποιήσουμε το πακέτο σκούπας για να εξαγάγουμε τα αποτελέσματα από το PCA. Με τη συνάρτηση broom’s tidy() με όρισμα „pcs“, παίρνουμε την ποσοστιαία διακύμανση που εξηγείται από κάθε υπολογιστή.


library(broom)
pca_fit %>%
  tidy("pcs")  %>%
  head()
## # A tibble: 6 × 4
##      PC std.dev percent cumulative
##   <dbl>   <dbl>   <dbl>      <dbl>
## 1     1   14.9   0.441       0.441
## 2     2    5.54  0.0612      0.502
## 3     3    4.68  0.0438      0.546
## 4     4    3.76  0.0282      0.574
## 5     5    3.01  0.0180      0.592
## 6     6    2.82  0.0159      0.608

Χρησιμοποιώντας τη διακύμανση που εξηγήθηκε, μπορούμε να κάνουμε μια γραφική παράσταση για να κατανοήσουμε πόσοι υπολογιστές εξηγούν την πλειονότητα της διακύμανσης στα δεδομένα μετοχών του S&P 500.


pca_fit %>%
  tidy("pcs") %>% 
  filter(PC<50) %>%
  ggplot(aes(x=PC, y=percent))+
  geom_col(fill="dodgerblue", alpha=0.7) +
  scale_y_continuous(labels=scales::label_percent(),
                     breaks = scales::breaks_pretty(n=6))+
  labs(y= "Variance explained",
       title="Scree plot: 2022 S&P 500 Stock Return data")
ggsave("Scree_plot_percent_variance_explained_SP500_data.png")
Διάγραμμα οθόνης: Ποσοστό διακύμανσης που εξηγείται από υπολογιστές στα δεδομένα SP500
Διάγραμμα οθόνης: Ποσοστό διακύμανσης που εξηγείται από υπολογιστές στα δεδομένα SP500

Ας αποθηκεύσουμε τη διακύμανση που εξηγείται από κάθε υπολογιστή για μελλοντική χρήση στη δημιουργία γραφημάτων PCA.


variance_exp <- pca_fit %>%  
  tidy("pcs") %>% 
  pull(percent)

variance_exp %>% head()
[1] 0.44130 0.06117 0.04376 0.02817 0.01804 0.01586

PCA Plot : PC1 vs PC2 – Ημερήσιες επιστροφές εταιρειών S&P 500

Για να κατανοήσουμε γρήγορα τους δύο κορυφαίους υπολογιστές από PCA σε δεδομένα δείκτη S&P 500, κάνουμε μια γραφική παράσταση PCA με PC1 έναντι PC2.

Αρχικά, ας συνδυάσουμε τα αποτελέσματα από το PCA με τα δεδομένα εταιρικών πληροφοριών του S&P 500.


pc_df <- pca_fit %>% 
  tidy("loadings") %>% 
  filter(PC %in% c(1:5)) %>% 
  rename(symbol=column) %>%
  left_join(stock_list_tbl, by="symbol") %>%
  mutate(PC=paste0("PC",PC)) %>%  
  pivot_wider(names_from = "PC",
              values_from = "value") 

pc_df %>% head()

## # A tibble: 6 × 13
##   symbol company      identifier sedol  weight sector shares_held local_currency
##   <chr>  <chr>        <chr>      <chr>   <dbl> <chr>        <dbl> <chr>         
## 1 A      Agilent Tec… 00846U10   2520… 1.42e-3 Healt…     3289739 USD           
## 2 AAL    American Ai… 02376R10   BCV7… 2.80e-4 Indus…     7063898 USD           
## 3 AAP    Advance Aut… 00751Y10   2822… 2.90e-4 Consu…      667858 USD           
## 4 AAPL   Apple Inc.   03783310   2046… 5.87e-2 Infor…   165455870 USD           
## 5 ABBV   AbbVie Inc.  00287Y10   B92S… 9.07e-3 Healt…    19567584 USD           
## 6 ABC    Amerisource… 03073E10   2795… 8.29e-4 Healt…     1792022 USD           
## # … with 5 more variables: PC1 <dbl>, PC2 <dbl>, PC3 <dbl>, PC4 <dbl>,
## #   PC5 <dbl>

Τώρα κάνουμε το γράφημα PCA, ένα διάγραμμα διασποράς μεταξύ PC1 και PC2. Χρωματίζουμε επίσης τα σημεία στο διάγραμμα διασποράς με βάση τον τομέα που ανήκει στον δείκτη S&P 500.


pc_df %>% 
  ggplot(aes(x=PC1,y=PC2, color=sector))+
  geom_point(size=3, alpha=0.7)+
  #coord_fixed() +
  labs(title= "PCA: 2022 S&P 500 Stock Data",
       x=paste0("PC1: ", round(variance_exp[1]*100), "%"),
       y=paste0("PC1: ", round(variance_exp[2]*100), "%"))
ggsave("PCA_plot_PC1_vs_PC2_SP500_daily_return.png")

Στραβίζοντας λίγο στο οικόπεδο PCA μπορούμε να δούμε κάποια μοτίβα σε επίπεδο τομέα, αλλά όχι εύκολα.

PCA Plot: PC1 έναντι PC2 S&P 500 Daily Return Data
PCA Plot: PC1 έναντι PC2 S&P 500 Δεδομένα μετοχής

Για να δούμε τι έχει καταγράψει το PC1, φτιάχνουμε ένα πλαίσιο με το PC1 στον άξονα x και τους τομείς του δείκτη S&P 500 στον άξονα y.
Έχουμε παραγγείλει τους τομείς με τις μέσες τιμές PC1.


pc_df %>%
  ggplot(aes(x=PC1,y=reorder(sector,PC1),
             color=sector))+
  geom_boxplot(size=1)+
  labs(title= "PCA: 2022 S&P 500 Stock Data",
       x=paste0("PC1: ", round(variance_exp[1]*100), "%"),
       y="Sector")+
  #geom_jitter(width=0.05)+
  theme(legend.position="none")
ggsave("PCA_plot_PC1_vs_SP500_sectors.png")

Μπορούμε να δούμε ξεκάθαρα το μοτίβο που έχει καταγράψει το PC1. Στη μία άκρη του κουτιού έχουμε εταιρείες πληροφορικής και στην άλλη πλευρά έχουμε εταιρείες ενέργειας. Καθώς προχωράμε από τον τομέα IT, που έχει χαμηλές τιμές PC1, στον ενεργειακό τομέα με υψηλή τιμή PC1, μπορούμε επίσης να δούμε άλλους τομείς να έχουν ένα ωραίο αυξανόμενο μοτίβο στις μέσες τιμές PC1 τους.

PCA σε δεδομένα μετοχών S&P 500: Τομείς PC1 έναντι SP500
PCA σε δεδομένα μετοχών S&P 500: Τομείς PC1 έναντι SP500

Επιστρέφοντας στο οικόπεδο PCA μεταξύ PC1 και PC2, ας επαναλάβουμε την πλοκή αυτή τη φορά, επισημαίνοντας μόνο τους τομείς της ενέργειας και της πληροφορικής.


pc_df %>%
  ggplot(aes(x=PC1,y=PC2))+
  geom_point(color="grey", size=3, alpha=0.3)+
  geom_point(data=pc_df %>% filter(sector=="Energy"),
             aes(PC1,PC2, color=sector), size=3, alpha=0.5)+
  geom_point(data=pc_df %>% filter(sector=="Information Technology"),
             aes(PC1,PC2, color=sector), size=3, alpha=0.5)+
  #coord_fixed() +
  labs(title= "PCA: 2022 S&P 500 Stock Data",
       x=paste0("PC1: ", round(variance_exp[1]*100), "%"),
       y=paste0("PC1: ", round(variance_exp[2]*100), "%"))
  #theme(legend.position = "none")
ggsave("PCA_plot_PC1_vs_PC2_SP500_sectors.png")

Τώρα, μπορούμε να δούμε ότι τόσο το PC1 όσο και το PC2 φαίνεται να διαχωρίζουν όμορφα αυτούς τους τομείς. Σίγουρα υπάρχει τεράστια διακύμανση εντός των τομέων.

PCA Plot S&P 500 Data : Επισημάνετε Επιλογή Τομέων
PCA Plot S&P 500 Data : Επισημάνετε Επιλογή Τομέων

Συνοψίζοντας, σε αυτήν την ανάρτηση, είδαμε πώς να λαμβάνετε δεδομένα τιμών μετοχών χρησιμοποιώντας το tidyquant και να εκτελείτε PCA σε δεδομένα μετοχών S&P 500 χρησιμοποιώντας το πλαίσιο tidyverse. Πραγματοποιήσαμε ένα πρώτο πέρασμα PCA για τα δεδομένα ημερήσιας απόδοσης από εταιρείες του δείκτη S&P 500 για το έτος 2022. Και θα μπορούσαμε να βρούμε ότι οι κορυφαίοι υπολογιστές εξηγούν καλά τη γενική συμπεριφορά της αγοράς στις αποδόσεις. Όπως αναφέρθηκε, αυτή είναι πραγματικά μια πρόχειρη διασκεδαστική ανάλυση, θα είναι ενδιαφέρον να κάνουμε πιο λεπτομερή οικονομική ανάλυση με αυτά τα δεδομένα χρησιμοποιώντας τεχνικές μείωσης διαστάσεων όπως το PCA.

Schreibe einen Kommentar