13. 高频交易框架

13.高频交易框架

本文将详细介绍 QLib 中的高频交易框架,包括嵌套决策执行框架的设计理念、高频交易数据处理方法、订单流模拟与回测系统,以及实际的高频策略实现示例。通过本章内容,读者将能够掌握使用 QLib 进行高频交易策略开发的核心技术和实践方法。

高频交易概述

高频交易是量化投资中的一个重要领域,其特点是交易频率高、持仓时间短、交易量巨大。与传统的日频交易相比,高频交易需要处理更精细的时间粒度数据(如分钟级、秒级甚至 tick 级数据),对系统的 latency 和处理能力有更高要求。在实际操作中,高频交易策略通常依赖于市场微观结构特征、订单流分析和短期价格波动模式来获取收益。

QLib 作为一个全栈式的量化投资平台,提供了专门针对高频交易的完整解决方案。其核心是嵌套决策执行框架,该框架能够支持多级别交易策略的联合回测和优化,解决了传统框架中不同频率策略难以协同的问题。

嵌套决策执行框架

设计理念

在量化投资中,日间交易(如组合管理)和日内交易(如订单执行)通常是分开研究的。然而,为了获得整体的交易绩效,这两个层面必须相互作用并进行联合回测。传统的高频交易框架大多没有考虑多级别联合交易,导致回测结果不够准确。此外,不同级别策略的优化也不是独立的,它们之间会相互影响。例如,组合管理策略的最优选择可能会随着订单执行绩效的变化而改变。

为了解决这些问题,QLib 设计了嵌套决策执行框架,该框架考虑了不同级别策略之间的相互作用。框架的核心思想是将交易决策和执行环境进行层级化设计,允许在一个执行环境中嵌套更细粒度的交易算法和执行环境。这种灵活性使得用户可以轻松探索不同级别交易策略组合的效果,打破不同级别交易算法之间的优化壁垒。

框架架构

嵌套决策执行框架的设计如图 13-1 所示。每个级别由“交易代理”(Trading Agent)和“执行环境”(Execution Env)组成。交易代理包含自己的数据处理模块(信息提取器)、预测模块(预测模型)和决策生成器。交易算法基于预测模块输出的信号,通过决策生成器生成交易决策,并将决策传递给执行环境,执行环境返回执行结果。

flowchart TD
    subgraph "Level N"
        TA_N[Trading Agent]
        EE_N[Execution Env]
        TA_N -->|Decisions| EE_N
        EE_N -->|Results| TA_N
        subgraph TA_N
            IE_N[Information Extractor]
            FM_N[Forecast Model]
            DG_N[Decision Generator]
            IE_N --> FM_N --> DG_N
        end
        subgraph "Level N-1 (Nested)"
            TA_N1[Trading Agent]
            EE_N1[Execution Env]
            TA_N1 -->|Decisions| EE_N1
            EE_N1 -->|Results| TA_N1
        end
        EE_N -->|Sub-decisions| TA_N1
        EE_N1 -->|Sub-results| EE_N
    end

图 13-1 嵌套决策执行框架架构

交易算法的频率、决策内容和执行环境都可以由用户自定义(例如日内交易、日频交易、周频交易),执行环境内部可以嵌套更细粒度的交易算法和执行环境(即图中的子工作流,例如日频订单可以通过日内订单拆分转化为更细粒度的决策)。

核心组件

嵌套决策执行框架的核心组件包括以下几个部分:

  1. Trading Agent:负责生成交易决策,包含信息提取器、预测模型和决策生成器三个子模块。信息提取器用于从市场数据中提取有用的特征,预测模型基于这些特征生成价格走势或其他相关指标的预测,决策生成器则根据预测结果生成具体的交易决策。
  2. Execution Env:负责执行交易决策并返回执行结果。执行环境可以是真实的交易系统,也可以是模拟的回测环境。在嵌套框架中,执行环境可以调用更细粒度的交易代理来进一步优化决策执行。
  3. 嵌套机制:允许在一个执行环境中嵌套另一个完整的交易代理和执行环境组合,形成多层级的决策执行结构。这种机制使得不同频率的策略可以有机结合,例如日频的资产配置策略可以嵌套分钟级的订单执行策略。

