亚马逊AWS官方博客

利用 Amazon FinSpace 构建 Quant Data Analytics 应用

在金融行业,尤其是量化对冲基金领域,数据分析扮演着至关重要的角色。这一领域的分析师需要处理海量的金融市场数据,包括股票、期货、外汇等各类资产的历史和实时价格、交易量、财务报表等信息。功能需求方面,分析系统需要能够进行多维度的数据挖掘和模式识别,并能够快速构建和回测交易策略。同时,系统还需要具备强大的可视化能力,以直观呈现分析结果。在性能需求方面,由于金融市场瞬息万变,分析系统必须能够实时处理大规模数据流,并在毫秒级别内完成复杂计算和决策制定。此外,系统的稳定性和可靠性也至关重要,需要能够 7×24 小时不间断运行,并具备高度的容错能力和安全性。总的来说,量化对冲基金的数据分析系统需要在功能的全面性和性能的极致要求之间取得平衡,以支持基金在激烈的市场竞争中保持领先地位。kdb+ 是在金融行业,尤其是量化对冲基金领域有着广泛应用场景的时序数据库。本文围绕 kdb+ 以及 Amazon 托管的 kdb+ insights 服务,即 Amazon FinSpace,展开对 kdb+,尤其是 Amazon FinSpace 的架构以及功能介绍,并详细描述了如何利用 Amazon FinSpace 构建一个 Quant Data Analytics 应用的操作过程。

1. kdb+ 介绍

kdb+ 是一种高性能的列式内存数据库,广泛适用于金融、物联网、电信等领域的海量数据分析处理。它拥有非常简洁的语法和极高的执行效率,能够快速处理 TB 级别的数据。kdb+ 使用 q 语言进行编程,q 语言是一种类似于 SQL 的查询语言,但更为简洁和灵活。kdb+ 的独特之处在于其列式存储和向量化处理,充分利用了现代硬件的特性,如 CPU 缓存和 SIMD 指令,从而实现了超高的性能。此外,kdb+ 还内置了丰富的数据类型和函数库,支持实时流数据处理和复杂的分析计算。凭借其优异的性能和强大的功能,kdb+ 已经成为金融领域的事实标准,并正在被越来越多的行业所采用。

kdb+ 作为一款高性能的时序数据库,在金融领域有着广泛的应用。金融行业产生海量的交易数据、行情数据和衍生工具数据,对数据处理的实时性、准确性和并发性要求极高。kdb+ 凭借其列式存储矢量化处理、内存计算、数据压缩等特性,能够高效地存储和查询时序数据,单核每秒可处理数百万到上千万条记录,性能远超传统数据库。kdb+ 提供了丰富便捷的数据分析函数,内置时间序列处理、窗口计算等功能,使交易分析、风险管理、高频交易等场景开发便捷高效。此外,kdb+ 采用进程内编程语言 q,速度较 C/C++ 相近,但开发效率远高于其他编程语言。凭借性能和功能优势,kdb+ 已成为高盛、摩根大通等大型金融机构的核心技术标准,被广泛应用于算法交易、实时风控、流动性管理等领域。Kdb+ 的架构介绍可以参考此文

作为时序数据库,kdb+ 是目前性能最好的。kdb+ 与业界几种较流行的时序数据库的性能比较如下面柱状图和表格所示。在同等硬件条件下,kdb+ 与其他几种时序数据库的 Throughput 性能比较如图 1 所示。

图 1. 几种时序数据库 Throughput(MBps)性能比较

几种不同 benchmark 的读性能比较见表 1。

表 1. 几种时序数据库读性能(latecy (ms))比较

Benchmark ID[1] kdb+ in-memory kdb+ on-disk InfluxDB Timescale ClickHouse
T-V1 57 81 93 469 272
T-V2 740 273 3700 1991
O-T 5 11 124 10 706
O-B1 94 146 3938 962
O-B2 287 440 12847 3202
O-NBBO 5 34 191 1614 454

几种不同 benchmark 的计算密集性 query 性能比较见表 2。

表 2. 几种时序数据库计算密集性 query 性能(latecy (ms))比较

