본문 바로가기

코딩

함수 적용해보기

스토캐스틱 N = (현재 가격 - N일중 최저가)/(N일중 최고가 - N일중 최저가)

거래정지를 당하면 분모가 0이 되어버린다.

 

저번에 만든 개념을 사용자 지정 함수로 만들었다.

 

tradeFunction<- function(stockname,from,to){
  setwd("C:/Users/eunhy/Desktop/STUDY") # 작업폴더 넣어주세요
  
  library(readr)
  library(tidyverse)
  library(lubridate)
  library(tsibble)
  library(tidyquant)
  library(TTR)
  
  codeData<-read_csv("codeData.txt",show_col_types = FALSE)
  
  from<- ymd(from)
  to<- ymd(to)
  
  stockdata<- tq_get(paste0(
    codeData %>% 
      filter(종목명==stockname) %>% 
      select(종목번호),".KS")) %>% 
      na.omit() %>% 
      mutate(macd=MACD(close,12,26,9,"EMA")[,1],
             signal=MACD(close,12,26,9,"EMA")[,2],
             roc=ROC(close,14),
             rsi=RSI(close,14),
             fastk=stoch(cbind(high,low,close),nFastK = 10, nFastD = 6, nSlowD = 6)[,1],
             slowk=stoch(cbind(high,low,close),nFastK = 10, nFastD = 6, nSlowD = 6)[,2],
             slowd=stoch(cbind(high,low,close),nFastK = 10, nFastD = 6, nSlowD = 6)[,3],
           ) %>% 
      filter((date>=from) & (date<=to)) %>% 
      mutate(type_signal=ifelse((rsi<35) & (macd>signal) & (slowk>slowd),"buy",
                               ifelse((rsi>65)  &  (macd<signal) & (slowk<slowd),"sell",NA))) %>% 
      na.omit() %>% 
      mutate(trade = ifelse(is.na(lag(type_signal))==TRUE,type_signal,
                        ifelse(lag(type_signal)==type_signal,NA,type_signal))) %>% 
      na.omit() %>% 
      mutate(rate_return=ifelse((trade=="sell") & (lag(trade)=="buy"),(close/lag(close)-1)*100,NA))
  
    totalreturn = round((prod(stockdata %>% select(rate_return) %>% na.omit() %>%  unlist()/100+1)-1)*100,2)
    yeardiff = (lubridate::interval(from,to) %>% as.numeric("years"))
    annualreturn = ((totalreturn/100+1)^(1/yeardiff)-1)*100
    returns = c(totalreturn,annualreturn)
    names(returns)<-c("total return(%)","annual return(%)")
  return(list(data=stockdata,return=returns))
}

 

그래서 시험해보면,

 

> setwd("C:/Users/eunhy/Desktop/STUDY")
> source(file="tradeFunction1.R")
>
> testresult1<- tradeFunction("CJ제일제당",20170101,20210101)
Warning message:                                                                                                              
`type_convert()` only converts columns of type 'character'.
- `df` has no columns of type 'character' 
>
> testresult1$return
 total return(%) annual return(%) 
         8.06000          1.95681
         
> testresult2<- tradeFunction("CJ제일제당",20120101,20210101)
Warning message:                                                                                                              
`type_convert()` only converts columns of type 'character'.
- `df` has no columns of type 'character' 

> testresult2$return
 total return(%) annual return(%) 
       79.520000         6.715701

 

잘 작동한다.

그래서 다른 주식을 넣어보았다

 

> testresult3<- tradeFunction("SK텔레콤",20120101,20210101)
Warning message:                                                                                                              
`type_convert()` only converts columns of type 'character'.
- `df` has no columns of type 'character' 
> testresult3$return
 total return(%) annual return(%) 
               0                0 
> 
> testresult4<- tradeFunction("현대백화점",20170101,20210101)
Warning message:                                                                                                              
`type_convert()` only converts columns of type 'character'.
- `df` has no columns of type 'character' 
> testresult4$return
 total return(%) annual return(%) 
       1.1300000        0.2813107 
> 
> testresult5<- tradeFunction("삼성전자",20120101,20210101)
Warning message:                                                                                                              
`type_convert()` only converts columns of type 'character'.
- `df` has no columns of type 'character' 
> testresult5$return
 total return(%) annual return(%) 
       15.760000         1.639015 
> 
> testresult6<- tradeFunction("카카오",20120101,20210101)
Warning message:                                                                                                              
`type_convert()` only converts columns of type 'character'.
- `df` has no columns of type 'character' 
> testresult6$return
 total return(%) annual return(%) 
      130.700000         9.731021 
