
LUCIDA:用多因子模型去选赛道、选币种
投资小币种,无论是一级还是二级,我把整个过程分成四个部分:选、买、管、卖。『 选 』选包括两部分,选赛道和选币种。『 买 』买有两种方式,一级或者二级,这两个需要的核心能力不一样,一级看重行业资源,二级看重投研能力,目前我没看到,二者各有优劣,目前没看到两个能力都有的机构,这里不展开讲。『 管 』管是指管理投资组合。包括对冲风险、增强收益、调仓等等。『 卖 』卖不解释了。如果你是屯币者或者对某类资产有特殊信仰,当我没说。仅靠逻辑分析,不太靠谱这四块里最难的还是选。市场中的小币种太多,光CMC收录的就有9000多个,再怎么筛选,潜在的投资标的也得有大几十个。 关于选赛道和选币种,我发现目前行业的主流做法还是靠逻辑分析。列一堆看好某个赛道和币种的理由作为买某类资产的依据,这算不上错,但是有缺陷。首先,当你处在某个时间截面下,你都能找到无数个看多或看空某一赛道和资产的理由,因为凡事都是一体两面的,所以靠逻辑分析还是主观的,再深入讨论下去就成辩论了,二是不定量,缺乏客观数据的支撑。关于多因子模型,80%靠算法,20%靠经验我希望通过多因子模型去解决“选”的问题。 市场是有统计规律的,为什...

用多因子策略构建强大的加密资产投资组合 #理论基础篇#
前言在去年6月份,我设想了用多因子模型去择币的简单构思。 https://mirror.xyz/lucidafund.eth/UdOfxxKgD_Xuc_KrvGvsjrWZZCwKlWPAYNx991ZgmIA nft://undefined/undefined/undefined?showBuying=true&showMeta=true 一年后,我们已经着手研发针对加密资产市场的多因子策略,并把整体的策略框架写成系列的文章《用多因子策略构建强大的加密资产投资组合》。 本系列的大体框架如下(不排除微调的可能):一、多因子模型理论基础 二、单因子构建因子数据预处理数据筛选异常值处理:极值、错误值、空值标准化中性化:行业、市场、市值因子有效性判断信息比率IC、收益率、夏普比率、换手率三、大类因子合成因子共线性分析正交消除因子共线性经典加权方法→合成因子等权、滚动IC加权、IC_IR加权合成因子的测试:收益率、分组收益率、因子值加权收益率、合成因子IC、分组换手率其他加权方法(因子与收益率存在非线性关系):机器学习、强化学习(由于加密货币行业的特殊性,不考虑)四、风险组合优化以下是...

用多因子策略构建强大的加密资产投资组合 #数据预处理篇#
前言书接上回,我们发布了《用多因子策略构建强大的加密资产投资组合》系列文章的第一篇 - 理论基础篇,本篇是第二篇 - 数据预处理篇。 在计算因子数据前/后,以及测试单因子的有效性之前,都需要对相关数据进行处理。具体的数据预处理涉及重复值、异常值/缺失值/极端值、标准化和数据频率的处理。一、重复值数据相关定义:键(Key):表示一个独一无二的索引。eg. 对于一份有全部token所有日期的数据,键是“token_id/contract_address - 日期”值(Value):被键索引的对象就称之为“值”。诊断重复值的首先需要理解数据“应当”是什么样子。通常数据的形式有:时间序列数据(Time Series)。键是“时间”。eg.单个token5年的价格数据横截面数据(Cross Section)。键是“个体”。eg.2023.11.01当日crypto市场所有token的价格数据面板数据(Panel)。键是“个体-时间”的组合。eg.从2019.01.01-2023.11.01 四年所有token的价格数据。原则:确定了数据的索引(键),就能知道数据应该在什么层面没有重复值。检...
Lucida is a quantitative hedge fund. Falcon is a Web3 investment infra.



