다중 요인 전략을 사용하여 강력한 암호 자산 투자 포트폴리오 구축 #대분류 요인 분석: 요인 합성 편#
^저자:LUCIDA \& FALCON^
이전 회차에 이어, 《다중 요인 모델을 사용하여 강력한 암호 자산 포트폴리오 구축하기》 시리즈 기사에서 우리는 세 편을 발표했습니다: 《이론 기초篇》、《데이터 전처리篇》、《요인 유효성 검증篇》。
앞의 세 편은 각각 다중 요인 전략의 이론과 단일 요인 테스트의 단계를 설명했습니다.
1. 요인 상관성 검증의 이유: 다중 공선성
우리는 단일 요인 테스트 부분을 통해 유효한 요인 집합을 선별했지만, 위의 요인은 직접 데이터베이스에 저장할 수 없습니다. 요인 자체는 구체적인 경제적 의미에 따라 대분류로 나눌 수 있으며, 동일 유형의 요인 간에는 강한 상관성이 존재합니다. 상관성 검증 없이 직접 데이터베이스에 저장하면, 서로 다른 요인에 대해 다중 선형 회귀를 통해 기대 수익률을 구할 때 다중 공선성 문제가 발생할 수 있습니다. 계량 경제학에서, 다중 공선성이란 회귀 모델의 일부 또는 모든 설명 변수가 "완전"하거나 정확한 선형 관계(각 변수 간의 높은 상관성)를 갖는 것을 의미합니다.
따라서 유효한 요인을 선별한 후, 먼저 대분류에 따라 요인의 상관성을 T 검정으로 검증해야 하며, 상관성이 높은 요인에 대해서는 유의성이 낮은 요인을 버리거나 요인을 합성해야 합니다.
다중 공선성의 수학적 설명은 다음과 같습니다:
다중 공선성으로 인한 결과:
완전 공선성 하에서 매개변수 추정량이 존재하지 않음
근사 공선성 하에서 OLS 추정량 비효율적
2. 단계 1: 동일 유형 요인의 상관성 검증
새로 구한 요인과 이미 데이터베이스에 저장된 요인의 상관성을 검증합니다. 일반적으로 두 가지 유형의 데이터로 상관성을 구합니다:
모든 토큰의 백테스트 기간 동안의 요인 값을 기준으로 상관성 계산
모든 토큰의 백테스트 기간 동안의 요인 초과 수익 값을 기준으로 상관성 계산
3. 단계 2: 요인 선택, 요인 합성
상관성이 높은 요인 집합에 대해 두 가지 방법으로 처리할 수 있습니다:
(1) 요인 선택
요인 자체의 ICIR 값, 수익률, 거래량, Sharpe 비율을 기준으로 특정 차원에서 가장 유효한 요인을 선택하여 보존하고, 다른 요인은 삭제합니다.
(2) 요인 합성
요인 집합 내의 요인을 합성하여 단면에서 가능한 많은 유효 정보를 보존합니다.
현재 처리할 3개의 요인 행렬이 있다고 가정합니다:
synthesis = pd.concat([a,b,c],axis = 1)
synthesis
a b c
BTC.BN 0.184865 -0.013253 -0.001557
ETH.BN 0.185691 0.022708 0.031793
BNB.BN 0.242072 -0.180952 -0.067430
LTC.BN 0.275923 -0.125712 -0.049596
AAVE.BN 0.204443 -0.000819 -0.006550
... ... ... ...
SOC.BN 0.231638 -0.095946 -0.049495
AVAX.BN 0.204714 -0.079707 -0.041806
DAO.BN 0.194990 0.022095 -0.011764
ETC.BN 0.184236 -0.021909 -0.013325
TRX.BN 0.175118 -0.055077 -0.039513
2.1 동등 가중치
각 요인의 가중치가 동일(w=1/요인 개수)하며, 종합 요인은 각 요인 값을 합산하여 평균을 구합니다.
예: 모멘텀 계열 요인으로, 한 달 수익률, 두 달 수익률, 세 달 수익률, 여섯 달 수익률, 열두 달 수익률 이 여섯 개 요인의 요인 적재는 각각 1/6의 가중치를 차지하며, 새로운 모멘텀 요인 적재를 합성한 후 다시 표준화 처리를 진행합니다.
`synthesis1 = synthesis.mean(axis=1) # 행별 평균 계산
`
2.2 역사적 IC 가중치, 역사적 ICIR, 역사적 수익 가중치
백테스트 기간의 IC 값(ICIR 값, 역사적 수익 값)을 기준으로 요인에 가중치를 부여합니다. 과거에는 여러 기간이 있었고, 각 기간마다 IC 값이 있으므로, 이들의 평균을 요인의 가중치로 사용합니다. 일반적으로 백테스트 기간 IC의 평균(산술 평균)을 가중치로 사용합니다.
# 가중치 정규화 (후속 문서에서의 요인 가중치 방법도 기본적으로 가중치 정규화가 필요함)
w_IC = ic.mean() / ic.mean().sum()
w_ICIR = icir.mean() / icir.mean().sum()
w_Ret = Return.mean() / Return.mean().sum()
synthesis2 = (synthesis * w_IC).sum(axis=1)
synthesis2 = (synthesis * w_ICIR).sum(axis=1)
synthesis2 = (synthesis * w_Ret).sum(axis=1)
2.3 역사적 IC 반감기 가중치, 역사적 ICIR 반감기 가중치
2.1과 2.2는 모두 산술 평균을 계산하며, 백테스트 기간의 각 IC, ICIR이 요인에 미치는 영향이 동일하다고 가정합니다.
하지만 현실에서는 백테스트 기간의 각 기간이 현재 기간에 미치는 영향 정도가 완전히 동일하지 않으며, 시간에 따른 감쇠가 존재합니다. 현재 기간에 가까울수록 영향이 크고, 멀어질수록 영향이 작아집니다. 이 원리에 따라 IC 가중치를 구하기 전에 먼저 반감기 가중치를 정의하며, 현재 기간에 가까운 가중치 값이 더 크고, 멀어질수록 가중치가 작아집니다.
반감기 가중치 수학적 유도
2.4 ICIR 최대화 가중치
방정식을 풀어 ICIR을 최대화하는 최적 요인 가중치 w를 계산합니다.
공분산 행렬의 추정 문제: 공분산 행렬은 서로 다른 자산 간의 연관성을 측정하는 데 사용됩니다. 통계학에서는 샘플 공분산 행렬이 전체 공분산 행렬을 대체하는 경우가 많지만, 샘플 수가 부족할 경우 샘플 공분산 행렬과 전체 공분산 행렬 간의 차이가 클 수 있습니다. 따라서 압축 추정 방법이 제안되었으며, 원리는 추정된 공분산 행렬과 실제 공분산 행렬 간의 평균 제곱 오차를 최소화하는 것입니다.
방법:
- 샘플 공분산 행렬
# ICIR 최대화 가중치(샘플 공분산)
ic_cov = np.array(ic.cov())
inv_ic_cov = np.linalg.inv(ic_cov)
ic_vector = np.mat(ic.mean())
w = inv_ic_cov * ic_vector.T
w = w / w.sum()
synthesis4 = (synthesis * pd.DataFrame(w,index=synthesis.columns)[0]).sum(axis=1)
- Ledoit-Wolf 수축: 축소 계수를 도입하여 원래의 공분산 행렬과 단위 행렬을 혼합하여 노이즈의 영향을 줄입니다.
# ICIR 최대화 가중치(Ledoit-Wolf 압축 추정 공분산)
from sklearn.covariance import LedoitWolf
model=LedoitWolf()
model.fit(ic)
ic_cov_lw = model.covariance_
inv_ic_cov = np.linalg.inv(ic_cov_lw)
ic_vector = np.mat(ic.mean())
w = inv_ic_cov*ic_vector.T
w = w/w.sum()
synthesis4 = (synthesis * pd.DataFrame(w,index=synthesis.columns)[0]).sum(axis=1)
- Oracle 근사 수축: Ledoit-Wolf 수축의 개선으로, 공분산 행렬을 조정하여 샘플 크기가 작은 경우에도 실제 공분산 행렬을 더 정확하게 추정하는 것을 목표로 합니다. (프로그래밍 구현은 Ledoit-Wolf 수축과 유사합니다)
2.5 주성분 분석 PCA
주성분 분석(Principal Component Analysis, PCA)은 차원 축소 및 데이터의 주요 특성을 추출하는 데 사용되는 통계적 방법입니다. 그 목표는 선형 변환을 통해 원래 데이터를 새로운 좌표계로 매핑하여 데이터가 새로운 좌표계에서 분산이 최대화되도록 하는 것입니다.
구체적으로, PCA는 먼저 데이터에서 주성분을 찾습니다. 즉, 데이터에서 분산이 가장 큰 방향을 찾습니다. 그런 다음 첫 번째 주성분과 직교(무관)하며 최대 분산을 가지는 두 번째 주성분을 찾습니다. 이 과정은 데이터의 모든 주성분을 찾을 때까지 반복됩니다.
# 주성분 분석(PCA)
from sklearn.decomposition import PCA
model1 = PCA(n_components=1)
model1.fit(f)
w=model1.components_
w=w/w.sum()
weighted_factor=(f*pd.DataFrame(w,columns=f.columns).iloc[0]).sum(axis=1)