Valuation | R | Volatility 주가 변동성 계산 | 주식 역사적 변동성 | 옵션가치평가
Apr 1, 2025
Valuation | 가치평가에서의 옵션가치평가의 내용에 따라서 주식을 기초자산으로 하고 이 기초자산 주식에 의하여 파생하는 Pay-off에 따라서 가치가 결정된다고 보는 옵션가치평가에 있어서 현재 주가를 미래에 상승 또는 하락 변동하도록 하여 미래의 주식 변동 가능성을 가정하여 펼쳐놓고 그 변동에 따라서 결정된 값이 행사가격을 초과하는 경우 초과금액이 옵션의 가치라고 보아 할인하여 현재가치로 계산하는 것을 파생상품평가의 개념이라고 할 때 여기에 적용하는 주요 변수로 변동성이 작용하게 된다.
채권수익률의 기간구조(The Term Structure of Interest rate) 와 위험구조 | 채권 평가 | 옵션 평가 | Valuation 에서 적용하기 위한 할인율을 도출하는 것은 보다 복잡한 과정을 거쳐야 하지만 역사적 변동성의 도출은 상대적으로 간단한 과정으로 해결할 수 있다.
주식 가격의 변동성 종류
내재변동성과 역사적 변동성
내재변동성은 옵션 가격에 내재되어 있는 기초자산의 가격의 변동성으로 옵션에서 역산해서 산출한 변동성인데 시장에서 거래되는 옵션 가격이 이미 주어져 있다는 전제가 필요하므로 하고자 하는 일이 옵션가격을 계산하기 위하여 변동성을 필요로 하는 상황인데 이미 옵션이 활성시장에서 거래되고 있어서 옵션 가격이 있어야 한다면 직면하고 있는 상황에 부합하지 않는 경우가 많은 것으로 예상된다.
내재변동성을 측정하는 것이 항상 더 좋은 결과를 가져오는 것이 아니며 추가 가정을 필요로 하거나 계산이 복잡해지기만 하여 현실적이지 않은 문제로 인하여 회계처리를 목적으로 하는 옵션가치평가에 있어 대부분의 경우에 역사적 변동성을 도출하여 적용하고 있다. 또한 내재변동성과 역사적 변동성의 차이가 크지 않으며 오히려 역사적 변동성이 내재변동성보다 현실 설명력이 높다는 연구결과도 있으므로 역사적 변동성을 계산하는 간단한 방법을 소개하고자 한다.1
역사적 변동성
활성시장에서 거래되는 주식의 거래가격은 매일 시장이 활성화된 상태에 있을 때 빈번하게 거래되는 과정에서 가격이 변동된다.
그 변동하는 가격은 각 주식의 성격이나 거래량이 많고 적음에 따라서 상승 혹은 하락의 폭 등 많은 변수에 의하여 크게 변동하기도 하고 변동이 크지 않을 수도 있다. 이를 일일 종가 기준으로 나열한 주가 데이터를 활용하여 표준편차를 계산하면 그 표준편차 값을 주가 변동성으로 가정하여 주가 전개 모델을 마련하는데 활용하게 된다.
변동성 계산의 순서는 주식가격을 날짜순으로 나열하고 수익률을 계산한 다음 해당 수익률의 표준편차를 계산하면 된다.
(1) 단순 수익률과 로그 정규분표 수익률
주식 가격의 변동을 수치화하기 위하여는 수익(손실)률을 계산하면 된다.
단순히 수익률을 계산하면 현재의 가격을 직전 가격으로 나누어서 1을 빼면 수익률이 된다. 예를 들어 100의 가격이 110이 되었다면 110-100은 1.1이 되고 여기서 1을 빼면 0.1이 되어 10% 증가한 것을 변동을 표현할 수 있다.
$$ Rate \ of \ change = { After \ Value \over Before \ Value } - 1 $$
그런데 주가 변동성을 계산할 때에는 이렇게 하지 않고 주식의 수익률이 로그정규분표(lognormal distribution)를 따른다고 하여 주가의 변동성 측정을 위한 수익률을 로그를 사용하여야 한다. 자연상수 e 를 밑으로 하는 로그 ln 을 사용하여 로그 수익률을 계산하는 방법은 현재의 가격을 직전 가격으로 나눈 값을 자연로그 취하면 된다.(이 때에는 1을 빼지 않는다.)
$$ Rate \ of \ change = ln ({ After \ Value \over Before \ Value }) $$
(2) 변동성 계산에 적용할 주식가격의 기간 설정
주식 가격의 일간 종가를 활용하여 수익율을 계산하는 대상 기간을 어떻게 정해야 하는지 정해져 있지는 않다. 보통은 90영업일(달력의 날짜가 아니라 영업일이므로 주식 가격이 형성된 데이터 갯수)이나 180영업일 또는 달력의 날짜 1년을 대상 기간으로 하여 계산한다.
(3) 이상치(Outlier) 제거
역사적 변동성 측정에는 장기평균 회귀현상 및 이상치(Outlier)로 인한 왜곡보정을 고려할 필요가 있다. 통상적으로 역사적 변동성은 주가의 상승과 하락의 표준편차로 측정되는데, 대개 주가의 상승 보다는 하락폭이 크게 나타남(변동성 미소)에도 불구하고 옵션평가모형은 상승과 하락의 변동성에 동일한 가중치를 부여하기 때문에 결과가 왜곡될 수 있다는 것을 고려하여야 한다. 또한 가치평가에 있어서 역사적으로 기록된 과거의 데이터를 적용할 때는 역사적 수치를 그대로 적용하지 않고 일부 보정해서(Normalization) 적용하는 관행이 있다. 베타의 경우를 보더라도 실제 베타를 적용하지 않고 조정 베타를 적용한다. 실제 베타가 0.5로 계산되었으나 1에 장기평균 회귀한다고 보아 0.67을 적용하는 것이다.
따라서 IQR 또는 MSD, MAD 등의 통계의 이상치 제거 방법론을 적용한 변동성을 적용하는 것이 바람직하다고 생각한다.
다만, 업계에서 이상치 제거를 자의적이거나 수치 외곡의 의도가 있을 것이라고 오해하여 이상치 제거를 하지 않기를 바라는 경우도 있는것 같다.2
R을 활용한 실습
주식가격 데이터는 한국거래소 정보데이터시스템에서 내려받거나 네이버 등 포털사이트를 통해 받을 수도 있다. 웹 화면의 UI를 활용하여 마우스 클릭을 하는 과정을 통해 데이터를 받는 것은 의외로 상당히 피곤한 일이다. 주가 데이터와 같이 정형화된 데이터는 받는 것은 패키지로 구현되어 있으므로 간단한 함수 사용 방법만 알고 적용하면 쉽게 원하는 데이터를 내가 사용하고 있는 R 작업환경으로 가져올 수 있다.
주가 데이터 tidyquant 패키지3로 받기
R 패키지를 처음 사용하려면 install.packages("tidyquant")
명령어를 한 번 실행해야 한다.4
먼저, 삼성전자 주식(005930.KS)과 같은 하나의 종목 심볼에 대한 일일 가격 데이터를 데이터 제공자 Yahoo!Finance에서 직접 다운로드 한다. 데이터를 다운로드하기 위해 tq_get
명령어를 사용한다.5
다음 R 명령어로 삼성전자의 2024년 1월 1일부터 2024년 12월 31일의 주가를 받는다.
prices <- tq_get("005930.KS",
get = "stock.prices",
from = "2024-01-01",
to = "2024-12-31"
)
주가 데이터가 잘 받아졌는지 확인한다.
prices
삼성전자 주가 데이터의 상단에 연초 날짜가 나타나 잘 받아진 것을 확인할 수 있다.
# A tibble: 244 × 8
symbol date open high low close volume adjusted
<chr> <date> <dbl> <dbl> <dbl> <dbl> <dbl> <dbl>
1 005930.KS 2024-01-02 78200 79800 78200 79600 17142847 77917.
2 005930.KS 2024-01-03 78500 78800 77000 77000 21753644 75372.
3 005930.KS 2024-01-04 76100 77300 76100 76600 15324439 74980.
4 005930.KS 2024-01-05 76700 77100 76400 76600 11304316 74980.
5 005930.KS 2024-01-08 77000 77500 76400 76500 11088724 74882.
6 005930.KS 2024-01-09 77400 77700 74300 74700 26019249 73120.
7 005930.KS 2024-01-10 75000 75200 73200 73600 20259529 72044.
8 005930.KS 2024-01-11 72900 73600 72700 73200 57691266 71652.
9 005930.KS 2024-01-12 73000 74100 72800 73100 13038939 71554.
10 005930.KS 2024-01-15 73200 74000 73200 73900 2957915 72337.
# ℹ 234 more rows
# ℹ Use `print(n = ...)` to see more rows
해당 주가 데이터에 필요한 열을 추가한다. 주가 데이터셋의 종가(close) 열의 행을 한칸 위로 올려서 열을 추가하기 위하여 lead 함수6를 사용한다. 한칸 위로 올려 붙인 다음 종가(close) 열과 한칸 위로 올려 붙인 lead_close 열과의 log 수익률을 계산(R에서는 엑셀의 ln 자연로그 함수를 log로 쓴다.)하여 Change 열로 만들어 붙인다. Change 열의 값을 rates 변수에 벡터로 넣고 이 값들의 표준편차(sd)를 계산한다. na 값이 에러를 일으키지 않게 하기 위하여 na.rm=TRUE를 인수로 넣어준다.
prices$lead_close <- dplyr::lead(prices$close)
prices$Change <- log(prices$lead_close / prices$close)
rates <- prices$Change
sd(rates, na.rm=TRUE)
이렇게 하면 로그 수익률로 계산한 표준편차를 간단하게 계산할 수 있다. 이 표준편차를 해당 주식의 변동성이라고 가정하고 모델의 주식 가치 변동 Tree를 만드는데 활용한다.
[1] 0.02022787
이렇게 계산한 변동성은 1년을 기준으로 한 일간 변동성이다. 옵션가치평가를 할 때 이항모형을 사용하는데 이항모형에서의 Node의 주기는 Weekly를 주로 사용한다. 일간으로 하지 않고 주간으로 나누는 것도 Normalization의 일종으로 Valuation 모형을 구상하는 것은 일간보다 주간이 적합한것 같다. 따라서 주간 Node 모형이므로 일간 주식가격 종가 데이터를 사용하여 일일 변동성을 계산하는 것보다 주간 종가 데이터를 사용해서 주간 변동성을 계산하여 적용하는 것이 더 적합하다고 생각한다.
다만 앞서 일간 변동성을 계산하였으니 이것을 주간 변동성으로 환산하는 것을 예시해 보면 다음과 같다. 일간 변동성을 주간 변동성으로 환산하려면, 변동성(표준편차)은 루트 시간법칙(Square Root of Time Rule)을 따르므로 주간 변동성을 계산할 때 주 5일 거래를 가정하여 루트5를 곱한다.(루트 시간법칙은 변동성이 독립적인 정상분포를 따른다고 가정할 때 성립한다.)
sd(rates, na.rm=TRUE) * sqrt(5)
1년으로 계산한 일변동성을 주변동성으로 환산한 값은 다음과 같다.
$$ 주 \ 변동성 \ = \ 일간 \ 변동성 \times \ \sqrt{5} $$
[1] 0.04523089
모델에 주간 변동성을 적용하더라도 기업회계기준에서 연 변동성을 기재하도록 요구하는 경우가 있을 수 있다.
연 변동성으로 환산하는 것은 주간 변동성을 1년은 약 52주이므로 루트52를 곱하여 산정하거나 일간 변동성을 1년에 252거래일을 가정하여 루트252를 곱하여 산정할 수 있다.
$$ 연 \ 변동성 \ = \ 일간 \ 변동성 \times \ \sqrt{252} $$
> 0.02022787 * sqrt(252)
[1] 0.3211075
$$ 연 \ 변동성 \ = \ 주간 \ 변동성 \times \ \sqrt{52} $$
> 0.04523089 * sqrt(52)
[1] 0.3261646
-
실무에서 역사적 변동성을 계산해서 적용한다. ↩︎
-
IQR은 이상치를 제거하는 전통적인 통계적 기법으로써 구식으로 여겨질 수도 있으나 누가 재수행 하더라도 기계적이고 정확하게 같은 결과를 도출해 낼 수 있다는 측면을 생각하면 이상치 제거에 적합한 방법론이라고 생각한다. ↩︎
-
python의 financedatareader 또는 pykrx를 사용하면 국내 및 미국 주식가격을 내려받는 것이 더 용이할 수 있다. R의 reticulate https://rstudio.github.io/reticulate/ 패키지를 활용하면 python으로 받은 데이터를 R에서 사용하고 R에서 작업한 것을 python으로 보내는 등 유기적으로 하나의 작업환경에서 사용할 수 있다. ↩︎
-
tidyquant 사용에 문제가 있을 경우 해당 패키지 설명서를 참조. ↩︎
-
tq_get 명령어 사용 방법을 모르는 경우,
?tq_get
명령어를 입력하여 도움말 파일을 확인. ↩︎ -
dplyr 패키지가 설치되어 있어야 한다. ↩︎