高频交易数据处理

高频数据特点

高频交易数据具有以下特点:时间粒度小(通常为秒级或 tick 级)、数据量大、噪声多、包含丰富的市场微观结构信息(如订单簿数据、交易笔数据)。处理高频数据需要考虑数据的完整性、准确性和时效性,同时还需要高效的存储和计算能力。

QLib 提供了专门的高频数据处理工具,能够有效应对这些挑战。下面我们将介绍如何使用 QLib 处理高频数据。

数据处理流程

高频数据处理通常包括以下步骤:数据加载、数据清洗、特征提取和数据存储。QLib 提供了 HighFreqHandler 和相关工具类来简化这些流程。

首先,我们需要初始化 QLib 环境,指定高频数据的存储路径和相关配置:

import qlib
from qlib.constant import REG_CN
from qlib.config import HIGH_FREQ_CONFIG

# 自定义配置
SPEC_CONF = {
    "custom_ops": [DayLast, FFillNan, BFillNan, Date, Select, IsNull, Cut],
    "expression_cache": None
}

# 合并配置
QLIB_INIT_CONFIG = {** HIGH_FREQ_CONFIG, **SPEC_CONF}

# 初始化 QLib
qlib.init(**QLIB_INIT_CONFIG)

上述代码中,我们使用了 QLib 提供的 HIGH_FREQ_CONFIG 作为基础配置,并添加了自定义的操作和缓存设置。custom_ops 参数指定了在数据处理中可能用到的自定义操作符,expression_cache 设置为 None 表示不使用表达式缓存,这在处理高频数据时可以减少内存占用。

接下来,我们可以定义一个高频数据处理器 HighFreqHandler 来加载和处理数据:

from qlib.data.dataset.handler import DataHandlerLP

class HighFreqHandler(DataHandlerLP):
    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        # 设置特征和标签
        self.fields = {
            "feature": [
                "$close / Ref($close, 1) - 1",  # 收益率
                "$volume",  # 成交量
                "$open - $close",  # 开盘价与收盘价之差
                # 更多特征...
            ],
            "label": ["Ref($close, -2) / Ref($close, -1) - 1"]  # 预测目标
        }

# 定义数据处理器配置
DATA_HANDLER_CONFIG = {
    "start_time": "2020-09-15 00:00:00",
    "end_time": "2021-01-18 16:00:00",
    "fit_start_time": "2020-09-15 00:00:00",
    "fit_end_time": "2020-11-30 16:00:00",
    "instruments": "all",
    "freq": "1min",
    "infer_processors": [
        {"class": "HighFreqNorm", "module_path": "highfreq_processor"}
    ],
}

# 创建数据处理器实例
handler = HighFreqHandler(**DATA_HANDLER_CONFIG)

在这个例子中,我们定义了一个 HighFreqHandler 类,继承自 QLib 的 DataHandlerLP。在 __init__ 方法中,我们设置了需要提取的特征和标签。特征包括收益率、成交量、开盘价与收盘价之差等,标签是未来两期的收益率。

数据处理器配置中指定了数据的时间范围、标的范围、频率(1 分钟)以及推理过程中使用的处理器(HighFreqNorm)。HighFreqNorm 是一个高频数据标准化处理器,用于对高频特征进行标准化处理。

高频特征工程

高频交易策略的盈利能力很大程度上取决于特征工程的质量。QLib 提供了丰富的高频特征计算函数和操作符,方便用户构建复杂的高频特征。

以下是一些常用的高频特征及其计算方法:

  1. 价差特征:计算买卖价差及其变化,反映市场流动性。例如,计算买卖一档价差:
spread_1 = "($ask1 - $bid1) / ($ask1 + $bid1) * 2"
  1. 订单簿深度特征:衡量不同价位的订单数量,反映市场深度。例如,计算买卖前五档订单量之和:
depth_ask = "$asize1 + $asize2 + $asize3 + $asize4 + $asize5"
depth_bid = "$bsize1 + $bsize2 + $bsize3 + $bsize4 + $bsize5"
  1. 成交量加权平均价(VWAP) :反映一段时间内的平均成交价格,常用于订单执行算法。例如,计算 5 分钟 VWAP:
vwap_5min = "TResample($close * $volume, '5min', 'sum') / TResample($volume, '5min', 'sum')"
  1. 价格波动特征:衡量价格的波动性,如每分钟收益率的标准差:
volatility_1min = "TRolling(Log($close / Ref($close, 1)), '60s', 'std')"

这些特征可以通过 QLib 的表达式引擎进行计算,并集成到数据处理器中。下面是一个完整的高频特征工程示例:

# 定义高频特征表达式
hf_features = [
    # 价差特征
    "($ask1 - $bid1) / ($ask1 + $bid1) * 2 AS spread_1",
    "($ask2 - $bid2) / ($ask2 + $bid2) * 2 AS spread_2",
    # 订单簿深度特征
    "($asize1 + $asize2) / ($bsize1 + $bsize2) AS depth_ratio",
    # 成交量特征
    "TResample($volume, '5min', 'sum') AS volume_5min",
    # 价格波动特征
    "TRolling(Log($close / Ref($close, 1)), '60s', 'std') AS volatility_1min",
]

# 更新数据处理器的特征配置
handler.fields["feature"] = hf_features

通过这些特征,我们可以捕捉市场的微观结构信息,为高频交易策略提供有力的预测依据。

订单流模拟与回测

回测引擎架构

高频交易的回测需要处理大量的 tick 级数据,对性能和准确性有很高要求。QLib 的回测引擎采用了分层设计,支持多级别嵌套回测,能够准确模拟高频交易环境。

回测引擎的核心组件包括:

  1. Executor:执行器,负责执行交易决策,管理订单生命周期。在嵌套框架中,执行器可以包含内部执行器,形成多层级执行结构。
  2. Strategy:策略,根据市场数据和预测信号生成交易决策。
  3. Broker:经纪商,模拟市场交易环境,包括订单匹配、成交确认等。
  4. Recorder:记录器,记录回测过程中的订单、成交、持仓等信息,用于后续分析。

嵌套执行器配置

在 QLib 中,我们可以通过配置 NestedExecutor 来实现多层级的回测。下面是一个包含日频、30 分钟和 5 分钟三个级别的嵌套回测配置示例:

port_analysis_config = {
    "executor": {
        "class": "NestedExecutor",
        "module_path": "qlib.backtest.executor",
        "kwargs": {
            "time_per_step": "day",  # 外层执行器时间粒度为日
            "inner_executor": {
                "class": "NestedExecutor",
                "module_path": "qlib.backtest.executor",
                "kwargs": {
                    "time_per_step": "30min",  # 中层执行器时间粒度为30分钟
                    "inner_executor": {
                        "class": "SimulatorExecutor",
                        "module_path": "qlib.backtest.executor",
                        "kwargs": {
                            "time_per_step": "5min",  # 内层执行器时间粒度为5分钟
                            "generate_portfolio_metrics": True,
                            "verbose": True,
                            "indicator_config": {
                                "show_indicator": True,
                            },
                        },
                    },
                    "inner_strategy": {
                        "class": "TWAPStrategy",
                        "module_path": "qlib.contrib.strategy.rule_strategy",
                    },
                    "generate_portfolio_metrics": True,
                    "indicator_config": {
                        "show_indicator": True,
                    },
                },
            },
            "inner_strategy": {
                "class": "SBBStrategyEMA",
                "module_path": "qlib.contrib.strategy.rule_strategy",
                "kwargs": {
                    "instruments": market,
                    "freq": "1min",
                },
            },
        },
    },
}