Benchmark ID kdb+ in-memory kdb+ on-disk InfluxDB Timescale ClickHouse
T-VWAP 26 75 12716 334 202
O-S 1352 1386 623732 2182 14056
O-V1 533 373 4699 1626
O-V2 4375 4420 17092 10180

几种不同 benchmark 的复杂 query 性能比较见表 3。

表 3. 几种时序数据库复杂 query 性能(latecy (ms))比较

Benchmark ID kdb+ in-memory kdb+ on-disk InfluxDB Timescale ClickHouse
C-R 64 113 99 1614 401
C-VT 41 51 2009 324 190
C-VO1 61 96 94 1591 407
C-VO2 688 242 4319 1139

注:以上性能对比数据信息来自 paper:Benchmarking Specialized Databases for High-frequency Data,https://arxiv.org/abs/2301.1256

2. Q 语言简介

Q 是一种用于开发 kdb+ 数据库系统的高效向量化编程语言。Q 语言的语法非常简洁,大量使用单字符的原子函数,并支持向量化编程范式,代码简练而不失可读性。得益于其独特的设计理念,Q 能够实现极高的运行速度和内存利用效率,在金融、电信等行业得到了广泛应用。例如,Q 常被用于实时处理交易数据、风险管理、高频交易等领域。Q 语言的几个特性如下:

  • Q 不使用控制流、循环、if else 块、对象、继承和线程。
  • Q 是一种解释性语言,就像 Python 一样。
  • Q 是动态识别变量类型的,就像 Python 一样,不必提前声明类型。
  • Q 支持矢量操作。
  • Q 支持函数式编程。
  • Q 基于的数据结构:列表和字典。

常见的 Q 操作:

#vector operation
q)1 2 3+10 20 30
11 22 33
q)1+10 20 30
11 21 31
#right to left order operation
q)2*3+4 
14
q)til 3
0 1 2
q)first 10 20 30
10
q)last 10 20 30
30
q)max 10 20 30
30

Q SQL:

q)select date,time,sym,px from t
q)select date,time,qty,px from t where sym=`aapl

q)\t select date,time,qty,px from t where sym=`aapl #show calculation time in miliseconds

q)5#select open:first px, clost:last px from t by date,time where sym=`aapl

Snapshot 1. qSQL 查询结果展示示例

q)5#select open:first px, clost:last px, lo:min px, hi:max px from t by date,time where sym=`aapl

Snapshot 2. qSQL 查询结果示例

3. Amazon FinSpace Managed kdb+ Insights 介绍

Amazon FinSpace Managed kdb+ Insights 是亚马逊云科技推出的全托管服务,旨在帮助金融机构处理和分析大量实时和历史数据。这个服务基于 KX 公司开发的高性能时序数据库 kdb+,可提供毫秒级的低延迟数据摄取、分析和可视化。通过使用 Amazon FinSpace Managed kdb+ Insights,金融机构可以快速构建和部署可扩展的数据驱动型应用程序,如实时风险管理、交易分析、欺诈检测等。该服务具有高度可扩展性,可处理 PB 级别的数据,并支持复杂的数据分析和建模。同时,Amazon FinSpace Managed kdb+ Insights 还提供了强大的安全性和合规性保障,帮助金融机构满足严格的行业监管要求。通过利用 AWS 的云基础设施和 kdb+ 的高性能数据处理能力,该服务为金融机构提供了一种高效、灵活且经济实惠的解决方案,用于管理和分析海量金融数据。

3.1 托管服务的优势

  • 为 kdb+ 提供安全且可扩展的数据管理

轻松存储使用您提供的 KMS 密钥加密的 kdb+ 数据库文件。使用云对象存储技术可以随着数据量的增长无缝扩展 kdb+ 数据库。集成且可配置的高性能缓存可加速重要查询,同时管理缓存数据的成本。内置数据库版本控制允许您回溯以查询之前某个时间点的数据。

  • 启动与 AWS 服务集成的托管 kdb+ 集群

使用简单的 API,客户可以启动和配置 kdb+ 集群。托管 kdb+ Insights 消除了大量运营开销,并为 kdb+ Insights 应用程序提供按使用量付费的计算。托管 kdb+ Insights 与 Terraform 集成,以实现与 CI/CD 工作流和 AWS 服务(例如 CloudWatch、CloudTrail 和 IAM Permissions)的集成。

  • 自动扩展和高可用性以满足业务需求

