이전에 다룬 ACF, PACF 이후 작성하는 부분입니다.
2022.01.20 - [공부/통계학] - ACF (auto-correlative function, 자기상관함수) python
2022.01.20 - [공부/통계학] - PACF (Partial Auto Correlation Function, 편자기상관함수) python
자기상관계수, 편자기상관계수와 다르게 비교상관계수는 두 변수에 대해 시차를 적용시켜 상관계수를 도출하는 것입니다.
바로 코드를 보도록하겠습니다.
# 예시 : 마케팅 비용과 수익간의 상관성 분석
import statsmodels.api as sm
import numpy as np
import matplotlib.pyplot as plt
marketing = np.array([3, 4, 5, 5, 7, 9, 13, 15, 12, 10, 8, 8])
revenue = np.array([21, 19, 22, 24, 25, 29, 30, 34, 37, 40, 35, 30])
cc = sm.tsa.stattools.ccf(marketing, revenue, adjusted=False)
for i in range(len(cc)):
print(f'마케팅 비용과 수익의 {i}번째 기간 후 상관계수 값 : {cc[i] : .5f}')
for i in range(len(cc)):
plt.scatter(i, cc[i])
plt.axvline(x=0, color='k' ,linestyle = ':') # draw x =0 axes
plt.axhline(y=0, color='k' ,linestyle = ':') # draw y =0 axes
plt.title('Cross correlation (marketing, revenue)')
plt.xlabel('after k period')
plt.ylabel('cross corr')
plt.show()
결과
마케팅 비용과 수익의 0번째 기간 후 상관계수 값 : 0.77109
마케팅 비용과 수익의 1번째 기간 후 상관계수 값 : 0.46239
마케팅 비용과 수익의 2번째 기간 후 상관계수 값 : 0.19352
마케팅 비용과 수익의 3번째 기간 후 상관계수 값 : -0.06066
마케팅 비용과 수익의 4번째 기간 후 상관계수 값 : -0.28160
마케팅 비용과 수익의 5번째 기간 후 상관계수 값 : -0.44531
마케팅 비용과 수익의 6번째 기간 후 상관계수 값 : -0.49159
마케팅 비용과 수익의 7번째 기간 후 상관계수 값 : -0.35784
마케팅 비용과 수익의 8번째 기간 후 상관계수 값 : -0.15697
마케팅 비용과 수익의 9번째 기간 후 상관계수 값 : -0.03430
마케팅 비용과 수익의 10번째 기간 후 상관계수 값 : 0.01588
마케팅 비용과 수익의 11번째 기간 후 상관계수 값 : 0.00704
이를 보면 시차가 증가할 수록 감소하다가 다시 영향력이 거의 없어지는 결과를 볼 수 있습니다.
사용한 라이브러리로는 statsmodels의 api에서 추출한 함수로 ccf입니다.
ccf의 하이퍼파라미터를 보면 다음과 같습니다.
"""
The cross-correlation function.
Parameters
----------
x, y : array_like
The time series data to use in the calculation.
adjusted : bool
If True, then denominators for cross-correlation is n-k, otherwise n.
fft : bool, default True
If True, use FFT convolution. This method should be preferred
for long time series.
Returns
-------
ndarray
The cross-correlation function of x and y.
Notes
-----
If adjusted is true, the denominator for the autocovariance is adjusted.
"""
여기서 adjuted를 True로 설정하는 경우, 비교 상관계수의 분모가 n-k가 된다고 합니다. (사실 어떤 차이가 존재하는지 아직은 정확히 모르겠습니다)
또한 fft의 경우, True로 설정한다면, Fast Fourier Transform으로 고속퓨리에 변환을 의미하고 convolution은 합성곱을 의미합니다. 여기서는 시계열의 길이가 긴 경우 설정하도록 권장하고 있습니다. (퓨리에 변환 이게 공대에서 나오는데 시간에 대한 신호함수를 주파수에 대한 식으로 변환하는 것이라합니다... 잘 모르겠습니다 ㅠㅠ)
하지만, 시차 상관계수를 경제에 적용한다면 다음과 같이 해석할 수 있습니다.
예시를 보면, 통화정책 시행으로 M2 감소 충격시, 유가증권 시장에 어떤 영향을 미치고, 지속성은 어떠한지에 대해 알 수 있는 것이지요.
그래서 국내 10년물 국체와 코스피지수의 비교 상관계수를 코드로 구현해보았습니다.
financedatareader (fdr) 라이브러리를 활용하여 2010년부터 2020년 초까지 데이터를 불러옵니다.
import FinanceDataReader as fdr
kr10YT = fdr.DataReader('KR10YT=RR','2010-01-01', '2020-01-01')
ks11 = fdr.DataReader('KS11', '2010-01-01', '2020-01-01')
여기서 이제 전처리를 시행하는데, 순서는 다음과 같습니다.
- 10년간 영업일 전체를 불러오고 기존 데이터와 병합한다.
- 직전값으로 Nan 값을 채워준다.
- 월말 영업일 데이터 (ex. 2018.1.31이 토요일이면 2018.1.30)를 제외한 나머지는 drop한다.
- 전월 대비 변화율을 구한다.
이게 코드로 일일이 다 보여드리면 좀 길어져서 ks11에 대해서만 업로드하려 합니다. (변수명만 변경해주면 전처리 형태는 동일하기에 10년물 국체에도 무관함)
# 월말 영업일 데이터만 추출 시행
# 데이터 인덱스(날짜)를 컬럼으로 형성 후 처음과 끝을 추출
ks11 = ks11.reset_index()
start_date = ks11['Date'].astype(str).iloc[0]
end_date = ks11['Date'].astype(str).iloc[-1]
# 날짜 처음과 끝에서 영업일 기준 freq 적용 후 데이터 프레임 형성
date_all = pd.date_range(start_date, end_date, freq='B').to_frame().rename(columns={0:'Date'}).reset_index(drop=True)
# 데이터 병합 (영업일 date와 10년물 국체 병합)
df_all = pd.merge(date_all,ks11,how='left')
# 직전 값으로 NaN 값 채우기
df_all = df_all.fillna(method='ffill')
# 마지막 영업일 제외후 나머지 drop
df_ks11 = df_all.set_index(df_all['Date'])
# 각 월당 마지막 영업일 도출
month_end = pd.date_range('2010-01-01', '2020-01-01', freq='BM')
# 마지막 영업일 제외후 나머지 drop
ks11_BM = df_ks11[df_ks11['Date'].isin(month_end)].reset_index(drop=True)
ks11_BM = ks11_BM.set_index(ks11_BM['Date'])
ks11_BM = ks11_BM.drop(columns='Date')
# 전월대비 수익률 도출 (pct_change 사용, %로 표현하기 위해 100을 곱해준다)
kospi_bm_return = ks11_BM['Close'].pct_change().dropna()
kospi_bm_return = pd.DataFrame(kospi_bm_return) * 100
kospi_bm_return.head()
>>>
Close
Date
2010-02-26 -0.489881
2010-03-31 6.162751
2010-04-30 2.877396
2010-05-31 -5.759779
2010-06-30 3.475400
그리고 이 데이터에 대해 비교상관계수를 구하면 다음과 같습니다.
# 예시 : 마케팅 비용과 수익간의 상관성 분석
import statsmodels.api as sm
import numpy as np
import matplotlib.pyplot as plt
kr10yt_data = np.array(kr10yt_bm_return['Close'])
ks11_data = np.array(kospi_bm_return['Close'])
cc = sm.tsa.stattools.ccf(ks11_data, kr10yt_data, adjusted=False, fft=True)
for i in range(12):
print(f'10년물 국체수익률과 코스피지수 수익률의 {i}개월 후 상관계수 값 : {cc[i] : .5f}')
for i in range(12):
plt.scatter(i, cc[i])
plt.axvline(x=0, color='k' ,linestyle = ':')
plt.axhline(y=0, color='k' ,linestyle = ':')
plt.title('Cross correlation (KS11, KR10YT)')
plt.xlabel('after k period')
plt.ylabel('cross corr')
plt.show()
>>>
10년물 국체수익률과 코스피지수 수익률의 0개월 후 상관계수 값 : 0.12547
10년물 국체수익률과 코스피지수 수익률의 1개월 후 상관계수 값 : 0.14507
10년물 국체수익률과 코스피지수 수익률의 2개월 후 상관계수 값 : -0.13085
10년물 국체수익률과 코스피지수 수익률의 3개월 후 상관계수 값 : 0.02708
10년물 국체수익률과 코스피지수 수익률의 4개월 후 상관계수 값 : 0.07631
10년물 국체수익률과 코스피지수 수익률의 5개월 후 상관계수 값 : 0.09027
10년물 국체수익률과 코스피지수 수익률의 6개월 후 상관계수 값 : 0.01290
10년물 국체수익률과 코스피지수 수익률의 7개월 후 상관계수 값 : 0.01621
10년물 국체수익률과 코스피지수 수익률의 8개월 후 상관계수 값 : -0.04429
10년물 국체수익률과 코스피지수 수익률의 9개월 후 상관계수 값 : -0.04753
10년물 국체수익률과 코스피지수 수익률의 10개월 후 상관계수 값 : -0.00915
10년물 국체수익률과 코스피지수 수익률의 11개월 후 상관계수 값 : -0.06412
이를 확인해보면 10년물 국체 금리가 변화할때, 1개월 후 KOSPI 지수의 변화하는 정도를 나타내는 상관계수가 가장 높은 절댓값을 가지는 것을 알 수 있습니다. 그리고 점차 상관성은 감소하는 형태를 보이고 있습니다.
물론 이는 11개월 시차까지 적용된 상태이기에 시차를 더 적용시키면 그 이후의 시차에 대해서도 알 수 있을 것입니다.
또한, 어떤 것이 선행지수이고 후행지수인지 알 수 있을 것입니다.
만약 여기서 시차 0일때 상관성이 가장 높게 나왔다면 x,y 변수는 동행지수에 해당하는 것이죠.
이번 포스트는 여기서 마치도록 하겠습니다.
'공부 > 기초통계' 카테고리의 다른 글
확률의 정의 (기초통계) (0) | 2022.04.07 |
---|---|
통계적 추론과 바람직한 추정량 python (0) | 2022.03.25 |
표본과 모집단의 이해 (0) | 2022.03.21 |
오차, 잔차, 편차의 차이 (기초통계) python (0) | 2022.03.19 |
confusion matrix (혼동행렬) python (0) | 2022.03.17 |
댓글