在这个配置中,我们定义了一个三层嵌套的执行器结构:

  • 外层执行器(日频):使用 SBBStrategyEMA 策略生成日频交易决策。
  • 中层执行器(30 分钟):将日频决策分解为 30 分钟级别的子决策,使用 TWAPStrategy 策略执行。
  • 内层执行器(5 分钟):将 30 分钟决策进一步分解为 5 分钟级别的子决策,使用 SimulatorExecutor 进行模拟执行。

这种多层级的执行结构可以更真实地模拟实际交易中的决策过程,提高回测的准确性。

回测指标与分析

回测完成后,我们需要对策略绩效进行评估。QLib 提供了丰富的回测指标计算和可视化工具,可以帮助我们全面评估高频交易策略的表现。

常用的高频回测指标包括:

  1. 年化收益率:衡量策略的盈利能力。
  2. 信息比率:衡量单位风险所获得的超额收益。
  3. 最大回撤:衡量策略的风险水平。
  4. 换手率:衡量策略的交易活跃度。
  5. 订单执行延迟:衡量订单从生成到成交的平均时间。

下面是一个使用 QLib 进行回测结果分析的示例代码:

from qlib.backtest.analysis import backtest_analysis
from qlib.workflow.record_temp import PortAnaRecord

# 执行回测
portfolio_metrics, indicator = backtest_analysis(
    executor=executor,
    strategy=strategy,
    benchmark=benchmark,
)

# 记录回测指标
PortAnaRecord(portfolio_metrics, indicator).save()

# 打印关键指标
print("年化收益率: {:.2%}".format(portfolio_metrics["annualized_return"]))
print("信息比率: {:.2f}".format(portfolio_metrics["information_ratio"]))
print("最大回撤: {:.2%}".format(portfolio_metrics["max_drawdown"]))

通过这些指标,我们可以全面评估策略的风险收益特征,找出潜在的改进空间。

高频策略实现示例

TWAP 策略

时间加权平均价格(TWAP)策略是一种常见的订单执行策略,其目标是使订单的执行价格尽可能接近这段时间内的平均价格。TWAP 策略通常将大额订单拆分为多个小额订单,在一段时间内均匀执行。

在 QLib 中,我们可以通过 TWAPStrategy 类来实现 TWAP 策略。下面是一个使用 TWAP 策略的示例:

from qlib.contrib.strategy.rule_strategy import TWAPStrategy

# 初始化 TWAP 策略
strategy = TWAPStrategy(
    instruments="csi300",  # 标的池
    freq="30min",  # 执行频率
    trade_ratio=0.1,  # 每次执行订单的比例
)

# 在嵌套执行器中使用 TWAP 策略
inner_executor_config = {
    "class": "SimulatorExecutor",
    "module_path": "qlib.backtest.executor",
    "kwargs": {
        "time_per_step": "30min",
        "strategy": strategy,
    },
}

在这个示例中,我们创建了一个 TWAP 策略实例,指定了标的池为沪深 300 指数成分股,执行频率为 30 分钟,每次执行订单总量的 10%。然后将该策略配置到 30 分钟级别的执行器中。

SBB 策略

SBB(Smart Beta and Alpha)策略是一种结合了因子选股和市场时机选择的策略。在高频交易场景中,SBB 策略通常基于短期市场趋势和流动性指标来调整持仓。

QLib 提供了 SBBStrategyEMA 类来实现基于指数移动平均(EMA)的 SBB 策略。下面是一个示例:

from qlib.contrib.strategy.rule_strategy import SBBStrategyEMA

# 初始化 SBB 策略
strategy = SBBStrategyEMA(
    instruments="csi300",
    freq="1min",
    fast_window=5,
    slow_window=20,
    threshold=0.001,
)