Managed kdb+ Insights 包含可配置的自动扩展功能,以确保 kdb+ 应用程序能够跟上最不稳定的市场条件。您还可以配置多可用区,以确保 kdb+ 应用程序在更重要的业务时间内具有高可用性。

  • 支持现有的 kdb+ 配置以简化和加速迁移

配置 kdb+ 行情系统、实时集群、历史集群和网关以匹配现有环境,从而轻松迁移现有 kdb+ 工作负载和 Q 代码。除了通过编程式 AWS API 以代码形式进行配置外,客户还可以通过熟悉的 FinSpace 控制台界面设置、访问和管理 kdb+ 环境(数据库和集群)。

除了以上的价值,Amazon FinSpace Managed kdb+ Insights 还有几个特有的 feature,使云上的托管服务比原生产品功能更强。

3.2 Shared Volume 工作机制阐述

Shared Volume 是一种持久化的 NAS(Network Attached Storage),可以同时挂载到多个 kdb+ 实例(如同一应用/不同应用的 Realtime Database (RDB)、Historical Database (HDB) 等)。这使得不同的实例可以共享相同的数据集,从而实现数据共享和协作。用户可以在创建 kdb+ 实例时指定需要附加的共享卷。共享卷可以是新创建的空卷,也可以是已有数据的卷。创建共享卷时需要指定卷的名称、大小和加密选项等属性。当 kdb+ 实例启动时,指定的共享卷会自动挂载到实例上的指定目录。目录的路径是 /opt/kx/app/shared/<VOLUME_NAME>/<CLUSTER_NAME>。FinSpace 使用分布式锁机制来协调不同实例的读写操作,保证数据一致性。即使 kdb+ 实例被终止,shared volume 上的数据也不会丢失。下次启动新的实例时,可以重新挂载共享卷,访问之前的数据。为了保护敏感数据,shared volume 可以启用加密功能。加密使用 AWS KMS(Key Management Service)进行密钥管理。启用加密后,存储在共享卷上的数据以及卷的快照都会被加密。如果共享卷的空间不足,用户可以对其进行在线扩展,而不需要卸载卷或停止 kdb+ 实例。扩展操作会动态地增加卷的大小,新增的空间可以立即使用。Shared volume 的访问权限可以通过 IAM(Identity and Access Management)策略来控制。用户可以定义哪些 IAM entity(用户、角色)能够访问共享卷,并且可以精细地控制每个实体的读写权限。

3.3 Data view 工作机制阐述

Data View 是一种强大的工具,用于探索和分析存储在 FinSpace 中的数据。它为用户提供了一种直观、交互式的方式来查询和可视化数据,而无需编写复杂的 SQL 查询或使用专门的商业智能工具。用户需要选择要在 Data View 中使用的数据源。数据源可以是 FinSpace Notebooks 中的数据表,也可以是外部数据源,如 Amazon S3、Amazon Athena 或 Amazon Redshift。一旦选择了数据源,用户就可以选择要在 Data View 中使用的特定字段(列),这允许用户专注于与其分析相关的数据子集。Data View 提供了强大的过滤和聚合功能,使用户能够细化其数据选择。用户可以应用各种过滤器,如数值范围、文本模式匹配或日期范围,还可以使用诸如 SUM、AVG、COUNT 等聚合函数对数据进行汇总。根据所选的字段和应用的过滤器/聚合,Data View 会自动生成数据的可视化效果。它支持各种图表类型,如条形图、折线图、散点图和饼图。用户可以通过简单的拖放操作来自定义这些可视化效果。Data View 允许用户通过在可视化中钻取和切片数据来进一步探索数据。例如,用户可以点击条形图中的特定条形来查看该特定类别的详细数据。当数据源中的基础数据发生变化时,Data View 会自动更新其可视化效果。这确保了用户始终看到最新的数据,而无需手动刷新视图。Data View 可以与其他 FinSpace 用户共享,促进协作和数据驱动的决策。用户可以将 Data View 嵌入到 Notebooks 中,或生成可共享的链接。如果需要,用户可以将 Data View 中的数据导出为 CSV 格式或将可视化效果下载为图像文件。

