시계열 분석 실전 사례 은닉 마르코프 HMM 모형 주식 분석 6편

    프로젝트와 같은 형태 처럼 분석 하는데,   분석을 진행 하는 단계 마다, 지속적으로 기존에 해 왔던 분석이 잘못된 것을 발견 하게 된다. 


 지금 현재 하고 있는 것이  해들리 위컴(Hadley Wickham)의  R for Data Science의 나온 아래와 같은 그림 대로 가고 있다. 


해들리 위컴의  데이터 분석 프로젝트에서 반드시 필요한 것 


데이터 분석의 분야는 매우 광범위 하기 때문에,  즉 책 한권을 읽는 다고 마스터 할 수 있는 것은 아니다,    즉  데이터를 변환 하고,   시각으로 보고 모델링 한 다음에 다시 데이터를 변환 하는 일정의 사이클이 필요하다. 물론  과정에서 계속 Communicate 가 필요한 것이다.  


시계열 분석 실적 사례 은닉 마르크프 모델은 동적인 모델이므로 언제 이야기가 끝이 날지는 모르겠지만, 이것을 계속 하다보면,  언젠가는 끝날 것이다.  

밀덕 세계에서는 한번의 실전이  백번의 훈련 보다 났지 않다고 하였는가?


  이번 분석의 특징은 비지도 학습 계열이라,  모델을 돌릴 때마다,  state의 결과가 다르게 나오기 때문에,    모델의 결과에 대해서, 보고나서,    HMM에서  적정한 갯수를 찾고,  최적화 해야 한다.

소스코드가 복잡하면, 해석하기 어려우므로,   그 동안 분석 한 과정을 간소화 하고,  일목요연 하게 정리 할 필요 성이 있다. 

    R에서 여러가지의 파라미터를 정리하려면,  모든 것이 함수 형태로 제작되어 관리 되어야 한다. 

처음에는 패키지를 vector 형태로 만들어,  sapply를 이용하여 일괄로 패키지를 로딩 한다. 

## 불필요 객체 지우기  
  rm(list = ls())

## 필요한 패키지 vector 형태 나열 및 함수형태로 불러오기   
  pkgs <- c("depmixS4", "ggplot2", "dplyr", "tqk", "forecast","stats")
  sapply(pkgs, require, character.only = T)

# 데이터가 바뀌지 않게 처리     
  set.seed(1004)   

  간단하게 정리하려면 함수가 필요하다. tqk를 이용해서 주식 데이터를 가져오고,  모델을 돌린 후 데이터 프레임 작업하고,  모델 작업결과를 나타내는 함수는 아래와 같다. 

## 주식 가져오는 함수 
  data_get_fun <- function(days, stock_code){  
    
    # Data get from tqk 
    stock <- tqk_get(stock_code, from= days)  
    stock$종목코드 <- stock_code
    
    # R은 데이터를 가져와 전저리 할때 단순함      
    stock <-   stock %>% 
      arrange(date) %>% 
      mutate(전일비 = c(NA,  diff(adjusted))) %>% 
      filter(!is.na(전일비)) %>% 
      mutate(전일시세 = adjusted - 전일비) %>% 
      mutate(등락율 =  round((adjusted - 전일시세)/전일시세 * 100, 2))
    
    return(stock)
  }

## 데이터를 불러오고 HMM 모델링하는 함수   
  model_fit_fun <- function(start_days, stock_code, state_count){  
    # 데이터 가져오기 
    df <- data_get_fun(start_days,stock_code)
    
    # HMM 모델 돌리기   
    hmm.model <- depmix(adjusted ~1, family = gaussian(),
                        nstates = state_count, data = df)
    model.fit <- fit(hmm.model)
    
    # 모델 결과 보기  
    fit <- attr(model.fit, "response")
    
    
    # state 상태에 대한 조건부 확률 큰것
    post_probs <- posterior(model.fit, type= "viterbi") 
    post_max <-  as.matrix(post_probs[2:6])
    post_prob_vt <-  apply(post_max,1, max)
  
    # 그래프를 그리기 위한 데이터 프레임 작업
    df1 <-   data.frame(date = df$date, 
                       adjusted = df$adjusted,
                       state = post_probs$state,
                       post_prob = round(post_prob_vt,2)) 
    
    # 확률이 95% 이하인것은 데이터 전처리 
    df1 <- df1 %>% 
      mutate(adjusted1 =  ifelse(post_prob >=0.95, adjusted, NA )) 
    
    return(list(df1, fit))
  }
  

