
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、分组换手率其他加权方法(因子与收益率存在非线性关系):机器学习、强化学习(由于加密货币行业的特殊性,不考虑)四、风险组合优化以下是...

用多因子策略构建强大的加密资产投资组合 #大类因子分析:因子合成篇#
书接上回,关于《用多因子模型构建强大的加密资产投资组合》系列文章中,我们已经发布了三篇:《理论基础篇》、《数据预处理篇》、《因子有效性检验篇》。 前三篇分别解释了多因子策略的理论与单因子测试的步骤。一、因子相关性检验的原因:多重共线性我们通过单因子测试部分筛选出一批有效因子,但以上因子不能直接入库。因子本身可以根据具体的经济含义进行大类划分,同类型的因子间存在较强的相关性,若不经相关性筛选直接入库,根据不同因子进行多元线性回归求预期收益率时,会出现多重共线性问题。计量经济学中,多重共线性是指回归模型中的一些或全部解释变量存在“完全”或准确的线性关系(各变量间高度相关)。 因此,有效因子筛选出后,首先需要根据大类对因子的相关性进行T检验,对于相关性较高的因子,要么舍弃显著性较低的因子,要么进行因子合成。 多重共线性的数学解释如下: $$Y = β₁ + β₂X₂ᵢ + β₃X₃ᵢ + ... + βₖXₖᵢ + μᵢ , i = 1,2,...,n$$ 会存在两种情况: 1.$$C₂X₂ᵢ + C₃X₃ᵢ + … + CₖXₖᵢ = 常数向量$$,$$ Cᵢ$$不全为$$0→Xᵢ$...
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、分组换手率其他加权方法(因子与收益率存在非线性关系):机器学习、强化学习(由于加密货币行业的特殊性,不考虑)四、风险组合优化以下是...

用多因子策略构建强大的加密资产投资组合 #大类因子分析:因子合成篇#
书接上回,关于《用多因子模型构建强大的加密资产投资组合》系列文章中,我们已经发布了三篇:《理论基础篇》、《数据预处理篇》、《因子有效性检验篇》。 前三篇分别解释了多因子策略的理论与单因子测试的步骤。一、因子相关性检验的原因:多重共线性我们通过单因子测试部分筛选出一批有效因子,但以上因子不能直接入库。因子本身可以根据具体的经济含义进行大类划分,同类型的因子间存在较强的相关性,若不经相关性筛选直接入库,根据不同因子进行多元线性回归求预期收益率时,会出现多重共线性问题。计量经济学中,多重共线性是指回归模型中的一些或全部解释变量存在“完全”或准确的线性关系(各变量间高度相关)。 因此,有效因子筛选出后,首先需要根据大类对因子的相关性进行T检验,对于相关性较高的因子,要么舍弃显著性较低的因子,要么进行因子合成。 多重共线性的数学解释如下: $$Y = β₁ + β₂X₂ᵢ + β₃X₃ᵢ + ... + βₖXₖᵢ + μᵢ , i = 1,2,...,n$$ 会存在两种情况: 1.$$C₂X₂ᵢ + C₃X₃ᵢ + … + CₖXₖᵢ = 常数向量$$,$$ Cᵢ$$不全为$$0→Xᵢ$...
Lucida is a quantitative hedge fund. Falcon is a Web3 investment infra.

Subscribe to LUCIDA & FALCON

Subscribe to LUCIDA & FALCON


