数据层:数据框架 & 使用

简介

数据层 提供了用户友好的 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 和 Parquet 格式转换为 Qlib 格式

Qlib 提供了脚本 scripts/dump_bin.py,只要数据格式正确,即可将 CSV 或 Parquet 格式的任意数据转换为 .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 或 Parquet 格式数据。但数据必须满足以下条件:

  • CSV 或 Parquet 文件需以特定股票命名,或CSV 或 Parquet 文件中包含一列表示股票名称。

    • 以股票命名 CSV 或 Parquet 文件:SH600000.csv、AAPL.csv 或 SH600000.parquet、AAPL.parquet(不区分大小写)。

    • CSV 或 Parquet 文件包含股票名称列。用户在导出数据时必须指定该列的列名。示例如下:

      python scripts/dump_bin.py dump_all ... --symbol_field_name symbol --file_suffix <.csv or .parquet>
      

      数据应为以下格式:

      symbol

      close

      SH600000

      120

  • CSV 或 Parquet 文件必须包含一列表示日期,且在导出数据时用户必须指定日期列的列名。示例如下:

    python scripts/dump_bin.py dump_all ... --date_field_name date --file_suffix <.csv or .parquet>
    

    数据应为以下格式:

    symbol

    date

    close

    open

    volume

    SH600000

    2020-11-01

    120

    121

    12300000

    SH600000

    2020-11-02

    123

    120

    12300000

假设用户已将 CSV 或 Parquet 格式的数据准备在目录 ~/.qlib/my_data 中,则可运行以下命令开始转换。

python scripts/dump_bin.py dump_all --data_path  ~/.qlib/my_data --qlib_dir ~/.qlib/qlib_data/ --include_fields open,close,high,low,volume,factor --file_suffix <.csv or .parquet>

关于将数据转储到 .bin 文件时支持的其他参数,用户可通过运行以下命令查看详细信息:

python scripts/dump_bin.py dump_all --help

转换完成后,用户可在目录 ~/.qlib/qlib_data/ 中找到其 Qlib 格式的数据。

注意

–include_fields 参数应与 CSV 或 Parquet 文件中的列名相对应。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 或 Parquet 文件中,然后导出为 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)
      
  • 如果用户以美国股票模式使用 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 的一个子类

返回:

转换后的已处理数据

返回类型:

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
        - ...