내용
- 시계열이란?
- 단순 수익률과 로그수익률(Simple Returns and Log Returns)
- < a href="#model">기본 모델
시계열이란?
다음은 코스피 지수의 일일 종가(closing price)와 3일 평균에 대한 그래프입니다.
import numpy as np import pandas as pd import matplotlib.pyplot as plt import FinanceDataReader as fdr
st=pd.Timestamp(2010,8, 26) et=pd.Timestamp(2022, 1, 5) nme={'ks':'KS11','sam':'005930','hyni':"000660",'ksemi':'091160'} ks=fdr.DataReader('KS11', st, et) sam=fdr.DataReader('005930', st, et) hyni=fdr.DataReader('000660', st, et) ksemi=fdr.DataReader('091160', st, et)
ks["Close"].rolling(3).mean()
Date 2010-08-26 NaN 2010-08-27 NaN 2010-08-30 1739.816667 2010-08-31 1744.146667 … 2022-01-04 2985.220000 2022-01-05 2977.326667 Name: Close, Length: 2803, dtype: float64
plt.figure(figsize=(15, 7), dpi=100) plt.plot(ks["Close"].index, ks["Close"], label="Close") plt.plot(ks["Close"].index, ks["Close"].rolling(10).mean(), label="mean") plt.xlabel("Time", size="12", weight="bold") plt.ylabel("kospi[Close]", size="12", weight="bold") plt.legend(loc="best") plt.show()
위 결과는 시리즈에 추세가 있음을 관찰합니다. 즉, 평균은 시간이 지남에 따라 분명히 일정하지 않습니다. 이것은 금융 시계열에 일반적입니다. 금융 시계열의 이러한 추세는 예측하기가 거의 불가능하고 수학적으로 특성화하기 어렵습니다.
다음은 달러 기준의 한화에 대한 데이터 입니다.
usKr=fdr.DataReader("USD/KRW", st, et) usKr
Close | Open | High | Low | Change | |
---|---|---|---|---|---|
Date | |||||
2010-08-26 | 1191.07 | 1200.87 | 1201.16 | 1188.76 | -0.0051 |
2010-08-27 | 1196.07 | 1196.97 | 1198.57 | 1193.57 | 0.0042 |
$\vdots$ | $\vdots$ | $\vdots$ | $\vdots$ | $\vdots$ | $\vdots$ |
2022-01-04 | 1197.49 | 1194.77 | 1199.49 | 1192.75 | 0.0038 |
2022-01-05 | 1198.20 | 1197.54 | 1200.18 | 1195.91 | 0.0006 |
plt.figure(dpi=100) plt.plot(usKr["Close"].index, usKr["Close"], label="Close") plt.plot(usKr["Close"].index, usKr["Close"].rolling(10).mean(), label="mean") plt.xlabel("Time", size="12", weight="bold") plt.ylabel("KRW/US[Close]", size="12", weight="bold") plt.legend(loc="best") plt.show()
위 결과와 같이 이 시리즈의 평균은 시간이 지남에 따라 분명히 일정하지 않습니다. 따라서 비정상 시계열(non-stationary series)로 간주됩니다. 다시 말하지만, 추세의 진화는 예측하는 것이 거의 불가능할 것입니다. 이 상황에서 우리가 할 수 있는 최선은 시리즈의 조건부 변동성, 즉 KRW/USD 환율의 일일 변화를 이해하는 것입니다.
시계열(Time Series)
시계열은 고정된 샘플링 간격 동안 수집된 일련의 관측값입니다. 통계적 접근 방식에 따라 이러한 시리즈는 일련의 무작위 변수(random variable)를 실현하는 것으로 간주합니다. 이러한 고정된 샘플링 간격으로 정의된 일련의 랜덤 변수는 이산 시간 확률적 프로세스라고도 하지만 일반적으로 시계열 모델 또는 시계열 프로세스로 명명됩니다. 시계열, 즉 관찰된 값과 프로세스, 즉 확률적 구성을 구별하는 것은 매우 중요합니다.
시계열 과정은 확률 변수 {Xt, t ∈ T}의 집합입니다. 여기서 T는 과정이 관찰되었거나 관찰될 예정이거나 관찰할 수 있는 시간 집합입니다. 각 확률 변수 Xt가 일부 일변량 분포 함수 Ft에 따라 분포된다고 가정합니다. 이 문서에서는 등거리 시간 간격의 시계열 프로세스와 실수 값 확률 변수 Xt만 고려합니다. 이를 통해 시간 집합을 열거할 수 있으므로 T={1, 2,3, …}를 쓸 수 있습니다.
반면에 관측된 시계열은 랜덤 벡터 X=(X1, X2, X3, …, Xn) 구현되며 x=(x1, x2, x3, …, xn)와 같이 소문자로 표시됩니다. 다변량 의미에서 시계열은 다변량 n차원 분포 함수 F를 사용하여 n차원 확률 변수 X를 한 번만 구현한 것이라는 점에 유의하는 것이 중요합니다. 일반적으로 단일 관찰(single variable)로 통계를 할 수 없습니다. 이 상황에서 벗어나기 위해 결합 분포 함수 F 에 몇 가지 조건을 부과해야 합니다.
정상성(Stationarity)
위에서 언급한 결합 분포 F에 대한 조건은 정상성(Stationarity)의 개념입니다. 구어체으로 시리즈의 확률적 특성이 시간이 지남에 따라 변경되지 않아야 함을 의미합니다. 즉, 시계열의 어떤 섹션은 동일한 길이의 다른 섹션에 대해 "전형"이 되어야 합니다. 수학적으로, 임의의 s, t 및 k에 대해 관측값 xt, … xt+k가 다른 시간 s, …, s+k에서 쉽게 발생할 수 있음이 요구됩니다.
더 많은 수학적 엄격함을 적용하여 고정성의 개념을 소개합니다. 시계열은 인덱스 t, s, 그리고 k의 조합에서 Xt, …, Xt+k의 (k+1)차원 결합 분포가 Xs, …, Xs+k의 결합 분포와 일치하는 경우에만 엄격하게 정상적이라고 합니다. k =0과 t=s의 특별한 경우, 이것은 모든 Xt의 일변량 분포 Ft가 동일함을 의미합니다. 엄격하게 고정된 시계열의 경우 분포에서 인덱스 t를 생략할 수 있습니다. 다음 단계로 moment를 정의할 것입니다:
기대값 | $\mu_t=E(X_t)$ | 정상 시계열 | $\mu_t=\mu$ |
분산 | $\sigma_t^2=Var(X_t)$ | 정상 시계열 | $\sigma_t^2=\sigma^2$ |
공분산 | $\gamma(t_1, t_2)=Cov(X_{t_1}, X_{t_2})$ | 정상 시계열 | $Cov(X_{t_1}, X_{t_2})\gamma_t=\gamma(h)$ |
다시 말해서, 엄밀하게 정상시계열은 일정한 기대값, 일정한 분산을 가지며 공분산, 즉 종속성 구조는 두 관측값 사이의 시간 차인 시차 h에만 의존합니다. 그러나 공분산 항은 일반적으로 0과 다르므로 Xt는 일반적으로 종속적입니다.
실제로 시뮬레이션 연구를 제외하고는 일반적으로 잠재 시계열 프로세스에 대한 명확한 지식이 없습니다. 엄격한 정상성은 프로세스의 결합 분포의 속성으로 정의되기 때문에 단일 구현, 즉 관찰된 시계열에서 확인하는 것은 불가능합니다. 그러나 시계열 프로세스가 일정한 평균과 분산을 나타내는지 여부와 종속성이 시차 h에만 의존하는지 여부를 항상 확인할 수 있습니다. 이와 같이 덜 엄격한 속성은 약한 정상성으로 알려져 있습니다.
시계열에 대한 근거가 있는 통계 분석을 수행하려면 약한 정상성이 필요합니다. 시리즈의 관측값이 일정한 평균/분산과 안정적인 종속 구조와 같은 공통 속성을 갖지 않으면 통계적으로 학습할 수 없다는 것은 명확합니다. 불행히도 자산 가격은 종종 비정상적입니다. 탈출구는 시리즈의 상대적 변화에 대한 근사치인 로그 수익률을 연구하는 것입니다.
단순 수익률과 로그수익률(Simple Returns and Log Returns)
금융 시계열은 종종 비정상적입니다. 따라서 가격(또는 지수 값, 환율, 이자율)에 대한 통계 분석을 수행하기가 어렵습니다. 이를 Pt 로 표시합니다. 여러 가지 이유(아래 설명)로 인해 식 1과 같이 계산하는 가격의 상대적 변화를 사용합니다. 이 변화를 단순수익률(simple returns)라고 합니다.
$$\begin{equation}\tag{1}R_t=\frac{P_t-P_{t-1}}{P_{t-1}} \end{equation}$$Rt: 가격 시계열 Pt에서 simple return
일반적으로 금융데이터의 통계 분석에서 단순수익률 대신 로그수익률(rt)를 사용합니다. (식 2)
$$\begin{align}\tag{2}r_t&=\log\left(\frac{p_t}{p_{t-1}} \right)\\&=\log(p_t)-\log(p_{t-1})\\&=\log(1+R_t) \end{align}$$다음 코드는 데이터에 대한 단순수익률과 로그수익률을 계산한 것입니다.
data=pd.DataFrame([100, 105, 210]) daP=data.pct_change() daLog=pd.DataFrame(np.append(0, np.log(data.values[:-1]/data.values[1:]))) re=pd.concat([data, daP, daLog], axis=1) re.columns=["data", "simple","log"] re
data | simple | log | |
---|---|---|---|
0 | 100 | NaN | 0.000000 |
1 | 105 | 0.05 | -0.048790 |
2 | 210 | 1.00 | -0.693147 |
로그 수익률의 사용 근거
- 경험적 경험(Empirical Experience): 가격 시리즈는 일반적으로 정상적이지 않고 오른쪽으로 치우쳐 있습니다. 즉, 양의 스파이크가 음의 스파이크보다 더 큽니다. 그 상황에서 시계열 분석의 경험적 경험은 시리즈를 로그 변환하고 lag 1에서 1차 차분을 취해야 한다고 말합니다. 이 과정의 결과는 rt 입니다.
- 유한 책임(Limited Liability): 많은 금융 자산의 경우 손실될 수 있는 최대 금액은 해당 자산에 투입된 금액입니다. 즉, 49$ 가치가 있는 주식을 보유하고 있다면 잃을 수 있는 최대 금액은 49$입니다. 이를 유한 책임이라고도 합니다. 이 경우 단순 수익률은 Rmin=100%가 됩니다. 반면에 가능한 최대 단순 반환값은 Rmax=∞입니다. 이러한 비대칭은 로그 반환에는 존재하지 않습니다. 완전한 손실은 Rmin=-∞을 산출하고 최대값은 Rmax=∞ 입니다.
- 복리(compounding): 두 기간에 걸쳐 자산의 단순 수익을 얻으려면 다소 복잡하고 직관적이지 않은 계산이 필요합니다. $$R_{2, t}=\frac{P_t - P_{t-2}}{P_{t-2}}=(1+R_{1, t})(1+R_{1, t-1})-1$$ 로그 수익률을 사용하면 여러 기간 수익률을 계산하는 것이 훨씬 간단합니다. $$r_{2, t}=r_{1, t}+r_{1, t-1}$$ 즉, 로그 반환은 가산적(additive)이지만 단순 반환은 그렇지 않습니다.
로그 반환을 사용하는 또 다른 매우 중요한 이유는 Random Walk 모델과의 호환성입니다.
기본 모델
Random Walk
Random Walk 모델은 단일 기간 로그 반환값 r1,t이 독립적이고 정규 분포를 따른다는 개념을 기반으로 합니다. 위에서 나타낸 복리 속성을 반복적으로 적용하면 다기간 수익률은 다음과 같이 표현할 수 있습니다.
다시말하면 시간 t에서의 k 기간 수익률은 시간 t-k+1까지의 모든 단일 기간 수익률의 합입니다. (편리하게) 로그 반환값이 가우스 분포를 따른다고 가정하면 r1,t~ N(μ, σ2)을 적용할 수 있습니다. 독립 정규 확률 변수의 합은 그 자체가 정규분포를 따르기 때문에 다음과 같이 나타낼 수 있습니다.(식 3)
$$\begin{equation}\tag{3} r_{k, t} \sim N(k\mu, k\sigma^2) \end{equation}$$그러므로 기간 k까지의 로그 수익률은 식 4와 같이 나타낼 수 있습니다. 이 식은 random walk model이 됩니다.
$$\begin{equation}\tag{4} \frac{P_t}{P_{t-k}}=\exp \left(r_{1,t}+\cdots+r_{1, t-k+1} \right) \end{equation}$$임의의 시작시점(t=k)에서 위 프로세스는 다음과 같습니다.
$$P_t = P_0\exp \left(r_{1,t}+\cdots+r_{1, 1} \right)$$로그가 랜덤 워크인 이러한 프로세스를 기하학적 랜덤 워크라고 합니다. $r_{1,t}+\cdots+r_{1, 1}$ 이 정규식이라는 가정 하에 가격 프로세스 Pt는 모든 시간 t에서 로그 정규 분포를 따릅니다.
예
자산의 초기 가격은 P0=100 , r1,2 ~ N(μ=0, σ2=0.032)라고 가정합니다. 이러한 가정으로 시간-가격의 그래프는 다음과 같이 작성됩니다.
from scipy import stats
p0=100 mu=0 sigma=0.03 ret=stats.norm.rvs(mu, sigma, size=1000, random_state=1) price=p0*np.exp(np.cumsum(ret)) plt.figure(dpi=100) plt.plot(price) plt.xlabel("Time", size="12", weight="bold") plt.ylabel("price", size="12", weight="bold") plt.show()
다음은 실제 주식 데이타들의 로그수익(log return)입니다.
st=pd.Timestamp(2020,1,3) et=pd.Timestamp(2022, 1, 13) ks=fdr.DataReader('KS11', st, et)["Close"] sam=fdr.DataReader('005930', st, et)["Close"] usKr=fdr.DataReader("USD/KRW", st, et)["Close"] data=np.log(pd.concat([ks, sam, usKr], axis=1)) data.columns=["kospi","sam","usKr"] data.head(3)
kospi | sam | usKr | |
---|---|---|---|
Date | |||
2020-01-03 | 7.685455 | 10.924138 | 7.060433 |
2020-01-06 | 7.675578 | 10.924138 | 7.062140 |
2020-01-07 | 7.685032 | 10.929529 | 7.062449 |
data=data.replace(np.nan, method="ffill") data.head()
kospi | sam | usKr | |
---|---|---|---|
Date | |||
2020-01-03 | 7.685455 | 10.924138 | 7.060433 |
2020-01-06 | 7.675578 | 10.924138 | 7.062140 |
2020-01-07 | 7.685032 | 10.929529 | 7.062449 |
2020-01-08 | 7.673832 | 10.947292 | 7.058113 |
2020-01-09 | 7.690035 | 10.978490 | 7.055071 |
np.where(data.isna())
(array([], dtype=int64), array([], dtype=int64))
data_diff=data.diff(axis=0).dropna() data_diff.head()
kospi | sam | usKr | |
---|---|---|---|
Date | |||
2020-01-06 | -0.009876 | 0.000000 | 0.001707 |
2020-01-07 | 0.009454 | 0.005391 | 0.000308 |
2020-01-08 | -0.011200 | 0.017762 | -0.004336 |
2020-01-09 | 0.016202 | 0.031198 | -0.003042 |
2020-01-10 | 0.009078 | 0.015242 | -0.000647 |
plt.figure(figsize=(15, 5), dpi=100) plt.plot(data_diff.index, data_diff["kospi"], label="kospi") plt.plot(data_diff.index, data_diff["sam"], label="sam") plt.plot(data_diff.index, data_diff["usKr"], label="usKr") plt.xlabel("Time", size="12", weight="bold") plt.ylabel("Log Return", size="12", weight="bold") plt.legend(loc="best", prop={"size":12, "weight":"bold"}) plt.grid(True) plt.show()
위 그림은 금융 데이터의 매우 일반적인 몇 가지 공통 기능을 보여줍니다.
- 평균이 0에 가까운 상관 관계가 거의 없는 로그 반환.
- 변동성 클러스터, 즉 로그 수익률이 크거나 작은 기간
- 일부 극단적인 스파이크, 즉 매우 크거나 작은 수익에 해당하는 이상치
위의 특성들은 일부 전용 플롯으로 이러한 점을 더 잘 시각화할 수 있습니다. 첫째, 로그 반환의 자기상관 함수(ACF)는 비상관성 문제를 해결합니다. 둘째, 제곱 로그 반환의 ACF를 표시하여 프로세스의 조건부 분산에 대한 종속성을 캡처할 수 있습니다. 특히, 변동성 클러스터가 존재할 때마다 제곱 로그 수익률은 자기 상관을 보여줍니다. 마지막으로 히스토그램과 일반 분위수-분위수 도표는 (가우스) 분포 가정을 확인하는 데 사용됩니다.
그림 a는 시간적으로 지연된 데이터들 사이에 자기상관계수를 그래프로 나타낸 것입니다. statsmodels.graphics.tsaplots 모듈의 plot_acf()를 적용한 결과입니다. 이 그림의 파란색 영역을 벗어난 경우가 자기상관이 있음을 의미합니다. 그림 b 역시 동일한 함수를 적용한 것으로 로그 수익을 제곱한 경우의 결과입니다. 그림 c와 d의 경우는 데이터의 정규분포이 부합여부를 나타내는 것으로 c는 scipy.stats 모듈의 probplot() 함수를 적용하여 q-q plot을 작성한 것이며 d는 데이터의 히스토그램과 동일한 정규분포를 따르는 랜덤수의 분포와 비교한 것입니다.
#acf of log returns plt.figure(dpi=100) plot_acf(data_diff["kospi"], lags=30) plt.xlabel("Lag", size=12, weight="bold") plt.ylabel("ACF", size=12, weight="bold") plt.title('(a) ACF of Log Returns', size=13, weight="bold") plt.show()
#acf of squared log returns plt.figure(dpi=100) plot_acf(data_diff["kospi"]**2, lags=30) plt.xlabel("Lag", size=12, weight="bold") plt.ylabel("ACF", size=12, weight="bold") plt.title('(b) ACF of Squared Log Returns', size=13, weight="bold") plt.show()
#normal plot of log returns plt.figure(dpi=100) val, para=stats.probplot(data_diff["kospi"], plot=plt, rvalue=True) plt.title("(c) Normal plot of Log Return", size=13, weight="bold") plt.show()
mu=data_diff["kospi"].mean() std=data_diff["kospi"].std()mu, std(0.0005557381711972228, 0.014131231177349868)#histogram of squared log returns plt.figure(dpi=100) plt.hist(data_diff["kospi"].values, bins=30, density=True) x=np.sort(stats.norm.rvs(loc=mu, scale=std, size=1000, random_state=3)) y=[stats.norm.pdf(i, mu, std) for i in x] plt.plot(x, y, color="red") plt.xlabel("kospi", size=12, weight="bold") plt.ylabel("Density", size=12, weight="bold") plt.title("(d) Historgram", size=13, weight="bold") plt.show()위 그림 (a)는 로그 반환값에는 자기상관이 거의 없음을 나타내지만 제곱된 인스턴스는 분명히 유의미한 ACF 추정치를 보여주기 때문에 로그 수익률은 독립적이지 않으며, 이는 주로 변동성 클러스터링으로 인한 것입니다. 또한 정규 플롯은 가우스 분포의 가정에 의심을 가질 수 있습니다. 즉, 양쪽 꼬리 부분은 이 가정에 부합하지 않음을 나타냅니다. 위의 결과는 시계열의 정상성을 유지할 수 없습니다. 그러므로 Gaussian Random Walk는 이 데이터에 대한 좋은 모델로 간주될 수 없습니다. 대신에 시계열의 조건부 분산에 대한 종속성을 허용하는 GARCH 유형 모델을 사용할 수 있습니다.
댓글
댓글 쓰기