Post

EWMA & EWMS - 메모리 O(1) 과 Irregular Interval 처리

EWMA(지수가중이동평균)와 EWMS를 O(1) 메모리로 구현하고, 반감기(half-life)를 이용해 불규칙 간격 데이터를 처리하는 방법을 수학적으로 설명합니다.

EWMA & EWMS - 메모리 O(1) 과 Irregular Interval 처리

EWMA(Exponentially Weighted Moving Average)는 직전 평균값만 재활용하는 재귀식으로, 메모리 O(1)만으로 지수 가중 평균을 계산합니다. 반감기(half-life)를 도입하면 데이터가 불규칙한 간격으로 들어오는 실제 매매 환경에서도 동일한 프레임워크를 그대로 적용할 수 있습니다.

금융 데이터 분석에서 평균과 합은 매우 빈번하게 사용됩니다. 평균은 현재 값이 일상적인 수준에서 얼마나 벗어났는지 판단하거나 변동성을 계산할 때, 합은 대표적으로 OFI(이후 글에서 다루겠습니다)나 일정 시간 동안의 체결 값을 집계할 때 쓰입니다.

이 참으로 일견 단순하고도 익숙한 평균과 합은 매매 시스템 개발 관점에서 미묘한 포인트가 있습니다. 일단 식을 한번 써보겠습니다.

\[\mu_t \mathrel{:=} \frac{1}{t} \sum_{i=1}^{t} x_i \tag{1}\] \[S_t \mathrel{:=} \sum_{i=1}^{t} x_i \tag{2}\]

단순한 위 수식과 다르게 실제 매매 환경에서는 신경을 써야 할 포인트가 두 개 정도 있습니다.

첫째로 메모리 부분입니다. 10분 동안의 평균을 쓴다고 해봅시다. 일단 먼저 heap 할당이 들어갑니다. 10분 동안 얼마나 많은 데이터가 들어올지 알 수가 없으니까요. 데이터 저장 자체도 문제입니다. 분석하는 피쳐가 많아질수록 타임시리즈를 전부 가지고 있으면 캐시를 차지하는 데이터가 점점 많아집니다. 매매 시스템에는 피쳐뿐만 아니라 계좌, 전략, 소켓 등 많은 것들이 들어가고, 그런 것들이 L3, L2를 들락날락거리게 되고 최악의 경우 DRAM 영역을 참조하게 될 수도 있습니다. 메모리는 항상 작게 유지하는 것이 좋습니다.

둘째로 데이터는 일관된 간격으로 들어오지 않습니다. 약간 극단적인 예시를 들어볼까요. 10초 평균을 계산하는데 1초, 2초, 10초에 데이터가 들어왔다고 해봅시다. 그러면 3개를 더해서 3으로 나누는 게 합리적일까요? 뭔가 아리송합니다. 마지막 데이터와 두 번째 데이터가 너무 멀고, 처음 두 개의 데이터는 마지막 데이터보다 덜 중요해 보입니다.

이 두 가지 문제 — 메모리 O(1), irregular interval — 에 대해 이번 글에서 다루겠습니다. 먼저 평균을 어떻게 다루는지 중점적으로 살펴보겠습니다. 평균을 이해하시면 합은 일종의 응용으로 쉽게 이해됩니다.

Exponentially Weighted Moving Average (EWMA)

EWMA는 위에서 설명한 메모리 문제를 깔끔하게 해결합니다. 대신 평균을 계산하는 방식을 조금 바꿉니다. 직관을 설명하기 위해 평균식 $(1)$을 풀어서 써보겠습니다.

\[\mu_t = \frac{1}{t}\,x_t + \frac{1}{t}\,x_{t-1} + \cdots + \frac{1}{t}\,x_1\]

계수들의 합은

\[\underbrace{\frac{1}{t} + \frac{1}{t} + \cdots + \frac{1}{t}}_{t\text{개}} = t \cdot \frac{1}{t} = 1\]

이 됩니다. 다시 돌아와서, 저희의 목적은 평균의 대안을 고안해 보는 것인데요. 대안으로 사용하려면 적어도 계수의 합이 위와 같이 1이 되는 성질은 유지해야 합니다.

더불어 저희는 $x_1, x_2, \ldots, x_t$를 전부 저장하지 않고 메모리를 절약하는 방식의 평균을 찾고 있습니다. 직전 평균값을 재활용하면 해결할 수 있을 것 같습니다. $0 < \alpha < 1$에 대해 다음과 같이 정의합니다.

\[\bar{\mu}_0 \mathrel{:=} x_0\] \[\bar{\mu}_t \mathrel{:=} \alpha \, x_t + (1 - \alpha)\,\bar{\mu}_{t-1} \tag{$\ast$}\]

이 재귀식은 새로운 관측값 $x_t$와 직전 평균 $\bar{\mu}_{t-1}$만 있으면 계산할 수 있으므로 메모리 $O(1)$로 충분합니다. $\alpha$가 클수록 최근 데이터에 더 큰 가중치를 부여합니다.

이제 계수의 합이 1이 되는지 확인해 볼까요? 식 $(\ast)$를 펼쳐 보겠습니다.

