시계열 데이터 Trend 감지

2024. 4. 1. 23:22금융 데이터 분석

반응형

앞선 포스팅에서 시계열 데이터에서 변하는 지점을 식별하는 알고리즘을 다뤘다면, 이번 포스팅에서는 시계열 데이터의 트렌드를 감지할 수 있는 방법에 대해서 다뤄보겠습니다.

트렌드는 증가/감소/방향없음으로 나타낼 수 있을 것입니다. Kat 패키지에서는 Mann-Kendall test라는 알고리즘을 활용하여, 현재 시계열 데이터가 어떤 트렌드를 가지고 있는지를 감지합니다.

Mann-Kendall test는 시계열 기간에 있는 모든 지점에 대해서 이원비교를 수행하고 데이터 지점이 n개라고 한다면 총 비교 수는 n(n-1)/2가 됩니다. 모든 쌍을 대상으로 아래와 같이 indicator function을 활용하여 0인지 1인지 -1인지를 결정합니다.

그 후 indicator function들의 값을 합합니다.

활용하는 통계량(statistic $\tau$)는 아래와 같습니다.

 $\tau$는 -1부터 1까지의 값을 가지게 되며, -1이면 단조 감소를, 0이면 방향성 없음을, 1이면 단조 증가를 나타냅니다.

import yfinance as yf
from kats.consts import TimeSeriesData
from trend_mk import MKDetector ## 코드위치 변경을 통한 import


# %%
df = yf.download("NVDA",start="2020-01-01",end="2020-12-31",progress=False)
df = df[["Adj Close"]].reset_index(drop=False)
df.columns = ["time", "price"]

tsd = TimeSeriesData(df)

trend_detector = MKDetector(tsd, threshold=0.9)
time_points = trend_detector.detector(direction="up",window_size=30)


trend_detector.plot(time_points)

빨간색으로 칠해진 기간에 단조 증가 트랜드가 존재함을 확인할 수 있습니다.

Trend를 감지하는 것과 유사하게 현재 시계열 데이터가 어떤 패턴을 가지고 움직이는지를 평가하는 방법론이 있습니다.

Hurst exponent는 현재 시계열 데이터가 Momentum을 가지고 움직이는지, 아니면 평균으로 회귀(Mean-reversion)하는 패턴으로 움직이는지를 평가하는 방법론입니다.

Hurst exponent H의 식은 아래와 같습니다.

즉 시차가 lag $\tat$만큼 차이난다고 가정한다면, 시차보다 표준편차가 크다면 momentum을 가지고 움직인다고 보는 것이고 시차보다 표준편차가 작다면 평균에 붙어서 움직이는 평균회귀과정으로 움직인다고 보는 것입니다. 따라서 1) H > 0.5 일 때 Momentum, 2) H = 0.5일때 random walk, 3)H<0.5일 때 평균회귀과정으로 판단합니다.

import yfinance as yf
import numpy as np
import pandas as pd
    

df = yf.download("^GSPC",start="2000-01-01",end="2019-12-31",progress=False)
df["Adj Close"].plot(title="S&P 500 (years 2000-2019)")

def get_hurst_exponent(ts, max_lag=20):
    """Returns the Hurst Exponent of the time series"""
    lags = range(2, max_lag)
    std_ = [np.std(np.subtract(ts[lag:], ts[:-lag])) for lag in lags]
    hurst_exp = np.polyfit(np.log(lags), np.log(std_), 1)[0]
    return hurst_exp

for lag in [20, 100, 250, 500, 1000]:
    hurst_exp = get_hurst_exponent(df["Adj Close"].values, lag)
    print(f"Hurst exponent with {lag} lags: {hurst_exp:.4f}")
    
    
    """    
    Hurst exponent with 20 lags: 0.4481
    Hurst exponent with 100 lags: 0.4513
    Hurst exponent with 250 lags: 0.4918
    Hurst exponent with 500 lags: 0.5265
    Hurst exponent with 1000 lags: 0.5178
    """

다만 Hurst exponent는 해석과 활용에 주의해야 하는데, 위 S&P 500 그래프를 보면 위로 Trend와 Momentum을 가지고 움직이는 것으로 보이나, Hurst exponent 값은 0.5에 가까워 사실상 Random walk로 움직임을 나타냅니다. 따라서 어떻게 활용할지에 대한 고민이 필요할 것으로 보입니다.

참고:

Mann-Kendall test

https://vsp.pnnl.gov/help/vsample/design_trend_mann_kendall.htm 
http://www.cwejournal.org/index.php/vol12no1/statistical-trend-analysis-of-rainfall-in-amaravathi-river-basin-using-mann-kendall-test
https://www.epa.gov/sites/default/files/2016-05/documents/tech_notes_6_dec2013_trend.pdf      

 

Hurst exponent

https://hjfm.tistory.com/11
https://research.macrosynergy.com/detecting-trends-and-mean-reversion-with-the-hurst-exponent/

반응형