> 
> testresult7<- tradeFunction("KB금융",20120101,20210101)
Warning message:                                                                                                              
`type_convert()` only converts columns of type 'character'.
- `df` has no columns of type 'character' 
> testresult7$return
 total return(%) annual return(%) 
       51.590000         4.729716

 

매매 자체가 잘 이뤄지지 않는다 ㅠㅠ 조건이 너무 엄격한가?

 

그리고 맨 처음 말했던 것처럼 거래 정지당한 주식들은 스토캐스틱 함수에서 분모가 0이 되어 오류가 나버린다.

 

> testresult8<- tradeFunction("삼성바이오로직스",20120101,20210101)
Error: Problem with `mutate()` column `fastk`.                                                                                
i `fastk = ...[]`.
x Series contains non-leading NAs
Run `rlang::last_error()` to see where the error occurred.
	In addition: Warning message:
	 Error: Problem with `mutate()` column `fastk`.
	i `fastk = ...[]`.
	x Series contains non-leading NAs
 
> testresult9<- tradeFunction("SKC",20120101,20210101)
Error: Problem with `mutate()` column `fastk`.                                                                                
i `fastk = ...[]`.
x Series contains non-leading NAs
Run `rlang::last_error()` to see where the error occurred.
	In addition: Warning message:
 	 Error: Problem with `mutate()` column `fastk`.
	i `fastk = ...[]`.
	x Series contains non-leading NAs

 

Rstudio에서 함수의 소스코드를 살펴보려면 패키지명::함수명 해주면 된다.

TTR 패키지의 stoch함수를 살펴보면

 

TTR::stoch

...

numMA <- do.call(maType[[3]][[1]], c(list(num), maType[[3]][-1]))
denMA <- do.call(maType[[3]][[1]], c(list(den), maType[[3]][-1]))
fastK <- numMA/denMA
fastK[!is.finite(fastK) & !is.na(fastk)] <- 0.5

...

 

대충 저런 부분이 존재하는데, 저 "!is.na(fastK)"부분에서 오류가 난다고 한다.

구글링 하니까 6년 전에 같은 오류를 마주치신 사람들이 계심

아예 빼버리고 진행해도 된다고 하여, 해본 결과

 

testresult3<- tradeFunction2("SK텔레콤",20120101,20210101)
testresult4<- tradeFunction2("현대백화점",20170101,20210101)
testresult5<- tradeFunction2("삼성전자",20120101,20210101)
testresult6<- tradeFunction2("카카오",20120101,20210101)
testresult7<- tradeFunction2("KB금융",20120101,20210101)

> testresult3$return
 total return(%) annual return(%) 
               0                0 
> testresult4$return
 total return(%) annual return(%) 
       1.1300000        0.2813107 
> testresult5$return
 total return(%) annual return(%) 
       15.760000         1.639015 
> testresult6$return
 total return(%) annual return(%) 
      130.700000         9.731021 
> testresult7$return
 total return(%) annual return(%) 
       51.590000         4.729716

# 처음 실행했던 결과

> testresult3$return
 total return(%) annual return(%) 
               0                0 
> testresult4$return
 total return(%) annual return(%) 
       1.1300000        0.2813107 
> testresult5$return
 total return(%) annual return(%) 
       15.760000         1.639015 
> testresult6$return
 total return(%) annual return(%) 
      130.700000         9.731021 
> testresult7$return
 total return(%) annual return(%) 
       51.590000         4.729716

 

똑같이 나온다. 아까 실패한 주식들에 넣어주면 이젠 결괏값이 나타난다.

 

> #삼성바이오로직스
> testresult8$return
 total return(%) annual return(%) 
               0                0 
> #SKC
> testresult9$return
 total return(%) annual return(%) 
       174.93000         11.89001

 

그런데 거래가 안 되는 것들은 이유가 뭘까?

 

삼성바이오로직스

 

SK텔레콤

 

조건에 해당하는 것이 없었던 것 같다

RSI가 과매도/과매수는 잡아내도 조건에 사용한 MACD와 스토캐스틱의 교차를 같이 적용하면

"과매도 상태인데, 주가 상승이 시작되는 시점"

이라는 상당히 까다로운 조건이 되어버려서 그런 것 같다.

그래서 대세 하락하는 현대백화점과 무한 횡보하는 SKT는 거래가 이뤄지지 않은 듯.

결과적으로 손해가 나지는 않지만, 거래 자체가 어려워져서 수익도 제한되어버리는 느낌.

 

시뮬레이션을 돌려서 적정 조건을 찾아보든지 해야 할 것 같다.

반응형