시계열

시계열time series (4)

nova-unum 2022. 8. 5. 13:48

시계열time series (4)

이동창 함수

● 지수 가중 함수

● 이진 이동창 함수

● 사용자 정의 이동창 함수


시계열 연산에서 사용되는 배열 변형에서 중요한 요소는 움직이는 창 또는 지수 가중과 함께 수행되는 통계와 여타 함수들이다. 이런 함수를 이용해서 누락된 데이터로 인해 매끄럽지 않은 시계열 데이터를 매끄럽게 다듬을 수 있다. 지수 가중 이동평균처럼 고정 크기의 창을 가지지 않는 함수도 포함해서 이동창 함수 moving window function 라고 부른다. 다른 통계함수와 마찬가지로 이동참 함수도 누락된 데이터를 자동으로 배제한다.

우선 시계열 데이터를 불러와서 영업일 빈도로 리샘플링하자.

close_px_all = pd.read_csv('examples/stock_px_2.csv', parse_dates=True, index_col=0)
close_px = close_px_all[['AAPL','MSFT','XOM']]
close_px.head(3)

 

close_px = close_px.resample('B').ffill()

resample이나 groupby와 유사하게 작동하는 rolling 연산을 알아보자. 이는 Series나 DataFrame에 대해 원하는 기간을 나타내는 window 값과 함께 호출할 수 있다. 

close_px.AAPL.plot()
close_px.AAPL.rolling(250).mean().plot()

rolling(250)이라는 표현은 groupby와 비슷해 보이지만 그룹을 생성하는 대신 250일 크기의 움직이는 창을 통해 그룹핑할 수 있는 객체를 생성한다. 

rolling 함수는 기본적으로 해당 원도우 내에는 결측치가 없기를 기대하지만 시계열의 시작 지점에서는 필연적으로 window보다 적은 기간의 데이터를 가지고 있으므로 이를 처리하기 위해 rolling 함수의 동작 방식은 변경될 수 있다.

appl_std250 = close_px.AAPL.rolling(250, min_periods=10).std()
appl_std250[5:12]
2003-01-09         NaN
2003-01-10         NaN
2003-01-13         NaN
2003-01-14         NaN
2003-01-15    0.077496
2003-01-16    0.074760
2003-01-17    0.112368
Freq: B, Name: AAPL, dtype: float64

애플의 250일 일별 수익 표준편차

appl_std250.plot()

확장창 평균 expanding window mean을 구하기 위해서는 rolling 대신 expanding을 사용한다. 확장창 평균은 시계열의 시작 지점에서부터 창의 크기가 시계열의 전체 크기가 될 때까지 점점창의 크기를 늘린다. apple_std250 시계열의 확장창 평균은 아래처럼 구할 수 있다.

expanding_mean = appl_std250.expanding().mean()

DataFrame에 대해 이동창 함수를 호출하면 각 컬럼에 적용된다.

close_px.rolling(60).mean().plot(logy=True)

rolling 함수는 고정 크기의 기간 지정 문자열을 넘겨서 호출할 수도 있다. 빈도가 불규칙한 시계열일 경우 유용하게 사용할 수 있다.  resample 함수에서 사용하던 것과 같은 형식이다. 예를 들어 20일 크기의 이동평균은 아래처럼 구할 수 있다.

close_px.rolling('20D').mean()

지수 가중 함수

균등한 가중치를 가지는 관찰과 함께 고정 크기 창을 사용하는 다른 방법은 감쇠인자 decay factor 상수에 좀 더 많은 가중치를 줘서 더 최근 값을 관찰하는 것이다. 감쇠인자 상수를 지정하는 방법은 몇 가지 있는데 널리 쓰는 방법은 기간을 이용하는 것이다. 이 방법은 결과를 같은 기간의 창을 가지는 단순 이동창 함수와 비교 가능하도록 해준다.

지수 가중 통계는 최근 값에  좀 더 많은 가중치를 두는 방법이므로 균등 가중 방식에 비해 좀더 빠르게 변화를 수용한다.

pandas는 rolling이나 expanding과 함게 사용할 수 있는 ewm 연산을 제공한다. 아래 예제는 애플 주가 60일 이동평균을 span=60으로 구한 지수 가중 이동평균과 비교한 것이다. 

aapl_px = close_px.AAPL['2006':'2007']
ma60 = aapl_px.rolling(30, min_periods=20).mean()
ewma60 = aapl_px.ewm(span=30).mean()
ma60.plot(style='k--', label='Simple MA')
ewma60.plot(style='k-', label='EW MA')
plt.legend()

이진 이동창 함수

상관관계와 공분산 같은 몇몇 통계 연산은 두 개의 시계열을 필요로 한다. 예를 들어보자. 금융분석가는 종종 S&P 500 같은 비교 대상이 되는 지수와 주식의 상관관계에 흥미를 가진다.

spx_px = close_px_all['SPX']
spx_rets = spx_px.pct_change()
returns = close_px.pct_change()

rolling 함수에 이어 호출한 corr 요약함수는 spx_rets와의 상관관계를 계산한다.

corr = returns.AAPL.rolling(125, min_periods=100).corr(spx_rets)
corr.plot()

 

6개월간 S&P 500 지수와 APPL 수익 상관관계

여러 주식과 S&P 지수와의 상관관계를 한번에 계산하고 싶다고 가정하자. 반목문을 작성해서 DataFrame을 생성하면 쉽겠지만 좋은 방법은 아니다. TimeSeires와 DataFrame 그리고 rolling_corr 같은 함수를 넘겨서 TimeSeries( 이 경우에는 spx_rets)와 DataFrame의 각 칼럼 간의 상관관계를 계산하면 된다. 

corr = returns.rolling(125, min_periods=100).corr(spx_rets)
corr.plot()

사용자 정의 이동창 함수

rolling 이나 다른 관련 메서드에 apply를 호출해서 이동창에 대한 사용자 정의 연산을 수행할수 있다. 유일한 요구 사항은 사용자 정의 함수가 배열의 각 조각으로부터 단일 값(감소)을 반환해야 한다는 것이다. 예를 들어 rolling(....).quantile(q)를 사용해서 표본 변위치를 계산할 수 있는 것처럼 전체 표본에서 특정 값이 차지하는 백분위 점수를 구하는 함수를 작성할 수 도 있다. scipy.stats.percentileofscore 함수가 그런 기능을 한다.

 

2%의 연간 AAPL 수익률에 대한 백분위 점수

from scipy.stats import percentileofscore
score_at_2percent = lambda x: percentileofscore(x, 0.02)

result = returns.AAPL.rolling(250).apply(score_at_2percent)
result.plot()