Share Dialog
Share Dialog
<100 subscribers
<100 subscribers
书接上回,我们发布了《用多因子策略构建强大的加密资产投资组合》系列文章的第一篇 - 理论基础篇,本篇是第二篇 - 数据预处理篇。
在计算因子数据前/后,以及测试单因子的有效性之前,都需要对相关数据进行处理。具体的数据预处理涉及重复值、异常值/缺失值/极端值、标准化和数据频率的处理。
键(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的价格数据。
原则:确定了数据的索引(键),就能知道数据应该在什么层面没有重复值。
pd.DataFrame.duplicated(subset=[key1, key2, ...])
检查重复值的数量:pd.DataFrame.duplicated(subset=[key1, key2, ...]).sum()
抽样看重复的样本:df[df.duplicated(subset=[...])].sample()找到样本后,再用df.loc选出该索引对应的全部重复样本
pd.merge(df1, df2, on=[key1, key2, ...], indicator=True, validate='1:1')
在横向合并的函数中,加入indicator参数,会生成_merge字段,对其使用dfm['_merge'].value_counts()可以检查合并后不同来源的样本数量
加入validate参数,可以检验合并的数据集中索引是否如预期一般(1 to 1、1 to many或many to many,其中最后一种情况其实等于不需要验证)。如果与预期不符,合并过程会报错并中止执行。
极端情况。比如token价格0.000001$或市值仅50万美元的token,随便变动一点,就会有数十倍的回报率。
数据特性。比如token价格数据从2020年1月1日开始下载,那么自然无法计算出2020年1月1日的回报率数据,因为没有前一日的收盘价。
数据错误。数据提供商难免会犯错,比如将12元每token记录成1.2元每token。
删除。对于无法合理更正或修正的异常值,可以考虑删除。
替换。通常用于对极端值的处理,比如缩尾(Winsorizing)或取对数(不常用)。
填充。对于缺失值也可以考虑以合理的方式填充,常见的方式包括均值(或移动平均)、插值(Interpolation)、填0 df.fillna(0)、向前df.fillna('ffill')/向后填充df.fillna('bfill')等,要考虑填充所依赖的假设是否合。
机器学习慎用向后填充,有 Look-ahead bias 的风险
1.百分位法。
通过将顺序从小到大排列,将超过最小和最大比例的数据替换为临界的数据。对于历史数据较丰富的数据,该方法相对粗略,不太适用,强行删除固定比例的数据可能造成一定比例的损失。
2.3σ / 三倍标准差法
标准差 体现因子数据分布的离散程度,即波动性。利用 范围识别并替换数据集中的异常值,约有99.73% 的数据落入该范围。该方法适用前提:因子数据必须服从正态分布,即 。
其中,, ,因子值的合理范围是。
对数据范围内的所有因子做出如下调整:

该方法不足在于,量化领域常用的数据如股票价格、token价格常呈现尖峰厚尾分布,并不符合正态分布的假设,在该情况下采用方法将有大量数据错误地被识别为异常值。
3.绝对值差中位数法(Median Absolute Deviation, MAD)
该方法基于中位数和绝对偏差,使处理后的数据对极端值或异常值没那么敏感。比基于均值和标准差的方法更稳健。
绝对偏差值的中位数
因子值的合理范围是。对数据范围内的所有因子做出如下调整:

# 处理因子数据极端值情况
class Extreme(object):
def __init__(s, ini_data):
s.ini_data = ini_data
def three_sigma(s,n=3):
mean = s.ini_data.mean()
std = s.ini_data.std()
low = mean - n*std
high = mean + n*std
return np.clip(s.ini_data,low,high)
def mad(s, n=3):
median = s.ini_data.median()
mad_median = abs(s.ini_data - median).median()
high = median + n * mad_median
low = median - n * mad_median
return np.clip(s.ini_data, low, high)
def quantile(s,l = 0.025, h = 0.975):
low = s.ini_data.quantile(l)
high = s.ini_data.quantile(h)
return np.clip(s.ini_data, low, high)
1.Z-score标准化
前提:
由于使用了标准差,该方法对于数据中的异常值较为敏感
2.最大最小值差标准化(Min-Max Scaling)
将每个因子数据转化为在 区间的数据,以便比较不同规模或范围的数据,但它并不改变数据内部的分布,也不会使总和变为1。
由于考虑极大极小值,对异常值敏感
统一量纲,利于比较不同维度的数据。
3.排序百分位(Rank Scaling)
将数据特征转换为它们的排名,并将这些排名转换为介于0和1之间的分数,通常是它们在数据集中的百分位数。*
由于排名不受异常值影响,该方法对异常值不敏感。
不保持数据中各点之间的绝对距离,而是转换为相对排名。
其中,, 为区间内数据点的总个数。
# 标准化因子数据
class Scale(object):
def __init__(s, ini_data,date):
s.ini_data = ini_data
s.date = date
def zscore(s):
mean = s.ini_data.mean()
std = s.ini_data.std()
return s.ini_data.sub(mean).div(std)
def maxmin(s):
min = s.ini_data.min()
max = s.ini_data.max()
return s.ini_data.sub(min).div(max - min)
def normRank(s):
# 对指定列进行排名,method='min'意味着相同值会有相同的排名,而不是平均排名
ranks = s.ini_data.rank(method='min')
return ranks.div(ranks.max())
有时获得的数据并非我们分析所需要的频率。比如分析的层次为月度,原始数据的频率为日度,此时就需要用到“下采样”,即聚合数据为月度。
指的是将一个集合里的数据聚合为一行数据,比如日度数据聚合为月度。此时需要考虑每个被聚合的指标的特性,通常的操作有:
第一个值/最后一个值
均值/中位数
标准差
指的是将一行数据的数据拆分为多行数据,比如年度数据用在月度分析上。这种情况一般就是简单重复即可,有时需要将年度数据按比例归集于各个月份。
Lucida (https://www.lucida.fund/ )是行业领先的量化对冲基金,在2018年4月进入Crypto市场,主要交易CTA / 统计套利 / 期权波动率套利等策略,现管理规模3000万美元。
Falcon (https://falcon.lucida.fund /)是新一代的Web3投资基础设施,它基于多因子模型,帮助用户“选”、“买”、“管”、“卖”加密资产。Falcon在2022年6月由Lucida所孵化。
书接上回,我们发布了《用多因子策略构建强大的加密资产投资组合》系列文章的第一篇 - 理论基础篇,本篇是第二篇 - 数据预处理篇。
在计算因子数据前/后,以及测试单因子的有效性之前,都需要对相关数据进行处理。具体的数据预处理涉及重复值、异常值/缺失值/极端值、标准化和数据频率的处理。
键(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的价格数据。
原则:确定了数据的索引(键),就能知道数据应该在什么层面没有重复值。
pd.DataFrame.duplicated(subset=[key1, key2, ...])
检查重复值的数量:pd.DataFrame.duplicated(subset=[key1, key2, ...]).sum()
抽样看重复的样本:df[df.duplicated(subset=[...])].sample()找到样本后,再用df.loc选出该索引对应的全部重复样本
pd.merge(df1, df2, on=[key1, key2, ...], indicator=True, validate='1:1')
在横向合并的函数中,加入indicator参数,会生成_merge字段,对其使用dfm['_merge'].value_counts()可以检查合并后不同来源的样本数量
加入validate参数,可以检验合并的数据集中索引是否如预期一般(1 to 1、1 to many或many to many,其中最后一种情况其实等于不需要验证)。如果与预期不符,合并过程会报错并中止执行。
极端情况。比如token价格0.000001$或市值仅50万美元的token,随便变动一点,就会有数十倍的回报率。
数据特性。比如token价格数据从2020年1月1日开始下载,那么自然无法计算出2020年1月1日的回报率数据,因为没有前一日的收盘价。
数据错误。数据提供商难免会犯错,比如将12元每token记录成1.2元每token。
删除。对于无法合理更正或修正的异常值,可以考虑删除。
替换。通常用于对极端值的处理,比如缩尾(Winsorizing)或取对数(不常用)。
填充。对于缺失值也可以考虑以合理的方式填充,常见的方式包括均值(或移动平均)、插值(Interpolation)、填0 df.fillna(0)、向前df.fillna('ffill')/向后填充df.fillna('bfill')等,要考虑填充所依赖的假设是否合。
机器学习慎用向后填充,有 Look-ahead bias 的风险
1.百分位法。
通过将顺序从小到大排列,将超过最小和最大比例的数据替换为临界的数据。对于历史数据较丰富的数据,该方法相对粗略,不太适用,强行删除固定比例的数据可能造成一定比例的损失。
2.3σ / 三倍标准差法
标准差 体现因子数据分布的离散程度,即波动性。利用 范围识别并替换数据集中的异常值,约有99.73% 的数据落入该范围。该方法适用前提:因子数据必须服从正态分布,即 。
其中,, ,因子值的合理范围是。
对数据范围内的所有因子做出如下调整:

该方法不足在于,量化领域常用的数据如股票价格、token价格常呈现尖峰厚尾分布,并不符合正态分布的假设,在该情况下采用方法将有大量数据错误地被识别为异常值。
3.绝对值差中位数法(Median Absolute Deviation, MAD)
该方法基于中位数和绝对偏差,使处理后的数据对极端值或异常值没那么敏感。比基于均值和标准差的方法更稳健。
绝对偏差值的中位数
因子值的合理范围是。对数据范围内的所有因子做出如下调整:

# 处理因子数据极端值情况
class Extreme(object):
def __init__(s, ini_data):
s.ini_data = ini_data
def three_sigma(s,n=3):
mean = s.ini_data.mean()
std = s.ini_data.std()
low = mean - n*std
high = mean + n*std
return np.clip(s.ini_data,low,high)
def mad(s, n=3):
median = s.ini_data.median()
mad_median = abs(s.ini_data - median).median()
high = median + n * mad_median
low = median - n * mad_median
return np.clip(s.ini_data, low, high)
def quantile(s,l = 0.025, h = 0.975):
low = s.ini_data.quantile(l)
high = s.ini_data.quantile(h)
return np.clip(s.ini_data, low, high)
1.Z-score标准化
前提:
由于使用了标准差,该方法对于数据中的异常值较为敏感
2.最大最小值差标准化(Min-Max Scaling)
将每个因子数据转化为在 区间的数据,以便比较不同规模或范围的数据,但它并不改变数据内部的分布,也不会使总和变为1。
由于考虑极大极小值,对异常值敏感
统一量纲,利于比较不同维度的数据。
3.排序百分位(Rank Scaling)
将数据特征转换为它们的排名,并将这些排名转换为介于0和1之间的分数,通常是它们在数据集中的百分位数。*
由于排名不受异常值影响,该方法对异常值不敏感。
不保持数据中各点之间的绝对距离,而是转换为相对排名。
其中,, 为区间内数据点的总个数。
# 标准化因子数据
class Scale(object):
def __init__(s, ini_data,date):
s.ini_data = ini_data
s.date = date
def zscore(s):
mean = s.ini_data.mean()
std = s.ini_data.std()
return s.ini_data.sub(mean).div(std)
def maxmin(s):
min = s.ini_data.min()
max = s.ini_data.max()
return s.ini_data.sub(min).div(max - min)
def normRank(s):
# 对指定列进行排名,method='min'意味着相同值会有相同的排名,而不是平均排名
ranks = s.ini_data.rank(method='min')
return ranks.div(ranks.max())
有时获得的数据并非我们分析所需要的频率。比如分析的层次为月度,原始数据的频率为日度,此时就需要用到“下采样”,即聚合数据为月度。
指的是将一个集合里的数据聚合为一行数据,比如日度数据聚合为月度。此时需要考虑每个被聚合的指标的特性,通常的操作有:
第一个值/最后一个值
均值/中位数
标准差
指的是将一行数据的数据拆分为多行数据,比如年度数据用在月度分析上。这种情况一般就是简单重复即可,有时需要将年度数据按比例归集于各个月份。
Lucida (https://www.lucida.fund/ )是行业领先的量化对冲基金,在2018年4月进入Crypto市场,主要交易CTA / 统计套利 / 期权波动率套利等策略,现管理规模3000万美元。
Falcon (https://falcon.lucida.fund /)是新一代的Web3投资基础设施,它基于多因子模型,帮助用户“选”、“买”、“管”、“卖”加密资产。Falcon在2022年6月由Lucida所孵化。
No activity yet