# 在日频执行器中使用 SBB 策略
outer_executor_config = {
    "class": "NestedExecutor",
    "module_path": "qlib.backtest.executor",
    "kwargs": {
        "time_per_step": "day",
        "inner_strategy": strategy,
        # 其他配置...
    },
}

在这个示例中,我们创建了一个 SBBStrategyEMA 实例,使用 5 分钟和 20 分钟的 EMA 交叉作为交易信号,当短期 EMA 上穿长期 EMA 且价差超过阈值(0.001)时买入,反之卖出。

高频预测模型

除了基于规则的策略,我们还可以使用机器学习模型来预测高频价格走势,从而构建更复杂的高频交易策略。QLib 提供了 HFLGBModel 类,专门用于高频场景下的 LightGBM 模型训练和预测。

下面是一个使用 HFLGBModel 构建高频预测模型的示例:

# 定义模型配置
task = {
    "model": {
        "class": "HFLGBModel",
        "module_path": "qlib.contrib.model.highfreq_gdbt_model",
        "kwargs": {
            "objective": 'binary',
            "metric": ['binary_logloss','auc'],
            "verbosity": -1,
            "learning_rate": 0.01,
            "max_depth": 8,
            "num_leaves": 150,
            "lambda_l1": 1.5,
            "lambda_l2": 1,
            "num_threads": 20,
        },
    },
    "dataset": {
        "class": "DatasetH",
        "module_path": "qlib.data.dataset",
        "kwargs": {
            "handler": {
                "class": "Alpha158",
                "module_path": "qlib.contrib.data.handler",
                "kwargs": data_handler_config,
            },
            "segments": {
                "train": ["2020-09-15", "2020-11-15"],
                "valid": ["2020-11-16", "2020-11-30"],
                "test": ["2020-12-01", "2021-01-18"],
            },
        },
    },
}

# 初始化模型并训练
model = init_instance_by_config(task["model"])
dataset = init_instance_by_config(task["dataset"])
model.fit(dataset)

# 预测
pred = model.predict(dataset)

在这个示例中,我们使用 HFLGBModel 定义了一个 LightGBM 模型,用于预测高频价格走势。模型的目标函数为二分类(上涨/下跌),使用对数损失和 AUC 作为评估指标。数据集使用 Alpha158 因子集,并分为训练集、验证集和测试集。训练完成后,我们可以使用模型对新数据进行预测,生成交易信号。

总结与实践建议

高频交易是一个复杂且具有挑战性的领域,需要深入理解市场微观结构、高效的数据处理能力和先进的策略设计方法。QLib 提供的嵌套决策执行框架为高频交易策略的开发和回测提供了强大的支持,使得多级别策略的协同优化成为可能。

在实际应用中,建议从以下几个方面入手:

  1. 数据质量控制:高频数据往往包含噪声和异常值,需要进行严格的数据清洗和预处理。可以使用 QLib 提供的数据处理器和自定义过滤规则来提高数据质量。
  2. 特征工程:高质量的特征是高频策略成功的关键。除了本章介绍的基本特征外,还可以探索订单流不平衡、成交量加权平均价偏差等更复杂的微观结构特征。
  3. 策略组合:单一策略往往难以适应多变的市场环境,可以考虑将不同频率、不同类型的策略进行组合,通过嵌套执行框架实现协同优化。
  4. 风险控制:高频交易对风险控制要求极高,需要设置严格的止损机制、仓位限制和流动性风险管理措施。
  5. 性能优化:高频交易对系统性能有很高要求,可以通过优化数据存储(如使用 Arctic 数据库)、并行计算和代码优化等方法提高系统的处理能力和响应速度。

总之,QLib 为高频交易策略的开发提供了全方位的支持,从数据处理到模型训练,再到回测和评估,形成了一个完整的生态系统。通过不断探索和实践,我们可以构建出更加稳健和高效的高频交易策略。