## fitting 화 된 모델 데이터 프레임 만드는 function
  state_fun <- function(i) { 
  
    state <- i  
    coeff <-as.double(fit[[i]][[1]]@parameters[["coefficients"]])
    sd <- as.double(fit[[i]][[1]]@parameters[["sd"]])
    
    df1 <- data.frame(state, 
                      coeff = round(coeff,2),
                      sd = round(sd,2)) 
  
    return(df1)
  }  

위의 함수가 정리 되었다면,  아래와 같이 파라메터를 넣는다. 

## 기초변수 Parameter
  # 분석 시작하고 싶은 일자  
  start_days = as.Date("2020-06-01")
  
  # HMM의 state  갯수(적정 HMM 갯수를 찾는 것이 목적임)
  state_count <- 5
  
  # 증권종목코드(대상으로 준비함) 
  stock_code <- "001680"  
  

파라메터가 정리되었다면 아래와 같이, 함수를 돌려 그래프 그릴 데이터 셋과 모델 결과를 데이터 프레임으로 만들어 정리 한다. 

    
## 그래프 분석할 데이터 셋 및 모델 가져오기 
  list <- model_fit_fun(start_days, stock_code, state_count)
## converged at iteration 49 with logLik: -2577.386
  df <- list[[1]]
  fit <- list[[2]]  
  
## 진단 결과에 따른 데이터 셋 만들기   
  # sapply를 계산 하려면,  1부터 주어진 state 갯수를 정해야 한다.   
  i <- 1:state_count  
  
  # sapply 함수를 t를 이용해서, 행렬 Transpose를 하여, 데이터 프레임을 만든다. 
  state_df <-  as.data.frame(t(sapply(i,state_fun)))  

# 데이터 보기 
  state_df
##   state    coeff     sd
## 1     1 26120.74 295.89
## 2     2 27772.23 307.91
## 3     3 25040.22 452.41
## 4     4 26857.13  288.1
## 5     5 28957.51 605.32

   앞에서 seed 값을 정하면, 일 단위로 분석 할 때는 변화하기 않으나,  시장 상황에 따라 state가 바뀐다.  며칠 째 돌리고 있는데,  매일 조금씩 바뀐다. 

stete 별 히스토그램

위 히스토그램을 보면 1번 3번이, 2,번 4번이 약간 비슷해 보인다.   이것을 anova turkey 분석을 하면,  아주 놀랍게도 전부 다르다고 해석이 된다. 

# state를 factor 형태로 만들기
  df$state <- as.factor(df$state)
  
# anova 모델 만들기
  model <- aov(adjusted~state, data=df)
  summary(model)
##              Df    Sum Sq   Mean Sq F value Pr(>F)    
## state         4 532989885 133247471   491.8 <2e-16 ***
## Residuals   330  89411115    270943                   
## ---
## Signif. codes:  0 '***' 0.001 '**' 0.01 '*' 0.05 '.' 0.1 ' ' 1
  TukeyHSD(model, conf.level=.95)
##   Tukey multiple comparisons of means
##     95% family-wise confidence level
## 
## Fit: aov(formula = adjusted ~ state, data = df)
## 
## $state
##          diff       lwr       upr   p adj
## 2-1 1268.5965  854.2771 1682.9158 0.0e+00
## 3-1  800.5882  381.2222 1219.9543 2.9e-06
## 4-1 2208.3505 1812.2280 2604.4730 0.0e+00
## 5-1 3853.4783 3461.5296 4245.4269 0.0e+00
## 3-2 -468.0083 -743.2038 -192.8127 4.4e-05
## 4-2  939.7540  701.4732 1178.0349 0.0e+00
## 5-2 2584.8818 2353.6061 2816.1574 0.0e+00
## 4-3 1407.7623 1160.8106 1654.7139 0.0e+00
## 5-3 3052.8900 2812.6905 3293.0895 0.0e+00
## 5-4 1645.1277 1448.3005 1841.9550 0.0e+00

  anova 가지고는 적정 클레스를 찾을 수 없다. 

댓글 없음:

댓글 쓰기

css cheat sheet 클래스 선택자, margin(마진), display , center 조정 간단한 구성 요소

 앞에서는 html의 간단한 sheet를 소개 하였습니다.   html은  주로 골격을 나타나는 것이라, 디자인을 하는데는 css로 하여야 합니다.  아래 코드와 같이 css 관련 하여 매우 간단하게 코딩 하겠습니다.  body 부분의 css 코딩  ...