\[\begin{aligned} \bar{\mu}_t &= \alpha \, x_t + (1 - \alpha)\,\bar{\mu}_{t-1} \\ &= \alpha \, x_t + (1 - \alpha)\bigl[\alpha \, x_{t-1} + (1 - \alpha)\,\bar{\mu}_{t-2}\bigr] \\ &= \alpha \, x_t + \alpha(1-\alpha)\,x_{t-1} + (1-\alpha)^2\,\bar{\mu}_{t-2} \\ &\;\;\vdots \\ &= \alpha \sum_{k=0}^{t-1}(1-\alpha)^k\,x_{t-k} \;+\; (1-\alpha)^t\,x_0 \end{aligned}\]

계수의 합을 구하면

\[\alpha \sum_{k=0}^{t-1}(1-\alpha)^k + (1-\alpha)^t = \bigl[1-(1-\alpha)^t\bigr] + (1-\alpha)^t = 1\]

정확히 1이 됩니다.

일반적인 윈도우 평균은 윈도우 바깥의 데이터를 버리지만, EWMA에서는 초기값부터 모든 $x$의 값이 들어갑니다. $x_0$의 계수를 보면 $(1-\alpha)^t$인데, 시간이 지남에 따라 이 값은 0에 가까워집니다. 그리고 $\alpha$가 클수록 이 감소는 더 빠릅니다. 식 $(\ast)$를 보면 $\alpha$는 최신 데이터의 비중입니다. 최신 데이터의 비중이 클수록 과거 데이터의 감쇠 속도가 커지는 자연스러운 결과입니다.

Exponentially Weighted Moving Sum (EWMS)

문헌에서 자주 등장하는 표현은 아닌 것 같습니다만, 저는 이 연산을 EWMS라고 부르고 다음과 같이 정의합니다.

\[\bar{S}_0 \mathrel{:=} x_0\] \[\bar{S}_t \mathrel{:=} x_t + (1 - \alpha)\,\bar{S}_{t-1} \tag{$\ast\ast$}\]

EWMA와 다른 점은 $x_t$의 계수가 $\alpha$에서 1로 바뀐 것뿐입니다. 이 식이 어떤 의미를 갖는지 펼쳐 보겠습니다.

\[\begin{aligned} \bar{S}_t &= x_t + (1-\alpha)\,\bar{S}_{t-1} \\ &= x_t + (1-\alpha)\bigl[x_{t-1} + (1-\alpha)\,\bar{S}_{t-2}\bigr] \\ &= x_t + (1-\alpha)\,x_{t-1} + (1-\alpha)^2\,\bar{S}_{t-2} \\ &= x_t + (1-\alpha)\,x_{t-1} + (1-\alpha)^2\,x_{t-2} + (1-\alpha)^3\,\bar{S}_{t-3} \\ &\;\;\vdots \\ &= \sum_{k=0}^{t}(1-\alpha)^k\,x_{t-k} \end{aligned}\]

가장 직관적으로, $\alpha = 0$이면 모든 계수가 1이 되어 단순한 합이 됩니다. 다만 과거 데이터가 감쇠되지 않으므로 기간합은 아니고 그냥 무한 기간의 합이 되겠죠. $0 < \alpha < 1$이면 EWMA와 마찬가지로 $t$가 커질수록 과거 데이터의 계수가 줄어듭니다.

계수의 합을 보겠습니다.

\[\sum_{k=0}^{t}(1-\alpha)^k = \frac{1-(1-\alpha)^{t+1}}{\alpha}\]

$t$가 커질수록 $1/\alpha$에 수렴합니다. $\alpha$가 클수록, 즉 최신 데이터에 가중치를 많이 줄수록 전체 계수의 합은 줄어듭니다. $\bar{S}_t$의 값 자체가 작아지는 것입니다. 최신 데이터 위주로 더했으니 자연스러운 현상입니다.

Irregular Interval

지금까지 모든 논의는 $x_t$가 일정한 간격으로 들어오는 편안한 상황을 가정했습니다. 실제 상황은 전혀 그렇지 않죠. 이 경우를 다루는 직관적인 방법 중 하나는 가중치 $\alpha$를 반감기로 표현하는 것입니다.

Half-Life

반감기 $h$는 데이터의 가중치가 절반으로 줄어드는 데 걸리는 시간입니다. EWMA의 전개식에서 $x_{t-k}$의 계수는 $(1-\alpha)^k$에 비례합니다. 이 값이 절반이 되는 시점을 구하면

\[(1-\alpha)^h = \frac{1}{2}\] \[1 - \alpha = 2^{-1/h}\]

위 식을 보면 반감기가 $h$일 때 한 틱당 감쇠율은 $1 - \alpha = 2^{-1/h}$라고 이해할 수 있습니다. 그러면 $\Delta t$ 시간이 지난 후의 감쇠율은

\[(1 - \alpha)^{\Delta t} = 2^{-\Delta t / h} \mathrel{:=} \lambda\]

EWMA와 EWMS를 다시 쓰면

\[\bar{\mu}_{t_i} = (1 - \lambda)\,x_{t_i} + \lambda\,\bar{\mu}_{t_{i-1}}\] \[\bar{S}_{t_i} = x_{t_i} + \lambda\,\bar{S}_{t_{i-1}}\]

$\Delta t$가 작으면 $\lambda$는 1에 가까워 직전 값이 거의 유지되고, $\Delta t$가 크면 $\lambda$는 0에 가까워 과거 값이 크게 감쇠됩니다. 등간격($\Delta t = 1$)에서는 $\lambda = 1 - \alpha$가 되어 앞서 정의한 식 $(\ast)$, $(\ast\ast)$와 동일합니다.

This post is licensed under CC BY 4.0 by the author.