library(quantmod)
library(stringr)
library(readr)
library(xts)
library(magrittr)
library(PerformanceAnalytics)
library(ggplot2)
library(dplyr)
# 상해380 증권
test_1 <- read.csv("上证380.csv")
tt <- test_1[,2]
test <- str_pad(tt, width = 6, side = c("left"), pad = "0")
k <- 1
start_time <- Sys.time()
df <- NULL
for(k in 1:length(test)){
tryCatch({
data <- getSymbols(paste0(test[k],".SS"), src = "yahoo", auto.assign = F, from = "2018-01-01")
Ad_data <- Ad(data)
df <- cbind(df,Ad_data)
cat("\n", test[k],"complete ,",length(test)-k,"left")
}, error = function(e){
warning(paste0("Error in Ticker: ", test[k]))
})
}
# 걸린 시간
end_time <- Sys.time()
end_time - start_time
일단 지난 포스트의 코드를 이용해 저장한 상해380(上证380)종목들을 가져온다.
1. 종목들을 가져올때, 숫자 0이 만약 종목코드 왼쪽부분에 위치해 있다면, 삭제된 상태로 read될 것이다. 그래서 불러온 다음 str_pad 함수로 삭제된 0들을 복구시켜준다.
2. 여기선 크롤링 안한다. 현재 원하는건 주가 수익률 계산을 위한 수정주가이므로 getSymbols 함수와 Ad 함수만 써도 충분하다.
3. getSymbols 쓰는 과정에서, 종목 자체에 오류가 있을 수도 있으니 trycatch 함수를 써서 오류발생을 방지하자.
4. 데이터는 2018년 1월 1일부터 시작해서 2021년 1월 15일에 끝나는 것으로 불러왔다
5. 참고로, 상해증권거래소에 상장된 종목이므로 종목코드 뒤에 SS를 붙여줬다. 션전증권거래소에 상장된 종목이면 SZ를 뒤에 붙여야한다.
# NA 데이터 삭제
colnames(df) <- substring(colnames(df),2,7)
pre_data <- df[,colSums(is.na(df)) == 0]
# 수익률 계산
ret <- na.omit(Return.calculate(pre_data))
ret_1y <- ret %>% sapply(.,function(x){
prod(1 + x) - 1
})
# Top 20 Ticker & Graph
ret_1y <- ret_1y[rank(-ret_1y) <= 20] %>% round(4) %>%
fortify.zoo()
ret_1y[,1] <- row.names(ret_1y)
colnames(ret_1y) <- c("Ticker","Return")
ggplot(ret_1y, aes(x = Ticker, y = Return)) +
geom_bar(stat = 'identity') +
geom_text(aes(label = paste0(ret_1y[,2],"%"),
vjust = 0.1, hjust = 0.5),
) + xlab(NULL) + ylab(NULL)
df는 380개 종목들의 수정주가들을 모은 데이터 집합이다.
1. is.na를 써서 df에 NA가 있는지 확인한다. 그 다음 colSums 함수를 써서 각 columns의 NA의 총 개수가 0개인 column만 추출한다.이렇게 되면 데이터 열들을 통째로 삭제해버리는 경우가 발생하는데, 삭제된 열들은 설립된지 약 3년도 되지않은 기업이거나 3년에 해당하는 데이터들이 없어서 분석하기에 용이하지않다. 물론 이러한 말은 분석데이터는 최소한 3년정도 있어야한다는 전제하에서 성립한다. 1년짜리 데이터를 분석하고 싶다면 그렇게해도 결과는 나올 것이다.(여기선 예전의 코드를 복붙하느라 그냥 ret_1y를 썼다;;)
2. 상위 20개 수익률을 낸 종목들을 뽑아봤다. 그걸 ggplot을 써서 그림을 그려보면 이렇게 나온다.
603345(安井食品)과 603127(昭衍新药)이 수익률이 제일 높은 두 종목이다. 회사명만 보면 전자는 식품관련이고 후자는 제약관련이다.
#### 상위 20개 종목 추출 & 상관관계 구하기
df_20 <- df[,row.names(ret_1y)]
df_20 <- df_20[,colSums(is.na(df_20)) == 0]
ret_20 <- df_20 %>% round(4) %>% xts() %>% Return.calculate() %>% na.omit()
options(scipen = 100)
# 상관관계를 return하는 함수
corr_func <- function(x){
result <- cor(x[,1],x[,2])
return(result)
}
# For문으로 20개 종목간 상관관계 구하기
corr_20 <- NULL
i <- 1
k <- 1
for(i in 1:ncol(ret_20)){
dt_1 <- ret_20[,i]
for(k in 1:ncol(ret_20)){
if(i + k <= ncol(ret_20)){
dt_2 <- ret_20[,i + k]
corr_df <- cbind(dt_1,dt_2)
corr <- rollapply(corr_df,252,corr_func,by.column = F)
colnames(corr) <- paste0(colnames(dt_1)," X ",colnames(dt_2))
corr_20 <- cbind(corr_20, corr)
cat("\n", k + i,"column finished")
}
else{
NULL
}
}
cat("\n", i," complete")
}
이제 본격적으로 수익률간 상관관계를 구해보자.
1. corr_func을 따로 만든 이유는, rollapply 함수에 파라미터로 넣기 위해서이다. 참고로 rollapply 함수는, 내가 어떤 한 기간(window)을 설정해주면, 그 기간단위로 함수를 apply 시켜주는 함수이다. 여기선 1년간 상관관계를 볼려고하니 영업일 252로 기간을 설정해놨다.
2. corr_20에 모든 종목간 상관관계를 저장한다.
# 20개 종목간의 상관관계
corr_20_1 <- na.omit(corr_20)
ncol(corr_20_1) # 총 190개
plot(corr_20_1)
190개 상관관계를 한꺼번에 같이 그래프로 보면 유의미한 정보를 발견하기 힘들다. 책 R고 하는 금융분석(Learning Quatitative Finance with R)에서는, "일반적으로 상관관계가 0.8보다 크면 상관관계가 높다고 하며, 0.5보다 작으면 상관관계가 낮다고 간주한다"라고 한다. 그래프를 보면 0.8 이상인건 없고 대부분 0.5보다 작다. 따라서 이 중에서 종목을 골라도, 대부분은 서로간의 상관관계가 0.5보다 작으므로 포트폴리오 위험이 상관관계로 인해 클 확률은 크지않다.(물론 산업, 국가등 다양한 요소를 고려해야한다) 그럼 일단은 뭐라도 추출해보고 싶으니 상관관계가 보통인 0.5보다 높았던 적이 있는 것, 그리고 상관관계가 매우 낮은 0보다 낮았던 적이 있는 것이라도 찾아보자.
# 0.6을 넘었던 상관관계
corr_06 <- corr_20_1[,unique(which(corr_20_1 > 0.6, arr.ind = T)[,2])]
plot(corr_06)
colnames(corr_06) # "X603882.X.603658" "X603605.X.603127" "X603658.X.603127"
# 마이너스였던적 있는 상관관계
corr_minus <- corr_20_1[,unique(which(corr_20_1 < 0 , arr.ind = T)[,2])]
plot(corr_minus)
colnames(corr_minus) # "X600862.X.603520" "X600862.X.603658" "X603520.X.603806" "X603456.X.603806"
정리해보면,
1. 0.6을 넘었던 상관계수
- "603882(金域医学)X 603658(安图生物)" : 의료과 제약/공학
- "603605(珀莱雅) X 603127(昭衍新药)" : 화장품과 제약
- "603658(安图生物) X 603127(昭衍新药)" : 제약/공학과 제약
2. 마이너스였던 적 있는 상관계수
- "600862(中航高科) X 603520(司太立)" : 항공/비행과 화장품
- "600862(中航高科) X 603658(安图生物)" : 항공/비행과 제약/공학
- "603520(司太立)X 603806(福斯特)" : 화장품과 신에너지
- "603456(九洲药业) X 603806(福斯特)" : 제약과 신에너지
'투자를 위한 코딩 > R' 카테고리의 다른 글
R로 중국 주식 티커 데이터 가져오기 (0) | 2021.01.18 |
---|---|
R로 네이버 주식 데이터 크롤링 (0) | 2021.01.11 |
R로 중국 주식 크롤링 & 저변동성 분석 (0) | 2020.12.31 |
R로 주식 데이터 가져오기 & 베타 분석 (0) | 2020.12.09 |
다변량 통계분석과 R 모델링(多元统计分析及R语言建模) (1) (0) | 2020.11.29 |
댓글