3.4 Historical Database(HDB)Data Caching工作机制阐述

图 2. HDB 数据缓存机制示意图

以下面的 qSQL 运行过程为例:

从 qSQL 查询中,kdb+ 知道要读取哪个列(从 where 子句中它知道要读取什么。通常,它只读取您感兴趣的部分而不是读取整个列)。因为 io 访问始终是瓶颈,所以 kdb+ 通过压缩列文件进一步减少 io 访问。压缩率通常为 10。因此,如果数据在内存中为 1GB,那么您只需要在磁盘上读取 100MB。hdb 集群也只加载 sym 文件。目标列部分以及 sym 文件都被加载到内存中以供进一步处理。加载过程是一个延迟加载过程:kdb+ 实际上只有一个指向目标列文件的指针。文件将仅按需加载。对于加载到内存中的数据没有数据分发机制。所有目标数据都将加载到单个节点的内存中。网关充当所有 hdb 集群节点前面的负载平衡器,以确定哪个节点能够处理查询工作负载并将查询作业分配给该节点。

4. 构建 Quant Data Analytics 应用

4.1 Quant Research Analytics 应用功能和架构介绍

本应用利用 Amazon FinSpace Managed kdb+ Insights 实现了托管的 Quant 数据分析应用。应用实现了实时 tick 数据接入、数据缓存、数据实时订阅、数据归档、数据查询(数据应用开发)以及历史数据存储。应用中数据通过 kxtaqfeed.q 脚本生成。数据的 schema 如下:

Table Trade:
sym: symbol(stock symbol)
time: Timestamp
price: Float(trade price)
size: Integer(trade size/volume)

Table Quote:
sym: symbol(stock symbol)
time: Timestamp
bid: Float(bid price)
ask: Float(ask price)
bsize: Integer(bid size)
assize: Integer(ask size)

数据的 symbol list 是:

[`AMD`,`AIG`,`AAPL`,`DELL`,`DOW`,`GOOG`,`HPQ`,`INTC`,`IBM`,`MSFT`,`ORCL`,`PEP`,`PRU`,`TXN`]

应用包含 Feed Handler(简称 FH)、Ticker Plant(简称 TP)、Realtime Database(简称 RDB)、Realtime Subscriber(简称 RTS)、Historical Database(简称 HDB)、Gate Way(简成 GW)。其中 FH 向 TP 发送实时 Tick 数据。生成环境 FH 需要对接数据供应商。实时数据发送到 TP 后会随即被 RDB 和 RTS 接收。RDB 用来存放当天的数据,满足研究员对当天数据的实时性要求高的复杂分析(往往会涉及数据查询的时间跨度)。每天结束的时候会有一个 EOD 数据同步的任务将 RDB 中的数据同步到 HDB 中(本应用通过运行 manual_eod.ipynb 实现数据同步)。RTS 和 RDB 相似,主要用来做实时数据的计算,如实时更新交易量的数据等等。HDB 会存放所有的历史数据,用于基于历史数据的分析、建模等。GW 同时连接 HDB 和 RDB。通过 GW,研究员可以查询当天的数据,同时也可以查询历史数据。不同的 module 可以查看(只读)其他 module 的 shared volume。比如,RDB 可以查看 HDB 的 shared volume。

本应用所有模块构建代码、数据查询的代码、debug 的代码都是通过 python 完成。

图 3. Quant Research Analytics 应用架构

4.2 准备

4.2.1 PyKX Client 所需要的 license 下载

通过以下入口申请 kdb+ Insights Personal Edition 的 license 作为所需要的 PyKX Client 的 license:

https://kx.com/kdb+-insights-personal-edition-license-download/

