본문 바로가기
  • plotly로 바로쓰는 동적시각화 in R & 파이썬
Plotly in R - 그래프에 마우스를 올려봅시다

이동평균이 표시된 plotly 동적 주가 그래프 in R

by 아참형인간 2022. 11. 24.
MA.knit

plotly를 사용한 주가 이동평균 그래프 그리기

주가 그래프에서 주가의 전반적인 흐름을 살펴보기 위해 사용하는 것이 이동평균 선 그래프이다. 보통 이동평균은 5일 이동평균, 20일 이동 평균, 60일 이동 평균, 120일 이동 평균을 보지만 그 간격은 사용자의 관점에 따라 달라질 수 있다.

그렇다면 plotly의 캔들 스틱 트레이스로 만든 그래프에서 이동 평균을 표시하는 선 그래프를 추가하는 방법에 대해 알아본다.

add_trace()를 사용한 여러 그래프의 중첩

plotly를 사용할 때 가장 직관적으로 표현되는 것은 add_trace()의 함수 이름과 같이 이미 그려진 plotly 객체에 트레이스를 추가하는 것이다. 이는 ggplot2에서 +를 사용해서 geom_*()을 추가해주는 것과 유사한 개념이지만 ‘add’ 라는 단어에서 주는 어감으로 기존의 시각화 개체에 추가한다는 의미가 보다 직관적으로 다가온다.

주가로 표현된 캔들스틱 트레이스로 그려진 plotly 객체에 add_trace()를 사용하여 ‘type’ 속성이 ‘scatter’이고 ’mode’ 속성이 ’lines’인 트레이스를 추가해주면 이동 평균 선 그래프가 추가된다.

이를 위해서 먼저 이동 평균값을 산출해주어야 한다.

이동 평균을 좀 더 잘 살펴보기 위해 앞서 100일간의 삼성전자 주가대신 500일간 삼성전자 주가를 사용하도록 하겠다.

library(tqk)
library(lubridate)
code <- code_get()

## 삼성전자 코드값을 가져온다. 
sse_code <- code |> filter(name == '삼성전자') |>
  select(code) |> 
  pull()

samsung_500 <- tqk_get(sse_code, from=today() - 500, to=today())

이제 5일, 20일, 60일, 120일 이동 평균을 다음과 같이 구한다. 이동 평균을 구하기 위해 zoo 패키지의 rollmean()을 사용한다.

samsung_moving <- samsung_500 %>% 
  mutate(MA_5 = zoo::rollmean(x = close, # column to take
                            k = 5, # rolling time period
                            align = "right", #leave values above the top
                            fill = NA), 
         MA_20 = zoo::rollmean(x = close, 
                             k = 20, 
                             align = "right", 
                             fill = NA), 
         MA_60 = zoo::rollmean(x = close, 
                             k = 60, 
                             align = "right", 
                             fill = NA), 
         MA_120 = zoo::rollmean(x = close, 
                             k = 120, 
                             align = "right", 
                             fill = NA)
         )  # fill the missing with NA)) |>

이제 앞선 포스트에서 최종적으로 그렸던 주말, 공휴일이 제거되고 거래량이 표시된 최종 캔들스틱 차트를 그린다.

samsung_moving <- samsung_moving |> 
  mutate(direction = case_when(
    open > close ~ 'd', 
    open <= close ~ 'i'
  ))

fig1 <- samsung_moving |> plot_ly() |>
  add_trace(
    type="candlestick", x = ~date,
    open = ~open, close = ~close,
    high = ~high, low = ~low, 
    increasing = list(line = list(color = 'red')), 
    decreasing = list(line = list(color = 'blue')), 
    text = paste0(samsung$date,"<br>시가:",scales::comma(samsung$open), '원', 
                  "<br>고가:", scales::comma(samsung$high), '원', 
                  "<br>저가:",scales::comma(samsung$low), '원', 
                  "<br>종가:", scales::comma(samsung$close), '원'),
    hoverinfo='text', showlegend = FALSE
  ) |> 
  layout(title = "삼성전자 Candlestick Chart", 
         xaxis = list(rangeslider = list(visible = F), 
                      rangebreaks=list(
                        list(bounds=list("sat", "mon")), 
                        list(values = list("2022-09-09", "2022-09-12", "2022-10-03", "2022-10-10"))
                      )
         ),
         yaxis = list(title = '주가'),
         showlegend = FALSE)

fig2 <- samsung_moving %>% plot_ly() |>
  add_trace(type = 'bar', x=~date, y=~volume, type='bar',
            color = ~direction, colors = c('blue','red'), showlegend = FALSE, 
            text = paste0(samsung$date, '<br>거래량:', scales::comma(samsung$volume)), 
            hoverinfo = 'text') |>
  layout(xaxis = list(rangebreaks=list(
    list(bounds=list("sat", "mon")), 
    list(values = list("2022-09-09", "2022-09-12", "2022-10-03", "2022-10-10"))
  )
  ),
  yaxis = list(title = '거래량'))

subplot(fig1, fig2, heights = c(0.7,0.2), nrows=2,
        shareX = TRUE) |>
  layout(margin = margins)

이제 완성된 fig에 이동 평균 선 그래프 3개를 추가해준다. 그런데 전체 그래프를 subplot()으로 구성된 두 개의 그래프(fig1, fig2)이기 떄문에 두 개의 그래프 중 어떤 그래프에 add_trace()할지를 결정하고 해당 그래프에 add_trace()로 추가해야한다.

fig1 <- fig1 |> add_trace(type = 'scatter', mode = 'lines', 
                          x = ~date, y = ~MA_5, name = '5일 이동평균')

fig1 <- fig1 |> add_trace(type = 'scatter', mode = 'lines', 
                          x = ~date, y = ~MA_20, name = '20일 이동평균')

fig1 <- fig1 |> add_trace(type = 'scatter', mode = 'lines', 
                          x = ~date, y = ~MA_60, name = '60일 이동평균')

fig1 <- fig1 |> add_trace(type = 'scatter', mode = 'lines', 
                          x = ~date, y = ~MA_120, name = '120일 이동평균')

subplot(fig1, fig2, heights = c(0.7,0.2), nrows=2,
        shareX = TRUE) |>
  layout(margin = margins)

댓글