LUCIDA:用多因子模型去选赛道、选币种
投资小币种,无论是一级还是二级,我把整个过程分成四个部分:选、买、管、卖。『 选 』选包括两部分,选赛道和选币种。『 买 』买有两种方式,一级或者二级,这两个需要的核心能力不一样,一级看重行业资源,二级看重投研能力,目前我没看到,二者各有优劣,目前没看到两个能力都有的机构,这里不展开讲。『 管 』管是指管理投资组合。包括对冲风险、增强收益、调仓等等。『 卖 』卖不解释了。如果你是屯币者或者对某类资产有特殊信仰,当我没说。仅靠逻辑分析,不太靠谱这四块里最难的还是选。市场中的小币种太多,光CMC收录的就有9000多个,再怎么筛选,潜在的投资标的也得有大几十个。 关于选赛道和选币种,我发现目前行业的主流做法还是靠逻辑分析。列一堆看好某个赛道和币种的理由作为买某类资产的依据,这算不上错,但是有缺陷。首先,当你处在某个时间截面下,你都能找到无数个看多或看空某一赛道和资产的理由,因为凡事都是一体两面的,所以靠逻辑分析还是主观的,再深入讨论下去就成辩论了,二是不定量,缺乏客观数据的支撑。关于多因子模型,80%靠算法,20%靠经验我希望通过多因子模型去解决“选”的问题。 市场是有统计规律的,为什...

用多因子策略构建强大的加密资产投资组合 #理论基础篇#
前言在去年6月份,我设想了用多因子模型去择币的简单构思。 https://mirror.xyz/lucidafund.eth/UdOfxxKgD_Xuc_KrvGvsjrWZZCwKlWPAYNx991ZgmIA nft://undefined/undefined/undefined?showBuying=true&showMeta=true 一年后,我们已经着手研发针对加密资产市场的多因子策略,并把整体的策略框架写成系列的文章《用多因子策略构建强大的加密资产投资组合》。 本系列的大体框架如下(不排除微调的可能):一、多因子模型理论基础 二、单因子构建因子数据预处理数据筛选异常值处理:极值、错误值、空值标准化中性化:行业、市场、市值因子有效性判断信息比率IC、收益率、夏普比率、换手率三、大类因子合成因子共线性分析正交消除因子共线性经典加权方法→合成因子等权、滚动IC加权、IC_IR加权合成因子的测试:收益率、分组收益率、因子值加权收益率、合成因子IC、分组换手率其他加权方法(因子与收益率存在非线性关系):机器学习、强化学习(由于加密货币行业的特殊性,不考虑)四、风险组合优化以下是...

用多因子策略构建强大的加密资产投资组合 #数据预处理篇#
前言书接上回,我们发布了《用多因子策略构建强大的加密资产投资组合》系列文章的第一篇 - 理论基础篇,本篇是第二篇 - 数据预处理篇。 在计算因子数据前/后,以及测试单因子的有效性之前,都需要对相关数据进行处理。具体的数据预处理涉及重复值、异常值/缺失值/极端值、标准化和数据频率的处理。一、重复值数据相关定义:键(Key):表示一个独一无二的索引。eg. 对于一份有全部token所有日期的数据,键是“token_id/contract_address - 日期”值(Value):被键索引的对象就称之为“值”。诊断重复值的首先需要理解数据“应当”是什么样子。通常数据的形式有:时间序列数据(Time Series)。键是“时间”。eg.单个token5年的价格数据横截面数据(Cross Section)。键是“个体”。eg.2023.11.01当日crypto市场所有token的价格数据面板数据(Panel)。键是“个体-时间”的组合。eg.从2019.01.01-2023.11.01 四年所有token的价格数据。原则:确定了数据的索引(键),就能知道数据应该在什么层面没有重复值。检...
Share Dialog
Share Dialog
Lucida is a quantitative hedge fund. Falcon is a Web3 investment infra.

Subscribe to LUCIDA & FALCON

