이전 장에 이어서 "다중 요소 모델을 사용하여 강력한 암호화 자산 포트폴리오 구축"에 대한 기사 시리즈 중 "이론적 기본 사항" 및 "데이터 전처리"라는 두 가지 기사를 게시했습니다.
세 번째 글은 요인 타당성 검정입니다.
특정 요인값을 결정한 후에는 먼저 유의성, 안정성, 단조성, 수익률 요구 사항을 충족하는 요인과 선별 요인에 대한 타당성 검정을 수행해야 하며, 요인 타당성 검정은 해당 기간의 요인 값을 분석하여 수행됩니다. 요인의 효율성을 결정하기 위한 기대 수익률 관계. 주로 3가지 고전적인 방법이 있습니다:
IC/IR 방법: IC/IR 값은 팩터 값과 기대 수익률 간의 상관 계수 입니다. 팩터가 클수록 성과가 좋습니다.
T 값(회귀법): T 값은 현재 기간의 팩터 값에 대한 다음 기간 수익률의 선형 회귀 후 계수의 유의성을 반영합니다. 회귀 계수가 t 테스트를 통과하는지 비교하여 현재의 기여 정도를 나타냅니다. 다음 기간의 수익률에 대한 기간의 요인 값을 판단할 수 있으며 일반적으로 다변량(즉, 다중 요인) 회귀 모델에 사용됩니다.
계층적 백테스팅 방법: 계층적 백테스팅 방법은 요소 값을 기준으로 토큰을 계층화한 다음 각 토큰 계층의 수익률을 계산하여 요소의 단조성을 결정합니다.
1. IC/IR법
(1) IC/IR의 정의
IC : 토큰 수익을 예측하는 요소의 능력을 나타내는 정보 계수입니다. 특정 기간의 IC 값은 현재 기간의 팩터 값과 다음 기간의 수익률 사이의 상관 계수입니다.
$$$ ICₜ = 상관관계(fₜ , Rₜ₊₁) $$$
fₜ: 기간 t의 인수 값
Rₜ₊₁: 기간 t+1의 토큰 수익률
IC∈(-1,1), IC 팩터가 클수록 통화 선택 능력이 강해집니다.
IC가 1에 가까울수록 팩터 값과 다음 기간의 수익률 사이의 양의 상관 관계가 더 강합니다. IC=1은 해당 팩터의 통화 선택이 100% 정확하다는 것을 의미합니다. 가장 높은 순위 점수를 가진 토큰에 해당합니다. 선택한 토큰은 다음 포지션 조정 주기에 사용되며, 이는 가장 큰 증가입니다.
IC가 -1에 가까울수록 팩터 값과 다음 기간의 수익률 사이의 음의 상관관계가 더 강해집니다. IC=-1인 경우 순위가 가장 높은 토큰이 다음 재조정 주기에서 가장 큰 하락세를 보일 것임을 의미합니다. , 이는 완전한 반전입니다.
IC가 0에 가까울수록 해당 팩터의 예측력이 극도로 약하다는 의미로, 해당 팩터는 토큰에 대한 예측력이 없음을 의미합니다.
IR: 안정적인 알파를 얻는 요인의 능력을 나타내는 정보 비율입니다. IR은 모든 기간의 평균 IC를 모든 기간의 IC 표준편차로 나눈 값입니다.
$$$ IR = 평균(ICₜ) / 표준(ICₜ) $$$
IC의 절대값이 0.05(0.02)보다 크면 해당 팩터의 주식 선택 능력이 강한 것입니다. IR이 0.5보다 크면 해당 팩터는 안정적으로 초과수익을 얻을 수 있는 능력이 강한 것입니다.
(2) IC 계산 방법
- 일반 IC(피어슨 상관): 가장 고전적인 상관 계수인 피어슨 상관 계수를 계산합니다. 그러나 이 계산 방법에는 데이터가 연속적이고, 정규 분포를 따르며, 두 변수가 선형 관계를 만족한다는 등 많은 가정이 있습니다.
$$$ ICₚₑₐᵣₛₒₙ,ₜ = cov(fₜ , Rₜ₊₁)/√var(fₜ)var(Rₜ₊₁) = ∑ᵗₜ₌₁(fₜ - fₜ)(Rₜ₊₁ - Rₜ₊₁) /√ ∑ᵗₜ ₌₁(fₜ - fₜ)²(Rₜ₊₁ - Rₜ₊₁)² $$$
- 순위 IC(Spearman 순위 상관계수): Spearman 순위 상관계수를 계산하고, 먼저 두 변수를 순서 한 후 순서 결과를 바탕으로 Pearson 상관계수를 계산합니다. Spearman 순위 상관 계수는 두 변수 간의 단조 관계를 평가하며 순서 값으로 변환되므로 데이터 이상값의 영향을 덜 받는 반면 Pearson 상관 계수는 두 변수 간의 선형 관계를 평가합니다. 원본 데이터이지만 데이터 이상값의 영향도 크게 받습니다. 실제 계산에서는 순위 IC를 찾는 것이 더 일관성이 있습니다.
(3) IC/IR 메소드 코드 구현
날짜 및 시간의 오름차순으로 고유한 날짜 및 시간 값 목록 생성 - 재조정 날짜 기록 def choosedate(dateList,cycle)
class TestAlpha(object): def __init__(self,ini_data): self.ini_data = ini_data def chooseDate(self,cycle,start_date,end_date): ''' cycle: day, month, quarter, year df: 原始数据框df,date列的处理''' chooseDate = [] dateList = sorted(self.ini_data[self.ini_data['date'].between(start_date,end_date)]['date'].drop_duplicates().values) dateList = pd.to_datetime(dateList) for i in range(len(dateList)-1): if getattr(dateList[i], cycle) != getattr(dateList[i + 1], cycle): chooseDate.append(dateList[i]) chooseDate.append(dateList[-1]) chooseDate = [date.strftime('%Y-%m-%d') for date in chooseDate] return chooseDate def ICIR(self,chooseDate,factor): # 1.先展示每个调仓日期的IC,即ICt testIC = pd.DataFrame(index=chooseDate,columns=['normalIC','rankIC']) dfFactor = self.ini_data[self.ini_data['date'].isin(chooseDate)][['date','name','price',factor]] for i in range(len(chooseDate)-1): # (1) normalIC X = dfFactor[dfFactor['date'] == chooseDate[i]][['date','name','price',factor]].rename(columns={'price':'close0'}) Y = pd.merge(X,dfFactor[dfFactor['date'] == chooseDate[i+1]][['date','name','price']], on=['name']).rename(columns={'price':'close1'}) Y['returnM'] = (Y['close1'] - Y['close0']) / Y['close0'] Yt = np.array(Y['returnM']) Xt = np.array(Y[factor]) Y_mean = Y['returnM'].mean() X_mean = Y[factor].mean() num = np.sum((Xt-X_mean)*(Yt-Y_mean)) den = np.sqrt(np.sum((Xt-X_mean)**2)*np.sum((Yt-Y_mean)**2)) normalIC = num / den # pearson correlation # (2) rankIC Yr = Y['returnM'].rank() Xr = Y[factor].rank() rankIC = Yr.corr(Xr) testIC.iloc[i] = normalIC, rankIC testIC =testIC[:-1] # 2.基于ICt,求['IC_Mean', 'IC_Std','IR','IC<0占比--因子方向','|IC|>0.05比例'] ''' ICmean: |IC|>0.05, 因子的选币能力较强,因子值与下期收益率相关性高。|IC|<0.05,因子的选币能力较弱,因子值与下期收益率相关性低IR: |IR|>0.5,因子选币能力较强,IC值较稳定。|IR|<0.5,IR值偏小,因子不太有效。若接近0,基本无效IClZero(IC less than Zero): IC<0占比接近一半->因子中性.IC>0超过一大半,为负向因子,即因子值增加,收益率降低ICALzpF(IC abs large than zero poin five): |IC|>0.05比例偏高,说明因子大部分有效''' IR = testIC.mean()/testIC.std() IClZero = testIC[testIC<0].count()/testIC.count() ICALzpF = testIC[abs(testIC)>0.05].count()/testIC.count() combined =pd.concat([testIC.mean(),testIC.std(),IR,IClZero,ICALzpF],axis=1) combined.columns = ['ICmean','ICstd','IR','IClZero','ICALzpF'] # 3.IC 调仓期内IC的累积图print("Test IC Table:") print(testIC) print("Result:") print('normal Skewness:',combined['normalIC'].skew(),'rank Skewness:',combined['rankIC'].skew()) print('normal Skewness:',combined['normalIC'].kurt(),'rank Skewness:',combined['rankIC'].kurt()) return combined,testIC.cumsum().plot()
2. T-값 검정(회귀법)
T값법은 현재기간의 팩터값과 차기기간의 수익률과의 관계를 검증하는 방법이기도 하지만 둘 사이의 상관관계를 분석하는 점에서 ICIR법과는 다르다. 종속변수 Y로, 현재 기간의 요인 값을 독립변수 X로 반환합니다. X 회귀의 경우 요인 값의 회귀계수에 대해 t 검정을 수행하여 0과 유의하게 다른지, 즉 요인이 이 기간의 수익률은 다음 기간의 수익률에 영향을 미칩니다.
이 방법의 핵심은 이변량 회귀 모델을 해결하는 것입니다. 구체적인 공식은 다음과 같습니다.
$$$ Rₜ₊₁ = αₜ + βₜfₜ + μₜ $$$
Rₜ₊₁: t+1 기간의 토큰 수익률
fₜ: 기간 t의 인수 값
βₜ : t기간 팩터값의 회귀계수, 즉 팩터 수익률
αₜ: Rₜ₊₁에 대한 모델에 포함되지 않은 모든 변수의 평균 영향을 반영하는 절편 항입니다.
(1) 회귀방법론
유의 수준 α를 일반적으로 10%, 5% 또는 1%로 설정합니다.
검정 가설: $$H₀ : βₜ =0$$, $$H₁ : βₜ ≠ 0$$
$$$ T 통계량 = (βʌₜ - βₜ) / se(βʌₜ) ~ tα/²(nk) $$$
k: 회귀 모델의 매개변수 수
- |t statistic| > |tα/²(nk)| → H₀이 기각되면, 즉 이 기간의 팩터 값 fₜ가 다음 기간의 수익률 Rₜ₊₁에 큰 영향을 미칩니다.
(2) 회귀 메소드 코드 구현
def regT(self,chooseDate,factor,return_24h): testT = pd.DataFrame(index=chooseDate,columns=['coef','T']) for i in range(len(chooseDate)-1): X = self.ini_data[self.ini_data['date'] == chooseDate[i]][factor].values Y = self.ini_data[self.ini_data['date'] == chooseDate[i+1]][return_24h].values b, intc = np.polyfit(X, Y, 1) # 斜率ut = Y - (b * X + intc) # 求t值t = (\hat{b} - b) / se(b) n = len(X) dof = n - 2 # 自由度std_b = np.sqrt(np.sum(ut**2) / dof) t_stat = b / std_b testT.iloc[i] = b, t_stat testT = testT[:-1] testT_mean = testT['T'].abs().mean() testTL196 = len(testT[testT['T'].abs() > 1.96]) / len(testT) print('testT_mean:',testT_mean) print('T值大于1.96的占比:',testTL196) return testT
3. 계층화된 백테스팅 방법
계층화는 모든 토큰을 계층화하는 것을 의미하고, 백테스팅은 토큰 조합의 각 계층에 대한 수익률을 계산하는 것을 의미합니다.
(1) 계층화
먼저, 토큰 풀에 해당하는 팩터 값을 구하고, 팩터 값에 따라 토큰을 순서. 순서. 즉, 요소 값이 작은 것이 먼저 순위를 매기고, 순서 에 따라 토큰을 균등하게 나눕니다. 레이어 0 토큰의 요소 값이 가장 작고, 레이어 9 토큰의 요소 값이 가장 큽니다.
이론적으로 "균등 분할"은 토큰 수를 균등하게 분할 것을 의미합니다. 즉, 각 계층의 토큰 수는 동일하며 분위수의 도움으로 달성됩니다. 실제로 토큰의 총 개수는 반드시 레이어 수의 배수가 아닙니다. 즉, 각 레이어의 토큰 수가 반드시 동일하지는 않습니다.
(2) 백테스팅
토큰을 팩터 값의 오름차순으로 10개의 그룹으로 나눈 후, 각 토큰 조합의 수익률 계산을 시작합니다. 이 단계에서는 각 계층의 토큰을 투자 포트폴리오로 취급하고(각 계층의 토큰 포트폴리오에 포함된 토큰은 다양한 백테스트 기간 동안 변경됨) 다음 기간에 포트폴리오의 전체 수익률을 계산합니다. ICIR과 t-value는 현재 기간의 팩터값과 다음 기간의 전체 수익률을 분석하지만, 계층적 백테스팅에서는 백테스팅 기간 동안 거래일별로 계층적 포트폴리오의 수익률을 계산해야 한다. 여러 기간의 백테스팅 기간이 있으므로 각 기간마다 계층화 및 백테스팅이 필요합니다. 마지막으로 각 계층의 토큰 반환율을 누적 곱하여 토큰 조합의 누적 반환율을 계산합니다.
이상적으로는 좋은 팩터의 경우 그룹 9의 곡선 수익률이 가장 높고 그룹 0의 곡선 수익률이 가장 낮습니다.
그룹 9에서 그룹 0을 뺀 곡선(즉, 롱-숏 수익률)은 단조로운 증가를 보여줍니다.
(3) 계층적 백테스팅 방법의 코드 구현
def layBackTest(self,chooseDate,factor): f = {} returnM = {} for i in range(len(chooseDate)-1): df1 = self.ini_data[self.ini_data['date'] == chooseDate[i]].rename(columns= {'price':'close0'}) Y = pd.merge(df1,self.ini_data[self.ini_data['date'] == chooseDate[i+1]] [['date','name','price']],left_on=['name'],right_on=['name']).rename(columns= {'price':'close1'}) f[i] = Y[factor] returnM[i] = Y['close1'] / Y['close0'] -1 labels = ['0','1','2','3','4','5','6','7','8','9'] res = pd.DataFrame(index=['0','1','2','3','4','5','6','7','8','9','LongShort']) res[chooseDate[0]] = 1 for i in range(len(chooseDate)-1): dfM = pd.DataFrame({'factor':f[i],'returnM':returnM[i]}) dfM['group'] = pd.qcut(dfM['factor'], 10, labels=labels) dfGM = dfM.groupby('group').mean()[['returnM']] dfGM.loc['LongShort'] = dfGM.loc['0']- dfGM.loc['9'] res[chooseDate[i+1]] = res[chooseDate[0]] * (1 + dfGM['returnM']) data = pd.DataFrame({'分层累积收益率':res.iloc[:10,-1],'Group': [0,1,2,3,4,5,6,7,8,9]}) df3 = data.corr() print("Correlation Matrix:") print(df3) return res.T.plot(title='Group backtest net worth curve')
루시다 & 팔콘 소개
루시다( https://www.lucida.fund/ )는 2018년 4월 암호화폐 시장에 진출한 업계 최고의 퀀트 헤지펀드입니다. 현재 관리 규모로 CTA/통계 차익거래/옵션 변동성 차익거래 및 기타 전략을 주로 거래합니다. 3천만 달러.
Falcon( https://falcon.lucida.fund/ )은 차세대 Web3 투자 인프라로, 다중 요소 모델을 기반으로 하며 사용자가 암호화폐를 "선택", "구매", "관리" 및 "판매"하도록 돕습니다. 자산. 매는 2022년 6월 루시다가 부화했습니다.
더 많은 콘텐츠는 https://linktr.ee/lucida_and_falcon에서 확인할 수 있습니다.