而不是 kdb+ Personal Edition 的 license。(申请的入口是

https://kx.com/kdb+-personal-edition-download/

点击下面 snapshot 中的链接下载 license 文件(kc.lic)

Snapshot 3. kdb+ Insights license email

4.2.2 带有 PyKX Client 的 Jupyter notebook 安装

在一台 ec2 上安装 jupyter notebook。这个 notebook 将作为 pykx 的 client。安装具体操作步骤如下:

(1)以 ec2-user 用户登录 ec2 实例。在 ec2 console 上运行,在 region 提示中输入应用计划部署的 region id,如 us-east-1

aws configure

(2)安装 Anaconda,操作命令如下

遇到 license 提示,回答 yes。Yes to default install location,yes to modifying ~/.bashrc

wget https://repo.anaconda.com/archive/Anaconda3-2022.05-Linux-x86_64.sh
sh ./Anaconda3-2022.05-Linux-x86_64.sh

source ~/.bashrc

(3)安装 git

sudo yum install git -y

(4)安装 JupyterQ Kernel

conda install -c kx jupyterq -y

(5)安装 Bash Kernel

pip install bash_kernel
python -m bash_kernel.install

(6)安装 PyKX

pip install --upgrade pip
pip install pykx
pip install boto3 --upgrade

(7)将 PyKX 的 client 的 license file(名字是 kc.lic 的文件)指向 jupyterq 的 kernel

首先,确保 kc.lic 文件在 ec2 的 local storage 上。

ln -s ~/kc.lic ~/anaconda3/q

(8)更新 ~/.bashrc 文件,命令如下

export QHOME=/home/ec2-user/anaconda3/q
export PATH=$QHOME/l64:$PATH
export SSL_VERIFY_SERVER=0

(9)启动 Jupyter Lab

两种启动方式,如果是在本机上使用 ssh tunnel 登录 ec2,运行如下命令:

nohup jupyter lab --no-browser &> nohup_jupyter.out &

# check server is running
jupyter server list

如果是通过 Session Manager 登录 ec2,运行如下命令:

nohup jupyter lab --ip=0.0.0.0 --no-browser &> nohup_jupyter.out &

# check server is running
jupyter server list

将下面的<internal_ip>替换成 ec2 的 Public IP Address,在 web browser 中输入 http://<public_ip>:8888,得到下面截图中的提示,在对话框中输入 token 的 value,可以完成对 jupyter lab 的登录。

Currently running servers:
http://<interal_ip>:8888/?token=<token> :: /home/ec2-user

4.3 FinSpace Application 构建步骤

https://github.com/aws/amazon-FinSpace-examples/tree/main/Managedkdb+Insights/basic_tick_V3 的 git repo 同步到 jupyter lab 中。

Folder basictick 中的文件是生成本应用所需的 data 的用 q 语言写的脚本;creat_all.ipynb 中包含应用所需要的各个模块的创建方法;

managed_kx.py, env.py, bastictick_setup.py 这三个 python 脚本中包含了应用运行依赖的基础方法和变量。其中,需要着重 highlight 的有以下几点:

  • 通过配置 py 中的 VPC_ID 变量值,约束 FinSpace 应用和 pykx client 的 ec2 实例在同一个 VPC 中。这个约束确保 pykx client 可以和 FinSpace 应用的各个模块通信。同时,需要注意所选择 SECURITY_GROUPS 的 inbound rules 的配置,确保 TCP 流量放通。
  • env.py 中的 AWS_ACCESS_KEY_ID,AWS_SECRET_ACCESS_KEY ,AWS_SESSION_TOKEN 配置成 None。这样可以保证后续 notebook 的 cell code 在运行的时候会从 ec2 上自动获取 credentials,可以减少配置工作量。
    AWS_ACCESS_KEY_ID=None
    AWS_SECRET_ACCESS_KEY=None,
    AWS_SESSION_TOKEN=None
    
  • managed_ky.py 脚本中的 get_kx_connection_string 方法返回值需要将 tls 的值由 True 改成 False,目的是关闭 Pykx client 连接 FinSpace 应用模块的 tls 鉴权。
    def get_pykx_connection(client, clusterName: str, userName: str, boto_session, endpoint_url: str=None, environmentId:str=None):
        if environmentId is None:
            environmentId = get_kx_environment_id(client)
    
        import pykx as kx
    
        conn_str = get_kx_connection_string(client, 
                                          environmentId=environmentId, clusterName=clusterName, userName=userName,
                                          boto_session=boto_session, endpoint_url=endpoint_url)
    
        host, port, username, password = parse_connection_string(conn_str)
        
        return kx.QConnection(host=host, port=port, username=username, password=password, tls=False)
    
  • create_all.ipynb 中 Start FeedHandler 部分的 cell code(In[24])中 QHOME 的值需要赋值为 /home/ec2-user/anaconda3/q。
    os.putenv("QHOME","/home/ec2-user/anaconda3/q")
    
    # get the connection string to the TP cluster
    conn_str = get_kx_connection_string(client, environmentId=ENV_ID, clusterName=TP_CLUSTER_NAME, userName=KDB+_USERNAME, boto_session=session)
    
    # populate the environment variable with connection string
    os.putenv("CONN_STR", conn_str)
    
    # optional
    feed_debug = 0
    
    # start q process kxtaqfeed to connect to the TP at $TP_CONN
    if os.getenv('QHOME') is not None:
        pid=subprocess.Popen(f'cd {CODEBASE}; nohup $QHOME/l64/q kxtaqfeed.q -g 1 -p {FH_PORT} -tp $CONN_STR -debug {feed_debug} -t {FEED_TIMER}', shell=True)
    
    else:
        print("Environment variable QHOME is not set, please set to where kdb+ is installed")
    
    # wait for feedhandler to start doing its thing
    time.sleep(2)
    

应用构建的代码可以参考 create_all.ipynb,里面有详细的操作指导和运行效果展示;

每个 module 的 query 代码可以参考 pykx_query_all.ipynb。本文不再赘述。

5. 总结

作为金融和大数据领域公认的顶级时序数据库,kdb+ 以其卓越的性能和高效的数据处理能力在业界独树一帜。为了进一步提升 kdb+ 的应用便利性和扩展性,亚马逊云科技推出了 Amazon FinSpace Managed kdb+ Insights 服务。这一托管解决方案不仅继承了原生 kdb+ 的强大功能,还在安全性、可扩展性和高可用性等方面进行了全面增强。用户可以轻松配置和迁移,同时享受自动扩展的优势,满足不断变化的业务需求。更重要的是,Amazon FinSpace Managed kdb+ Insights 与众多亚马逊云科技原生服务无缝集成,为用户提供了更加全面和强大的云端数据分析能力。本文将深入探讨 Amazon FinSpace 的架构特点,并详细阐述如何利用这一平台构建高效的量化数据分析应用,为金融机构和数据科学家提供实用的指导和参考。

6. 参考资料

7. 附件

表 4. 文中出现的几种数据库性能测试的 benchmark 说明

分类 Benchmark ID 规格描述 I/O 密集度 计算密集度
交易 T-V1 一天内以 1 分钟间隔的平均交易量 轻度读取 轻度
T-V2 一个月内的平均每日交易量 重度读取 轻度
T-VWAP 一天内以 1 分钟间隔的成交量加权平均价格(VWAP) 轻度读取 重度
订单簿 O-T 在随机时间生成订单簿顶部 轻度读取 轻度
O-B1 找出一周内最高出价 轻度读取 轻度
O-B2 找出一个月内最高出价 重度读取 轻度
O-S 一天内的买卖价差 轻度读取 重度
O-V1 使用一周内 1 分钟间隔的平均成交量找出顶级市场深度 轻度读取 重度
O-V2 使用一个月内 1 小时间隔的平均成交量找出第 5 级市场深度 重度读取 重度
O-NBBO 一天内的全国最佳买卖报价(NBBO) 轻度读取 轻度
复杂查询 C-R 一天内以 5 分钟间隔的中间报价回报 轻度读取 轻度
C-VT 计算一天内以 5 分钟间隔的执行价格回报的每小时标准差作为波动率 轻度读取 重度
C-VO1 计算一天内以 5 分钟间隔的中间报价回报的每小时标准差作为波动率 轻度读取 重度
C-VO2 计算一周内以 1 小时间隔的中间报价回报的每 4 小时标准差作为波动率 轻度读取 重度

[1] Benchmark 说明见附件表 4

本篇作者

魏诗洋

亚马逊云科技资深解决方案架构师。专注金融行业云上系统架构及解决方案设计。关注大数据、机器学习在金融行业的应用,以及金融行业监管合规对云上系统架构设计的影响机制。10年+数据领域研发及架构设计经验。