Subscribe to LUCIDA & FALCON
<100 subscribers
<100 subscribers
书接上回,关于《用多因子模型构建强大的加密资产投资组合》系列文章中,我们已经发布了两篇:《理论基础篇》、《数据预处理篇》
本篇是第三篇:因子有效性检验。
在求出具体的因子值后,需要先对因子进行有效性检验,筛选符合显著性、稳定性、单调性、收益率要求的因子;因子有效性检验通过分析本期因子值与预期收益率的关系,从而确定因子的有效性。主要有3种经典方法:
IC / IR法:IC / IR值为因子值与预期收益率的相关系数,越大因子表现越好。
T值(回归法):T值体现下期收益率对本期因子值线性回归后系数的显著性,通过比较该回归系数是否通过t检验,来判断本期因子值对下期收益率的贡献程度,通常用于多元(即多因子)回归模型。
分层回测法:分层回测法基于因子值对token分层,再计算每层token的收益率,从而判断因子的单调性
IC:即信息系数Information Coefficient,代表因子预测Tokens收益的能力。某一期IC值为本期因子值和下期收益率的相关系数。
fₜ: 第t期因子值
Rₜ₊₁: 第t+1期token的收益率
IC∈(-1,1),IC越大的因子,选币能力就越强。
IC 越接近1,说明因子值和下期收益率的正相关性越强,IC=1,表示该因子选币100%准确,对应的是排名分最高的token,选出来的token在下个调仓周期中,涨幅最大;
IC 越接近-1,说明因子值和下期收益率的负相关性越强,如果IC=-1,则代表排名分最高的token,在下个调仓周期中,跌幅最大,是一个完全反指的指标;
若 IC 越接近0,则说明该因子的预测能力极其弱,表明该因子对于token没有任何的预测能力。
IR:信息比率information ratio,代表因子获取稳定Alpha的能力。IR 为所有期 IC 均值除以所有期 IC 标准差。
当IC的绝对值大于0.05(0.02) 时,因子的选股能力较强。当IR大于0.5时,因子稳定获取超额收益能力较强。
Normal IC (Pearson correlation):计算皮尔森相关系数,最经典的一种相关系数。但该计算方式存在较多假设前提:数据连续,正态分布,两个变量满足线性关系等等。
Rank IC (Spearman's rank coefficient of correlation):计算斯皮尔曼秩相关系数,先对两个变量排序,再根据排序后的结果求皮尔森相关系数。斯皮尔曼秩相关系数评估的是两个变量之间的单调关系,并且由于转换为排序值,受数据异常值影响较小;而皮尔森相关系数评估的是两个变量之间的线性关系,不仅对原始数据有一定的前提条件,并且受数据异常值影响较大。在现实计算中,求rank IC更符合。
创建一个按日期时间升序排列的唯一日期时间值的列表--记录调仓日期 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()
T值法同样检验本期因子值和下期收益率关系,但与ICIR法分析二者的相关性不同,t值法将下期收益率作为因变量Y,本期因子值作为自变量X,由Y对X回归,对回归出因子值的回归系数进行t检验,检验其是否显著异于0,即本期因子是否影响下期收益率。
该方法本质是对双变量回归模型的求解,具体公式如下:
Rₜ₊₁: 第t+1期token收益率
fₜ:第t期因子值
βₜ:第t期因子值的回归系数,即因子收益率
αₜ:截距项,反映所有未包含到模型中的变量对Rₜ₊₁ 的平均影响
设定显著性水平α,通常为10%、5%、1%。
检验假设:,
k:回归模型中的参数个数
如果|t统计量| > |tα/₂(n-k)| → 拒绝H₀,即本期因子值fₜ对下期收益率Rₜ₊₁有显著的影响。
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
分层指对所有token分层,回测指计算每层token组合的收益率。
首先获取token池对应的因子值,通过因子值对token进行排序。升序排序,即因子值较小的排在前面,根据排序对token进行等分。第0层token的因子值最小,第9层token的的因子值最大。
理论上“等分”是指均等分拆token的个数,即每层token个数相同,借助分位数实现。现实中token总数不一定是层数的倍数,即每层token个数不一定相等。
将token按因子值升序分完10组后,开始计算每组token组合的收益率。该步骤将每层的token当成一个投资组合(不同回测期,每层的token组合所含的token都会有变化),并计算该组合整体的下期收益率。ICIR、t值分析的是当期因子值和下期整体的收益率,但分层回测需要计算回测时间内每个交易日的分层组合收益率。由于有很多回测期有很多期,在每一期都需要进行分层和回测。最后对每一层的token收益率进行累乘,计算出token组合的累积收益率。
理想状态下,一个好的因子,第9组的曲线收益最高,第0组的曲线收益最低。

第9组减去第0组(即多空收益)曲线呈现单调递增。

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')
Lucida (https://www.lucida.fund/ )是行业领先的量化对冲基金,在2018年4月进入Crypto市场,主要交易CTA / 统计套利 / 期权波动率套利等策略,现管理规模3000万美元。
Falcon (https://falcon.lucida.fund /)是新一代的Web3投资基础设施,它基于多因子模型,帮助用户“选”、“买”、“管”、“卖”加密资产。Falcon在2022年6月由Lucida所孵化。
书接上回,关于《用多因子模型构建强大的加密资产投资组合》系列文章中,我们已经发布了两篇:《理论基础篇》、《数据预处理篇》
本篇是第三篇:因子有效性检验。
在求出具体的因子值后,需要先对因子进行有效性检验,筛选符合显著性、稳定性、单调性、收益率要求的因子;因子有效性检验通过分析本期因子值与预期收益率的关系,从而确定因子的有效性。主要有3种经典方法:
IC / IR法:IC / IR值为因子值与预期收益率的相关系数,越大因子表现越好。
T值(回归法):T值体现下期收益率对本期因子值线性回归后系数的显著性,通过比较该回归系数是否通过t检验,来判断本期因子值对下期收益率的贡献程度,通常用于多元(即多因子)回归模型。
分层回测法:分层回测法基于因子值对token分层,再计算每层token的收益率,从而判断因子的单调性
IC:即信息系数Information Coefficient,代表因子预测Tokens收益的能力。某一期IC值为本期因子值和下期收益率的相关系数。
fₜ: 第t期因子值
Rₜ₊₁: 第t+1期token的收益率
IC∈(-1,1),IC越大的因子,选币能力就越强。
IC 越接近1,说明因子值和下期收益率的正相关性越强,IC=1,表示该因子选币100%准确,对应的是排名分最高的token,选出来的token在下个调仓周期中,涨幅最大;
IC 越接近-1,说明因子值和下期收益率的负相关性越强,如果IC=-1,则代表排名分最高的token,在下个调仓周期中,跌幅最大,是一个完全反指的指标;
若 IC 越接近0,则说明该因子的预测能力极其弱,表明该因子对于token没有任何的预测能力。
IR:信息比率information ratio,代表因子获取稳定Alpha的能力。IR 为所有期 IC 均值除以所有期 IC 标准差。
当IC的绝对值大于0.05(0.02) 时,因子的选股能力较强。当IR大于0.5时,因子稳定获取超额收益能力较强。
Normal IC (Pearson correlation):计算皮尔森相关系数,最经典的一种相关系数。但该计算方式存在较多假设前提:数据连续,正态分布,两个变量满足线性关系等等。
Rank IC (Spearman's rank coefficient of correlation):计算斯皮尔曼秩相关系数,先对两个变量排序,再根据排序后的结果求皮尔森相关系数。斯皮尔曼秩相关系数评估的是两个变量之间的单调关系,并且由于转换为排序值,受数据异常值影响较小;而皮尔森相关系数评估的是两个变量之间的线性关系,不仅对原始数据有一定的前提条件,并且受数据异常值影响较大。在现实计算中,求rank IC更符合。
创建一个按日期时间升序排列的唯一日期时间值的列表--记录调仓日期 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()
T值法同样检验本期因子值和下期收益率关系,但与ICIR法分析二者的相关性不同,t值法将下期收益率作为因变量Y,本期因子值作为自变量X,由Y对X回归,对回归出因子值的回归系数进行t检验,检验其是否显著异于0,即本期因子是否影响下期收益率。
该方法本质是对双变量回归模型的求解,具体公式如下:
Rₜ₊₁: 第t+1期token收益率
fₜ:第t期因子值
βₜ:第t期因子值的回归系数,即因子收益率
αₜ:截距项,反映所有未包含到模型中的变量对Rₜ₊₁ 的平均影响
设定显著性水平α,通常为10%、5%、1%。
检验假设:,
k:回归模型中的参数个数
如果|t统计量| > |tα/₂(n-k)| → 拒绝H₀,即本期因子值fₜ对下期收益率Rₜ₊₁有显著的影响。
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
分层指对所有token分层,回测指计算每层token组合的收益率。
首先获取token池对应的因子值,通过因子值对token进行排序。升序排序,即因子值较小的排在前面,根据排序对token进行等分。第0层token的因子值最小,第9层token的的因子值最大。
理论上“等分”是指均等分拆token的个数,即每层token个数相同,借助分位数实现。现实中token总数不一定是层数的倍数,即每层token个数不一定相等。
将token按因子值升序分完10组后,开始计算每组token组合的收益率。该步骤将每层的token当成一个投资组合(不同回测期,每层的token组合所含的token都会有变化),并计算该组合整体的下期收益率。ICIR、t值分析的是当期因子值和下期整体的收益率,但分层回测需要计算回测时间内每个交易日的分层组合收益率。由于有很多回测期有很多期,在每一期都需要进行分层和回测。最后对每一层的token收益率进行累乘,计算出token组合的累积收益率。
理想状态下,一个好的因子,第9组的曲线收益最高,第0组的曲线收益最低。

第9组减去第0组(即多空收益)曲线呈现单调递增。

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')
Lucida (https://www.lucida.fund/ )是行业领先的量化对冲基金,在2018年4月进入Crypto市场,主要交易CTA / 统计套利 / 期权波动率套利等策略,现管理规模3000万美元。
Falcon (https://falcon.lucida.fund /)是新一代的Web3投资基础设施,它基于多因子模型,帮助用户“选”、“买”、“管”、“卖”加密资产。Falcon在2022年6月由Lucida所孵化。
No activity yet