
프로그래밍 방식 거래에서는 이동 평균선이나 변동성 등의 지표를 계산할 때와 같이 평균과 분산을 계산하는 것이 필요한 경우가 많습니다. 고빈도, 장기간 계산이 필요할 때는 장기간의 과거 데이터를 보관해야 하는데, 이는 불필요하고 시간 및 자원이 많이 소모됩니다. 본 논문에서는 가중 평균과 분산을 계산하기 위한 온라인 업데이트 알고리즘을 소개합니다. 이는 실시간 데이터 스트림을 처리하고 거래 전략, 특히 고빈도 전략을 동적으로 조정하는 데 특히 중요합니다. 또한 이 기사에서는 거래자가 이 알고리즘을 실제 거래에 신속하게 적용하고 배포할 수 있도록 돕기 위해 해당 Python 코드 구현을 제공합니다.
\(n\)번째 데이터 포인트의 평균을 나타내기 위해 \(\mu_n\)을 사용하는 경우, 우리는 이미 \({n-1}\)번째 데이터 포인트의 \(\mu_{n-1}\) 평균을 계산했다고 가정합니다. 이제 새로운 데이터 포인트 \(x_{n}\)이 수신되었습니다. 우리는 이 새로운 데이터 포인트를 포함하는 새로운 평균 \(\mu_{n}\)을 계산하고 싶습니다. 다음은 자세한 파생 내용입니다.
\(\mu_n = \frac{1}{n} \sum_{i=1}^{n} x_i\) \(\mu_n = \frac{1}{n} \left( x_n + \sum_{i=1}^{n-1} x_i \right)\) \(\mu_{n-1} = \frac{1}{n-1} \sum_{i=1}^{n-1} x_i\) \((n-1)\mu_{n-1} = \sum_{i=1}^{n-1} x_i\) \(\mu_n = \frac{1}{n} \left( x_n + (n-1)\mu_{n-1} \right)\) \(\mu_n = \mu_{n-1} + \frac{1}{n} (x_n - \mu_{n-1})\)
분산 업데이트 프로세스는 다음 단계로 분해될 수 있습니다.
\(S_n = \sum_{i=1}^{n} (x_i - \mu_n)^2\) \(S_n = \sum_{i=1}^{n} x_i^2 - n\mu_n^2\) \(S_n - S_{n-1} = x_n^2 - n\mu_n^2 + (n - 1)\mu_{n-1}^2\) \(S_n - S_{n-1} = (x_n - \mu_{n-1})(x_n - \mu_n)\) \(S_n = S_{n-1} + (x_n - \mu_{n-1})(x_n - \mu_n)\) \(\sigma_n^2 = \frac{S_n}{n}\)
위의 두 공식에서 볼 수 있듯이 이 프로세스를 사용하면 이전 데이터의 평균과 분산만 유지하고 과거 데이터를 저장하지 않고 각 새 데이터 포인트 \(x_n\)을 받을 때마다 새 평균과 분산을 업데이트할 수 있습니다. 계산이 더 빨라집니다. 하지만 문제는 이런 방식으로 계산하는 것은 전체 표본의 평균과 분산인 반면, 실제 전략에서는 특정 고정 기간을 고려해야 한다는 것입니다. 위의 평균 업데이트를 관찰하면, 새로운 평균 업데이트 양은 과거 평균에서 새로운 데이터의 편차에 비율을 곱한 것임을 알 수 있습니다. 이 비율이 고정되어 있다면, 우리는 다음에 논의할 지수 가중 평균을 얻게 됩니다.
지수 가중 평균은 다음과 같은 재귀 관계로 정의할 수 있습니다.
\(\mu_t = \alpha x_t + (1 - \alpha) \mu_{t-1}\)
여기서 \(\mu_t\)는 시점 \(t\)에서의 지수 가중 평균이고, \(x_t\)는 시점 \(t\)에서의 관측 값이고, \(\alpha\)는 가중치 인자이고, \(\mu_{t-1}\) 는 이전 시점의 지수 가중 평균입니다.
분산의 경우, 각 시점에서 제곱 편차의 지수 가중 평균을 계산해야 합니다. 이는 다음의 재귀 관계를 통해 달성될 수 있습니다.
\(S_n = \alpha S_{n-1} + (1 - \alpha)(x_n - \mu_n)(x_n - \mu_{n-1})\)
여기서 \(\sigma_t^2\)는 시점 \(t\)에서의 지수 가중 분산이고, \(\sigma_{t-1}^2\)는 이전 시점의 지수 가중 분산입니다.
지수 가중 평균과 분산을 관찰하세요. 그들의 증분 업데이트 형태는 직관과 일치합니다. 둘 다 과거 값의 일부를 유지하고 새로운 변화를 추가합니다. 구체적인 파생 과정은 이 논문을 참조할 수 있습니다: https://fanf2.user . srcf.net/hermes/doc/antiforgery/stats.pdf
단순 평균(산술 평균이라고도 함)과 지수 가중 평균은 두 가지 일반적인 통계적 측정 방법으로, 각각 특성과 용도가 다릅니다. 단순 평균은 각 관찰치에 동일한 가중치를 부여하고 데이터 집합의 중심 위치를 반영합니다. 지수 가중 평균은 최근의 관측치에 더 많은 가중치를 두는 재귀적 계산입니다. 관측치가 현재 시간으로부터 멀어질수록 가중치는 기하급수적으로 감소합니다.
단순 평균과 지수 가중 평균은 개념적으로 다르지만, 적절한 \(\alpha\) 값을 선택하면 지수 가중 평균이 특정 개수의 관측치에 대한 단순 평균에 근접하도록 만들 수 있습니다. 이러한 대략적인 관계는 지수 가중 평균의 가중치 인자 \(\alpha\)의 함수인 유효 표본 크기로 설명할 수 있습니다.
단순 이동 평균(SMA)은 주어진 기간 내의 모든 가격의 산술 평균입니다. 시간 창 \(N\)의 경우 SMA의 중심(평균이 있는 곳)은 다음과 같이 간주할 수 있습니다.
\(\text{SMA 중심} = \frac{1 + N}{2}\)
지수 이동 평균(EMA)은 최근 데이터 포인트에 더 큰 가중치를 두는 가중 평균입니다. EMA의 가중치는 시간이 지날수록 기하급수적으로 감소합니다. EMA의 중심은 다음 급수를 합산하여 얻을 수 있습니다.
\(\text{EMA 중심} = \alpha \times \left[1 + 2(1 - \alpha) + 3(1 - \alpha)^2 + \cdots \right] = \frac{1}{\alpha}\)
SMA와 EMA가 같은 질량 중심을 가지고 있다고 가정하면 다음과 같습니다.
\(\frac{1 + N}{2} = \frac{1}{\alpha}\)
이 방정식을 풀면 \(\alpha\)와 \(N\) 사이의 관계를 얻을 수 있습니다.
\(\alpha = \frac{2}{N + 1}\)
즉, 주어진 \(N\)일 SMA에 대해 해당 \(\alpha\) 값을 사용하여 “동등한” EMA를 계산할 수 있으며, 이때 두 EMA는 동일한 질량 중심을 갖고 결과가 매우 유사합니다.
매초 \(\alpha_1\)의 가중치로 업데이트되는 EMA가 있다고 가정해보자. 이는 매초마다 가중치가 \(\alpha_1\)인 새로운 데이터 포인트가 EMA에 추가되고, 기존 데이터 포인트의 영향이 \(1 - \alpha_1\)로 곱해진다는 것을 의미합니다.
업데이트 빈도를 변경하여 \(f\)초마다 업데이트하도록 하면 \(f\)초 내에 데이터 포인트의 총 영향이 1초마다 업데이트할 때와 동일하도록 하는 새로운 가중치 인자 \(\alpha_2\)를 찾고자 합니다. .
\(f\)초 동안 업데이트가 이루어지지 않으면 이전 데이터 포인트의 영향은 \(f\)번 연속적으로 감소하며, 매번 \(1 - \alpha_1\)로 곱해집니다. 따라서 \(f\)초 후의 총 붕괴 인자는 \((1 - \alpha_1)^f\)입니다.
\(f\)초마다 업데이트되는 EMA가 초당 한 번씩 업데이트되는 EMA와 동일한 감소 효과를 한 업데이트 주기에서 갖도록 하기 위해 \(f\)초 후의 총 감소 계수를 한 업데이트의 감소 계수와 같게 설정합니다. 주기:
\((1 - \alpha_1)^f = 1 - \alpha_2\)
이 방정식을 풀면 새로운 가중치 인자 \(\alpha_2\)를 얻습니다.
\(\alpha_2 = 1 - (1 - \alpha_1)^f\)
이 공식은 업데이트 빈도가 변경될 때 EMA 평활화 효과를 일정하게 유지하는 새로운 가중치 계수 \(\alpha_2\)에 대한 근사값을 제공합니다. 예를 들어, 우리는 가격 평균 \(\alpha_1\)을 0.001로 계산하고, 10초마다 최신 가격을 업데이트합니다. 만약 우리가 그것을 1초로 바꾸면, 동등한 \(\alpha_2\)는 약 0.01입니다.
class ExponentialWeightedStats:
def __init__(self, alpha):
self.alpha = alpha
self.mu = 0
self.S = 0
self.initialized = False
def update(self, x):
if not self.initialized:
self.mu = x
self.S = 0
self.initialized = True
else:
temp = x - self.mu
new_mu = self.mu + self.alpha * temp
self.S = self.alpha * self.S + (1 - self.alpha) * temp * (x - self.mu)
self.mu = new_mu
@property
def mean(self):
return self.mu
@property
def variance(self):
return self.S
# 使用示例
alpha = 0.05 # 权重因子
stats = ExponentialWeightedStats(alpha)
data_stream = [] # 数据流
for data_point in data_stream:
stats.update(data_point)
고빈도 프로그래밍 거래에서는 실시간 데이터를 빠르게 처리하는 것이 매우 중요합니다. 계산 효율성을 개선하고 리소스 소비를 줄이기 위해 본 논문에서는 데이터 스트림의 가중 평균과 분산을 지속적으로 계산하는 온라인 업데이트 알고리즘을 소개합니다. 실시간 증분 업데이트 계산은 두 자산 가격 간의 상관 관계, 선형 피팅 등 다양한 통계 데이터와 지표를 계산하는 데에도 활용할 수 있으며, 이는 큰 잠재력을 가지고 있습니다. 증분적 업데이트는 데이터를 신호 시스템으로 취급하는데, 이는 고정 기간 계산에 비해 사고방식이 진화한 것입니다. 귀하의 전략에 과거 데이터 계산을 저장하는 부분이 있는 경우 이 아이디어에 따라 전략을 수정하여 시스템 상태에 대한 추정치만 기록하고, 새로운 데이터가 도착하면 시스템 상태를 업데이트하고 이러한 순환을 계속하는 것이 좋습니다.