数据层:数据框架 & 使用
简介
数据层
提供了用户友好的 API 来管理和获取数据,并提供了高性能的数据基础设施。
它专为量化投资设计。例如,用户可以轻松地使用 数据层
构建公式化阿尔法因子。更多细节请参考 构建公式化阿尔法因子。
数据层
的介绍包括以下几个部分。
数据准备
数据 API
数据加载器
数据处理器
数据集
缓存
数据与缓存文件结构
以下是 Qlib 数据工作流的一个典型示例
用户下载数据并将其转换为 Qlib 格式(文件名后缀为 .bin)。此步骤通常仅将一些基础数据存储在磁盘上(如 OHLCV)。
基于 Qlib 的表达式引擎创建一些基本特征(例如“Ref($close, 60) / $close”,表示过去 60 个交易日的收盘价比率)。表达式引擎支持的操作符可在此处 查看。此步骤通常由 Qlib 的 数据加载器 实现,它是 数据处理器 的一个组件。
如果用户需要更复杂的数据处理(例如数据归一化),数据处理器 支持用户自定义的处理器来处理数据(一些预定义的处理器可在此处 查看)。这些处理器与表达式引擎中的操作符不同,它们用于实现表达式引擎难以支持的复杂数据处理方法。
最后,数据集 负责从数据处理器处理后的数据中准备模型专用的数据集
数据准备
Qlib 格式数据
我们专门设计了一种数据结构来管理金融数据,详细信息请参阅 Qlib 论文中的文件存储设计部分。此类数据将以 .bin 作为文件名后缀进行存储(我们将称其为 .bin 文件、.bin 格式或 Qlib 格式)。.bin 文件专为金融数据的科学计算而设计。
Qlib
提供了两种现成可用的数据集,可通过此 链接 获取:
数据集 |
美国市场 |
中国市场 |
---|---|---|
Alpha360 |
√ |
√ |
Alpha158 |
√ |
√ |
此外,Qlib
还提供了一个高频数据集。用户可以通过此 链接 运行高频数据集示例。
Qlib 格式数据集
Qlib
提供了一种现成的 .bin 格式数据集,用户可以使用脚本 scripts/get_data.py
按如下方式下载中国股票数据集。用户也可以使用 numpy 加载 .bin 文件来验证数据。由于价格和成交量数据经过了复权处理(复权价格),因此它们看起来与实际交易价格不同。你可能会发现,不同数据源的复权价格存在差异,这是因为不同数据源的复权方法可能不同。Qlib 在复权时会将每只股票的第一个交易日的价格标准化为 1。用户可以通过 $factor 来还原原始交易价格(例如,使用 $close / $factor 获取原始收盘价)。
以下是一些关于 Qlib 价格复权的讨论。
# download 1d
python scripts/get_data.py qlib_data --target_dir ~/.qlib/qlib_data/cn_data --region cn
# download 1min
python scripts/get_data.py qlib_data --target_dir ~/.qlib/qlib_data/qlib_cn_1min --region cn --interval 1min
除了中国股票数据外,Qlib
还包含一个美国股票数据集,可通过以下命令下载:
python scripts/get_data.py qlib_data --target_dir ~/.qlib/qlib_data/us_data --region us
运行上述命令后,用户可以在 ~/.qlib/qlib_data/cn_data
目录和 ~/.qlib/qlib_data/us_data
目录中分别找到以 Qlib
格式存储的中国股票和美国股票数据。
Qlib
还在 scripts/data_collector
中提供了脚本,帮助用户从互联网爬取最新数据并将其转换为 qlib 格式。
当使用该数据集初始化 Qlib
后,用户即可基于此构建和评估自己的模型。更多细节请参考 初始化。
日频数据的自动更新
建议用户先手动更新一次(如设置 --trading_date 2021-05-25),然后设置为自动更新。
更多信息请参考:yahoo collector
- 每个交易日自动将数据更新到“qlib”目录(Linux 系统)
使用 crontab: crontab -e
设置定时任务:
* * * * 1-5 python <script path> update_data_to_bin --qlib_data_1d_dir <user data dir>
脚本路径:scripts/data_collector/yahoo/collector.py
手动更新数据
python scripts/data_collector/yahoo/collector.py update_data_to_bin --qlib_data_1d_dir <user data dir> --trading_date <start date> --end_date <end date>
trading_date:交易起始日
end_date:交易结束日(不包含)
将 CSV 格式转换为 Qlib 格式
Qlib
提供了脚本 scripts/dump_bin.py
,只要数据格式正确,即可将任意 CSV 格式的数据转换为 .bin 文件(Qlib
格式)。
除了下载准备好的示例数据外,用户还可以直接从数据采集器下载示例数据,以参考 CSV 格式的具体结构。以下是一些示例:
- 对于日频数据:
python scripts/get_data.py download_data --file_name csv_data_cn.zip --target_dir ~/.qlib/csv_data/cn_data
- 对于 1 分钟数据:
python scripts/data_collector/yahoo/collector.py download_data --source_dir ~/.qlib/stock_data/source/cn_1min --region CN --start 2021-05-20 --end 2021-05-23 --delay 0.1 --interval 1min --limit_nums 10
用户还可以提供自己以 CSV 格式存储的数据。但是,CSV 数据必须满足以下条件:
CSV 文件以特定股票命名 或 CSV 文件包含一列表示股票名称的列
将 CSV 文件以股票代码命名:SH600000.csv、AAPL.csv(不区分大小写)。
CSV 文件包含一列表示股票名称的列。用户在导入数据时必须指定该列的名称。示例如下:
python scripts/dump_bin.py dump_all ... --symbol_field_name symbol
数据应为以下格式:
symbol
close
SH600000
120
CSV 文件必须包含一列表示日期的列,且用户在导入数据时必须指定日期列的名称。示例如下:
python scripts/dump_bin.py dump_all ... --date_field_name date
数据应为以下格式:
symbol
date
close
open
volume
SH600000
2020-11-01
120
121
12300000
SH600000
2020-11-02
123
120
12300000
假设用户已将他们的 CSV 格式数据准备在目录 ~/.qlib/csv_data/my_data
中,则可以运行以下命令开始转换。
python scripts/dump_bin.py dump_all --csv_path ~/.qlib/csv_data/my_data --qlib_dir ~/.qlib/qlib_data/my_data --include_fields open,close,high,low,volume,factor
关于将数据转储到 .bin 文件时支持的其他参数,用户可通过运行以下命令查看详细信息:
python dump_bin.py dump_all --help
转换完成后,用户可在目录 ~/.qlib/qlib_data/my_data 中找到其 Qlib 格式的数据。
注意
–include_fields 参数应与 CSV 文件中的列名相对应。Qlib
提供的数据集至少应包含 open、close、high、low、volume 和 factor 列。
- open
复权后的开盘价
- close
复权后的收盘价
- high
复权后的最高价
- low
复权后的最低价
- volume
复权后的成交量
- factor
复权因子。通常,
factor = 复权价格 / 原始价格
,复权价格 参考:前复权
在 Qlib 数据处理的惯例中,如果股票停牌,则 open、close、high、low、volume、money 和 factor 将被设置为 NaN。如果你想要使用自己无法通过 OCHLV 计算的 alpha 因子(例如 PE、EPS 等),可以将其与 OHCLV 一起添加到 CSV 文件中,然后转换为 Qlib 格式的数据。
检查数据健康状况
Qlib
提供了一个脚本来检查数据的健康状况。
主要检查点如下
检查 DataFrame 中是否存在缺失数据。
检查 OHLCV 列中是否存在超过阈值的大幅跳变。
检查 DataFrame 中是否缺少必要的列(OLHCV)。
检查 DataFrame 中是否缺少 'factor' 列。
你可以运行以下命令来检查数据是否健康。
- 对于日频数据:
python scripts/check_data_health.py check_data --qlib_dir ~/.qlib/qlib_data/cn_data
- 对于 1 分钟数据:
python scripts/check_data_health.py check_data --qlib_dir ~/.qlib/qlib_data/cn_data_1min --freq 1min
当然,你也可以添加一些参数来调整测试结果。
可用参数如下。
freq:数据频率。
large_step_threshold_price:价格最大允许变化幅度。
large_step_threshold_volume:成交量最大允许变化幅度。
missing_data_num:数据允许为空的最大数量。
你可以运行以下命令来检查数据是否健康。
- 对于日频数据:
python scripts/check_data_health.py check_data --qlib_dir ~/.qlib/qlib_data/cn_data --missing_data_num 30055 --large_step_threshold_volume 94485 --large_step_threshold_price 20
- 对于 1 分钟数据:
python scripts/check_data_health.py check_data --qlib_dir ~/.qlib/qlib_data/cn_data --freq 1min --missing_data_num 35806 --large_step_threshold_volume 3205452000000 --large_step_threshold_price 0.91
股票池(市场)
Qlib
将股票池定义为股票列表及其对应的日期范围。可按如下方式导入预定义的股票池(例如 csi300)。
python collector.py --index_name CSI300 --qlib_dir <user qlib data dir> --method parse_instruments
多种股票模式
Qlib
目前为用户提供两种不同的股票模式:A 股模式和美股模式。以下是这两种模式的一些不同设置:
地区 |
交易单位 |
涨跌停限制 |
---|---|---|
中国 |
100 |
0.099 |
美国 |
1 |
None |
交易单位 定义了每笔交易中可买卖的股票最小单位数量,涨跌停限制 定义了股票涨跌幅的上下限比例。
- 如果用户在 A 股模式下使用
Qlib
,则需要 A 股数据。用户可按照以下步骤在 A 股模式下使用Qlib
: 下载以 Qlib 格式提供的中国股票数据,请参考章节 Qlib 格式数据集。
- 以中国股票模式初始化
Qlib
假设用户将 Qlib 格式的数据下载到目录
~/.qlib/qlib_data/cn_data
中。用户只需按以下方式初始化Qlib
。from qlib.constant import REG_CN qlib.init(provider_uri='~/.qlib/qlib_data/cn_data', region=REG_CN)
- 以中国股票模式初始化
- 如果用户在 A 股模式下使用
- 如果用户以美国股票模式使用
Qlib
,则需要美国股票数据。Qlib
还提供了一个脚本用于下载美国股票数据。用户可按照以下步骤以美国股票模式使用Qlib
: 下载以 Qlib 格式提供的美国股票数据,请参考章节 Qlib 格式数据集。
- 以美国股票模式初始化
Qlib
假设用户已将 Qlib 格式的数据准备在目录
~/.qlib/qlib_data/us_data
中。用户只需按以下方式初始化Qlib
。from qlib.config import REG_US qlib.init(provider_uri='~/.qlib/qlib_data/us_data', region=REG_US)
- 以美国股票模式初始化
- 如果用户以美国股票模式使用
注意
我们非常欢迎新增数据源的 Pull Request!用户可以像 此处示例 一样提交爬取数据的代码作为 PR。然后我们将使用该代码在服务器上创建数据缓存,其他用户可直接使用。
数据 API
数据获取
用户可以使用 qlib.data
中的 API 来获取数据,请参考 数据获取。
特征
Qlib
提供了 Feature 和 ExpressionOps,可根据用户需求提取特征。
- 特征
从数据提供方加载数据。用户可以获得如 $high、$low、$open、$close 等特征,这些应与 –include_fields 参数相对应,请参考章节 将 CSV 格式转换为 Qlib 格式。
- ExpressionOps
ExpressionOps 将使用算子进行特征构建。欲了解有关
Operator
的更多信息,请参考 算子 API。此外,Qlib
支持用户自定义Operator
,示例已在tests/test_register_ops.py
中给出。
欲了解有关 Feature
的更多信息,请参考 特征 API。
过滤器
Qlib
提供了 NameDFilter 和 ExpressionDFilter,可根据用户需求筛选标的。
- NameDFilter
名称动态标的筛选器。基于规定的名称格式筛选标的,需要提供一个名称规则的正则表达式。
- ExpressionDFilter
表达式动态标的筛选器。基于特定表达式筛选标的,需要提供指示某一特征字段的表达式规则。
基础特征筛选:rule_expression = ‘$close/$open>5’
截面特征过滤器:rule_expression = ‘$rank($close)<10’
时序特征过滤器:rule_expression = ‘$Ref($close, 3)>100’
以下是一个简单的示例,展示如何在基本的 Qlib
工作流配置文件中使用过滤器:
filter: &filter
filter_type: ExpressionDFilter
rule_expression: "Ref($close, -2) / Ref($close, -1) > 1"
filter_start_time: 2010-01-01
filter_end_time: 2010-01-07
keep: False
data_handler_config: &data_handler_config
start_time: 2010-01-01
end_time: 2021-01-22
fit_start_time: 2010-01-01
fit_end_time: 2015-12-31
instruments: *market
filter_pipe: [*filter]
要了解更多关于 Filter
的信息,请参考 Filter API。
参考
要了解更多关于 Data API
的信息,请参考 Data API。
数据加载器
Data Loader
在 Qlib
中用于从原始数据源加载原始数据,它将被加载并在 Data Handler
模块中使用。
QlibDataLoader
QlibDataLoader
类是 Qlib
中的一个接口,允许用户从 Qlib
数据源加载原始数据。
StaticDataLoader
StaticDataLoader
类是 Qlib
中的一个接口,允许用户从文件或指定来源加载原始数据。
接口
以下是 QlibDataLoader
类的一些接口:
- 类 qlib.data.dataset.loader.DataLoader
DataLoader 用于从原始数据源加载原始数据。
- abstract load(instruments, start_time=None, end_time=None) DataFrame
将数据加载为 pd.DataFrame。
数据示例(列的多级索引是可选的):
feature label $close $volume Ref($close, 1) Mean($close, 3) $high-$low LABEL0 datetime instrument 2010-01-04 SH600000 81.807068 17145150.0 83.737389 83.016739 2.741058 0.0032 SH600004 13.313329 11800983.0 13.313329 13.317701 0.183632 0.0042 SH600005 37.796539 12231662.0 38.258602 37.919757 0.970325 0.0289
- 参数:
instruments (str 或 dict) – 可以是市场名称,也可以是由 InstrumentProvider 生成的标的配置文件。如果 instruments 的值为 None,则表示不进行过滤。
start_time (str) – 时间范围的起始时间。
end_time (str) – 时间范围的结束时间。
- 返回:
从底层数据源加载数据
- 返回类型:
pd.DataFrame
- Raises:
KeyError: – 如果不支持 instruments 过滤,则抛出 KeyError
API
要了解更多关于 Data Loader
的信息,请参考 Data Loader API。
数据处理器
Data Handler
模块在 Qlib
中用于处理大多数模型常用的通用数据处理方法。
用户可以通过 qrun
在自动工作流中使用 数据 处理器
,更多详细信息请参考 工作流:工作流管理。
DataHandlerLP
除了通过 qrun
在自动工作流中使用 数据 处理器
外,数据 处理器
还可以作为独立模块使用,用户可借此方便地对数据进行预处理(如标准化、去除 NaN 等)并构建数据集。
为了实现这一点,Qlib
提供了一个基类 qlib.data.dataset.DataHandlerLP。该类的核心思想是:我们拥有一些可学习的 处理器
,它们能够学习数据处理的参数(例如 z-score 标准化的参数)。当新数据到来时,这些经过训练的 处理器
就可以处理新数据,从而实现高效地处理实时数据。有关 处理器
的更多详细信息将在下一小节中列出。
接口
以下是 DataHandlerLP
提供的一些重要接口:
- 类 qlib.data.dataset.handler.DataHandlerLP(instruments=无, start_time=无, end_time=无, data_loader: 字典 | 字符串 | DataLoader | 无 = 无, infer_processors: 列表 = [], learn_processors: 列表 = [], shared_processors: 列表 = [], process_type='append', drop_raw=False, **kwargs)
带有(可)学习(处)理器的 DataHandler
该处理器将以 pd.DataFrame 格式生成三组数据。
DK_R / self._data:从加载器中加载的原始数据
DK_I / self._infer:为推理处理过的数据
DK_L / self._learn:为模型学习处理过的数据
使用不同的处理器流程分别用于学习和推理的原因如下,以下是一些示例。
用于学习和推理的标的范围可能不同。
某些样本的处理可能依赖于标签(例如,某些触及涨跌停的样本可能需要额外处理或被剔除)。
这些处理器仅应用于学习阶段。
关于数据处理器的提示
为了降低内存开销
drop_raw=True:这将在原始数据上进行就地修改;
请注意,像 self._infer 或 self._learn 这样的已处理数据,与 Qlib 的 Dataset 中的 segments(如“train”和“test”)概念不同
像 self._infer 或 self._learn 这样的已处理数据,是指使用不同处理器处理得到的底层数据
Qlib 的 Dataset 中的 segments(如“train”和“test”)仅仅是在查询数据时的时间分段(“train”通常在时间序列上早于“test”)
例如,你可以在“train”时间段内查询由 infer_processors 处理过的 data._infer
- __init__(instruments=None, start_time=None, end_time=None, data_loader: dict | str | DataLoader | None = None, infer_processors: List = [], learn_processors: List = [], shared_processors: List = [], process_type='append', drop_raw=False, **kwargs)
- 参数:
infer_processors (列表) –
用于生成推理数据的处理器的<描述信息>列表
<描述信息>示例:
1) classname & kwargs: { "class": "MinMaxNorm", "kwargs": { "fit_start_time": "20080101", "fit_end_time": "20121231" } } 2) Only classname: "DropnaFeature" 3) object instance of Processor
learn_processors (列表) – 与 infer_processors 类似,但用于生成模型学习所需的数据
process_type (字符串) –
PTYPE_I = ‘independent’
self._infer 将由 infer_processors 处理
self._learn 将由 learn_processors 处理
PTYPE_A = ‘append’
self._infer 将由 infer_processors 处理
self._learn 将由 infer_processors + learn_processors 共同处理
(例如,self._infer 由 learn_processors 处理)
drop_raw (布尔值) – 是否丢弃原始数据
- fit()
在不处理数据的情况下进行拟合
- fit_process_data()
拟合并处理数据
fit 的输入将是前一个处理器的输出
- process_data(with_fit: 布尔值 = False)
处理数据。如有必要,调用 processor.fit
符号说明:(数据) [处理器]
# self.process_type == DataHandlerLP.PTYPE_I 时的数据处理流程
(self._data)-[shared_processors]-(_shared_df)-[learn_processors]-(_learn_df) \ -[infer_processors]-(_infer_df)
# self.process_type == DataHandlerLP.PTYPE_A 时的数据处理流程
(self._data)-[shared_processors]-(_shared_df)-[infer_processors]-(_infer_df)-[learn_processors]-(_learn_df)
- 参数:
with_fit (布尔值) – fit 的输入将是前一个处理器的输出
- config(processor_kwargs: 字典 | 无 = 无, **kwargs)
数据的配置。# 从数据源加载哪些数据
当从数据集中加载已序列化的处理器时,将使用此方法。数据将使用不同的时间范围进行初始化。
- setup_data(init_type: 字符串 = 'fit_seq', **kwargs)
在多次初始化运行时设置数据
- 参数:
init_type (字符串) – 上述列出的 IT_* 类型。
enable_cache (bool) –
默认值为 false:
如果 enable_cache == True:
处理后的数据将被保存到磁盘,当下次调用 init 时,处理器将直接从磁盘加载缓存的数据
- fetch(selector: Timestamp | slice | str = slice(None, None, None), level: str | int = 'datetime', col_set='__all', data_key: Literal['raw', 'infer', 'learn'] = 'infer', squeeze: bool = False, proc_func: Callable | None = None) DataFrame
从底层数据源获取数据
- 参数:
selector (Union[pd.Timestamp, slice, str]) – 描述如何通过索引选择数据。
level (Union[str, int]) – 选择数据的索引层级。
col_set (str) – 选择一组有意义的列。(例如:特征、列)。
data_key (str) – 要获取的数据:DK_*。
proc_func (Callable) – 请参考 DataHandler.fetch 的文档。
- 返回类型:
pd.DataFrame
- get_cols(col_set='__all', data_key: Literal['raw', 'infer', 'learn'] = 'infer') list
获取列名
- 参数:
col_set (str) – 选择一组有意义的列。(例如:特征、列)。
data_key (DATA_KEY_TYPE) – 要获取的数据:DK_*。
- 返回:
列名列表
- 返回类型:
list
- 类方法 转换(处理器: DataHandlerLP) DataHandlerLP
动机
用户在其自定义包中创建了一个 datahandler。然后他希望与其他用户共享已处理的 handler,而无需引入包依赖和复杂的数据处理逻辑。
该类通过将类转换为 DataHandlerLP 并仅保留已处理的数据来实现这一目标。
- 参数:
handler (DataHandlerLP) – DataHandlerLP 的一个子类
- 返回:
转换后的已处理数据
- 返回类型:
- 类方法 从 DataFrame 创建(df: DataFrame) DataHandlerLP
动机:- 当用户想要快速获得一个数据处理器时。
创建的数据处理器将只有一个共享的 DataFrame,且不包含任何处理器。创建处理器后,用户通常希望将其导出以便重复使用。以下是一个典型的使用场景
from qlib.data.dataset import DataHandlerLP dh = DataHandlerLP.from_df(df) dh.to_pickle(fname, dump_all=True)
待办事项:- StaticDataLoader 非常慢。其实没有必要再次复制数据……
如果用户希望通过配置加载特征和标签,可以定义一个新的处理器,并调用 qlib.contrib.data.handler.Alpha158
的静态方法 parse_config_to_fields。
此外,用户还可以将提供了一些基于配置定义特征的预处理方法的 qlib.contrib.data.processor.ConfigSectionProcessor
传入新的处理器中。
处理器
Qlib
中的 Processor
模块被设计为可学习的,负责处理诸如归一化和删除空值/NaN 特征或标签等数据处理任务。
Qlib
提供了以下几种 Processor
:
DropnaProcessor
:处理器,用于删除包含 N/A 的特征。DropnaLabel
:处理器,用于删除包含 N/A 的标签。TanhProcess
:处理器,使用 tanh 函数处理噪声数据。ProcessInf
:处理器,用于处理无穷大值,会将其替换为该列的均值。Fillna
:处理器,用于处理 N/A 值,会用 0 或其他指定数值填充。MinMaxNorm
:处理器,执行最小-最大值归一化。ZscoreNorm
:处理器,执行 Z-score 标准化。RobustZScoreNorm
:processor,用于执行稳健的 z-score 标准化。CSZScoreNorm
:processor,用于执行横截面 z-score 标准化。CSRankNorm
:processor,用于执行横截面秩次标准化。CSZFillna
:processor,通过列的均值以横截面方式填充缺失值(N/A)。
用户也可以通过继承基类 Processor
来创建自己的 processor。更多信息请参考所有处理器的实现(Processor Link)。
如需了解更多关于 Processor
的内容,请参考 Processor API。
示例
Data Handler
可通过修改配置文件后使用 qrun
运行,也可作为独立模块使用。
了解更多如何使用 qrun
运行 Data Handler
,请参考 Workflow: Workflow Management。
Qlib 提供了已实现的数据处理器 Alpha158。以下示例展示了如何将 Alpha158 作为独立模块运行。
注意
用户需要先通过 qlib.init 初始化 Qlib
,详情请参考 initialization。
import qlib
from qlib.contrib.data.handler import Alpha158
data_handler_config = {
"start_time": "2008-01-01",
"end_time": "2020-08-01",
"fit_start_time": "2008-01-01",
"fit_end_time": "2014-12-31",
"instruments": "csi300",
}
if __name__ == "__main__":
qlib.init()
h = Alpha158(**data_handler_config)
# get all the columns of the data
print(h.get_cols())
# fetch all the labels
print(h.fetch(col_set="label"))
# fetch all the features
print(h.fetch(col_set="feature"))
注意
在 Alpha158
中,Qlib
使用标签 Ref($close, -2)/Ref($close, -1) - 1,表示从 T+1 到 T+2 的变化,而不是 Ref($close, -1)/$close - 1。原因是,在获取中国股票 T 日的收盘价后,该股票可在 T+1 日买入,并在 T+2 日卖出。
API
如需了解更多关于 Data Handler
的内容,请参考 Data Handler API。
数据集
Qlib
中的 Dataset
模块旨在为模型训练和推理准备数据。
该模块的设计动机是:我们希望最大化不同模型处理其适用数据的灵活性。该模块赋予模型以独特方式处理数据的自由度。例如,像 GBDT
这类模型可以在包含 nan 或 None 值的数据上良好运行,而神经网络如 MLP
在此类数据上则会出错。
如果用户的模型需要以不同方式处理数据,可以实现自己的 Dataset
类。如果模型的数据处理方式并无特殊要求,可直接使用 DatasetH
。
DatasetH
类是带有数据处理器(Data Handler)的数据集。以下是该类最重要的接口:
- class qlib.data.dataset.__init__.DatasetH(handler: Dict | DataHandler, segments: Dict[str, Tuple], fetch_kwargs: Dict = {}, **kwargs)
带有数据处理(H)andler 的数据集
用户应尽量将数据预处理函数放入 handler 中。只有以下数据处理函数应保留在 Dataset 中:
处理逻辑与特定模型相关。
处理逻辑与数据划分相关。
- __init__(handler: Dict | DataHandler, segments: Dict[str, Tuple], fetch_kwargs: Dict = {}, **kwargs)
初始化底层数据。
- 参数:
handler (Union[dict, DataHandler]) –
handler 可以是:
DataHandler 的实例
DataHandler 的配置。请参考 DataHandler
segments (dict) –
描述数据分段的选项。以下是一些示例:
1) 'segments': { 'train': ("2008-01-01", "2014-12-31"), 'valid': ("2017-01-01", "2020-08-01",), 'test': ("2015-01-01", "2016-12-31",), } 2) 'segments': { 'insample': ("2008-01-01", "2014-12-31"), 'outsample': ("2017-01-01", "2020-08-01",), }
- config(handler_kwargs: dict | None = None, **kwargs)
初始化 DatasetH
- 参数:
handler_kwargs (dict) –
DataHandler 的配置,可能包含以下参数:
DataHandler.conf_data 的参数,例如 'instruments'、'start_time' 和 'end_time'。
kwargs (dict) –
DatasetH 的配置,例如
- segments字典
分段的配置,与 self.__init__ 中的 'segments' 相同
- setup_data(handler_kwargs: dict | None = None, **kwargs)
初始化数据
- 参数:
handler_kwargs (dict) –
DataHandler 的初始化参数,可能包含以下参数:
init_type : Handler 的初始化类型
enable_cache : 是否启用缓存
- prepare(segments: List[str] | Tuple[str] | str | slice | Index, col_set='__all', data_key='infer', **kwargs) List[DataFrame] | DataFrame
为学习和推理准备数据。
- 参数:
segments (Union[List[Text], Tuple[Text], Text, slice]) –
描述要准备的数据范围,以下是一些示例:
“train”
[“train”, “valid”]
col_set (str) –
该 col_set 将在获取数据时传递给 self.handler。TODO:实现自动化:
为测试数据选择 DK_I
为训练数据选择 DK_L。
data_key (str) – 要获取的数据:DK_* 默认值为 DK_I,表示获取用于推理的数据。
kwargs –
- kwargs 可能包含的参数:
- flt_colstr
仅存在于 TSDatasetH 中,可用于添加一列数据(True 或 False)以过滤数据。此参数仅在实例为 TSDatasetH 时支持。
- 返回类型:
Union[List[pd.DataFrame], pd.DataFrame]
- Raises:
NotImplementedError: –
API
要了解更多关于 Dataset
的信息,请参考 Dataset API。
缓存
Cache
是一个可选模块,通过将一些常用数据保存为缓存文件来加速数据提供。Qlib
提供了一个 Memcache 类用于在内存中缓存最常用的数据,以及一个可继承的 ExpressionCache 类和一个可继承的 DatasetCache 类。
全局内存缓存
Memcache 是一种全局内存缓存机制,由三个 MemCacheUnit 实例组成,分别用于缓存 日历、标的 和 特征。MemCache 在 cache.py 中被全局定义为 H。用户可以使用 H[‘c’], H[‘i’], H[‘f’] 来获取或设置 memcache。
- 类 qlib.data.cache.MemCacheUnit(*args, **kwargs)
内存缓存单元。
- __init__(*args, **kwargs)
- 属性 受限
内存缓存是否受限
- 类 qlib.data.cache.MemCache(mem_cache_size_limit=None, limit_type='length')
内存缓存。
- __init__(mem_cache_size_limit=None, limit_type='length')
- 参数:
mem_cache_size_limit – 缓存最大大小。
limit_type – length 或 sizeof;length(调用函数:len),size(调用函数:sys.getsizeof)。
表达式缓存
ExpressionCache 是一种缓存机制,用于保存诸如 Mean($close, 5) 之类的表达式。用户可以继承此类,通过以下步骤定义自己的表达式缓存机制。
重写 self._uri 方法,以定义缓存文件路径的生成方式。
重写 self._expression 方法,以定义将缓存哪些数据以及如何缓存。
以下是相关接口的详细说明:
- 类 qlib.data.cache.表达式缓存(提供者)
表达式缓存机制基类。
该类用于使用自定义的表达式缓存机制包装表达式提供者。
注意
重写 _uri 和 _expression 方法以创建您自己的表达式缓存机制。
- expression(instrument, field, start_time, end_time, freq)
获取表达式数据。
注意
与表达式提供者中的 expression 方法接口相同。
- update(cache_uri: str | Path, freq: str = 'day')
将表达式缓存更新至最新的日历。
重写此方法以定义如何根据用户自定义的缓存机制更新表达式缓存。
- 参数:
cache_uri (str 或 Path) – 表达式缓存文件的完整 URI(包含目录路径)。
freq (str) –
- 返回:
0(成功更新)/ 1(无需更新)/ 2(更新失败)。
- 返回类型:
int
Qlib
目前提供了已实现的磁盘缓存 DiskExpressionCache,它继承自 ExpressionCache。表达式数据将被存储在磁盘中。
DatasetCache
DatasetCache 是一种用于保存数据集的缓存机制。一个特定的数据集由股票池配置(或一系列标的,尽管不推荐)、表达式列表或静态特征字段、特征采集的开始时间与结束时间以及频率来确定。用户可以继承该基类,并按照以下步骤定义自己的数据集缓存机制。
重写 self._uri 方法,以定义其缓存文件路径的生成方式
重写 self._expression 方法,以定义将缓存哪些数据以及如何缓存。
以下是相关接口的详细说明:
- 类 qlib.data.cache.数据集缓存(提供者)
数据集缓存机制基类。
该类用于包装数据集提供者,并支持用户自定义的数据集缓存机制。
注意
重写 _uri 和 _dataset 方法,以创建您自己的数据集缓存机制。
- dataset(instrument, 字段, start_time=无, end_time=无, freq='day', disk_cache=1, inst_processors=[])
获取特征数据集。
注意
与数据集提供者中的 dataset 方法接口相同。
注意
服务器使用 redis_lock 来确保不会触发读写冲突,但不考虑客户端读取者的情况。
- update(cache_uri: str | Path, freq: str = 'day')
将数据集缓存更新到最新的日历。
重写此方法以定义如何根据用户自己的缓存机制更新数据集缓存。
- 参数:
cache_uri (str 或 Path) – 数据集缓存文件的完整 URI(包含目录路径)。
freq (str) –
- 返回:
0(成功更新)/ 1(无需更新)/ 2(更新失败)
- 返回类型:
int
- 静态 cache_to_origin_data(数据, 字段)
将缓存数据转换为原始数据
- 参数:
data – pd.DataFrame,缓存的数据。
fields – 特征字段。
- 返回:
pd.DataFrame。
- 静态 normalize_uri_args(instrument, 字段, freq)
标准化 URI 参数
Qlib
目前已提供实现了磁盘缓存 DiskDatasetCache,它继承自 DatasetCache。数据集的数据将存储在磁盘中。
数据与缓存文件结构
我们专门设计了一种文件结构来管理数据和缓存,详细信息请参考 Qlib 论文中的文件存储设计部分。数据和缓存的文件结构如下所示。
- data/
[raw data] updated by data providers
- calendars/
- day.txt
- instruments/
- all.txt
- csi500.txt
- ...
- features/
- sh600000/
- open.day.bin
- close.day.bin
- ...
- ...
[cached data] updated when raw data is updated
- calculated features/
- sh600000/
- [hash(instrtument, field_expression, freq)]
- all-time expression -cache data file
- .meta : an assorted meta file recording the instrument name, field name, freq, and visit times
- ...
- cache/
- [hash(stockpool_config, field_expression_list, freq)]
- all-time Dataset-cache data file
- .meta : an assorted meta file recording the stockpool config, field names and visit times
- .index : an assorted index file recording the line index of all calendars
- ...