QCon2023-探索智能量化交易系统中的性能优化秘籍

金融市场的行情数据,如股票价格、成交量、交易队列等是典型的时间序列数据,具有很强的时间性和顺序依赖性。智能量化交易系统需要对市场上高频产生的时间序列数据进行处理计算,输入深度学习模型进行预测,执行交易策略,生成交易行为进行交易。整个过程需要覆盖全市场一万以上的品种,并且需要在很小的时间窗口,比如秒级完成。

黄益聪团队使用多语言进行系统开发。其中数据采集模块使用了 C++ 以达到高性能,交易策略引擎使用了 Java Spring Boot 搭建服务,AI 模型使用了 Python 基于 TensorFlow 和 Torch 框架。业务需求的系统低延迟计算和多语言系统模块的交互,给性能优化带来了挑战。

在 12 月 28 日上海 QCon 软件开发大会上,我们邀请了楷同科技有限公司 CEO 黄益聪老师来演讲,分享他们是怎么降低高频产生、长生命周期数据对 Java GC 的影响,怎么高效部署调用低延迟、多模型、多版本的 AI 模型预测服务,系统故障的数据断点快速恢复等。希望对大家有帮助。

技术整合与性能挑战1. 背景介绍

InfoQ:您能解释一下量化交易系统的基本原理吗?

黄益聪:量化交易是利用计算机程序和数学模型来制定和执行交易策略的一种交易方式。它基于对市场数据进行分析和模式识别,通过确定性规则或者数理模型来进行决策,而非依赖于主观判断或情绪。其基本原理包括以下几方面:

  • 数据收集与分析:量化交易依赖大量历史和实时市场数据,包括价格、成交量、交易量、新闻事件等。这些数据会被收集并进行分析,以发现市场中的模式、趋势和关联。
  • 策略开发:基于对数据的分析,量化交易者会开发交易策略和模型。这些策略可能基于统计模型、机器学习算法、技术分析指标或者其他金融理论。
  • 模型验证与优化:开发出的交易模型需要经过验证和优化,以确保其在历史数据上表现良好,并具有较好的泛化能力。这个过程通常涉及对模型进行回测和参数优化。
  • 执行交易:一旦模型经过验证,并且达到了预期的性能水平,量化交易系统就会根据这些模型生成的信号执行交易。这可能包括自动发送买入、卖出指令到交易所或市场。
  • 风险管理:量化交易也非常注重风险管理。它们通常会设定止损点、仓位控制和其他风险管理规则,以限制潜在损失。

近几年,随着计算机技术和数据分析技术的进步,量化交易开始应用更复杂的数学模型,如机器学习和人工智能模型。这些技术使得量化交易系统有了飞速的发展和进步。

2. 多语言数据处理

InfoQ:在将 C++ 生成的高频时间序列数据整合到 Java 环境中时,您面临了哪些主要的性能挑战?

黄益聪:首先,我使用了多语言来开发整个智能量化交易系统。在前端与交易所柜台交互的实时行情数据收集处理与交易下单模块,我们使用了 C++ 进行开发,以实现高效性能;在系统服务层,包括了账户管理、风控、策略、实时通知等,我们使用了 Java SpingBoot 进行开发,以利用成熟的开发框架,和 Java 的动态语言能力,实现热部署与策略代码的热更新;在 AI 模型服务,我们使用了 Python 进行开发,使用了业界流行的 TensorFlow 和 Torch 框架。从每个模块和服务看,对开发语言的选择都是比较合理的,但是从整个系统看,我们就面临多语言交互的问题。

其次,如何快速处理高频时间序列数据是我们的主要性能挑战。数据特点:生成速度快,tick 级别行情数据,高频产生;数据量大,期货市场上万个品种合约,A 股市场 5000 多只股票,数据类型和字段多,包括多档行情,逐笔委托、成交、数据等;数据生命周期长,在使用模型对未来行情进行预测时,我们不仅使用当前时间窗口的数据,而且使用了最近 n 个时间窗口的数据,所以一个高频产生的数据的生命周期至少需要经历 n 个时间窗口。

第三,数据怎样高效地在多语言中进行传递,以及减少 GC 对性能的影响,是我们需要解决的性能问题。基于以上多语言交互,我们需要高效地把高频数据从 C++ 传递到 Java;同时,需要有好的方法尽可能减少高频产生、大数据量、长生命周期数据带来的 GC 性能损耗。

最后,我们全链路的数据处理计算以及模型预测的时延需要再秒级完成。3.Java 垃圾收集优化

InfoQ:您能具体描述一下如何降低长生命周期数据对 Java 垃圾收集 (GC) 的影响吗?

黄益聪:如问题 2 的回答描述,我们的数据特点是高频产生、大数据量、长生命周期。这是业务本身决定的。刚开始我们尝试使用数据采样降频,将数据采集和计算的时间间隔从 tick 级别降到秒级或者分钟级别。这种方式确实缓解了性能挑战,但是需要业务进行妥协,可能丢失了好的交易机会。

InfoQ:在优化 GC 方面,您采用了哪些策略或技术?

黄益聪:在系统层,我们使用了 Linux HugePage, 它允许将内存划分为更大的页面。从而,对 Java 的大内存 heap 带来了一些好处,减少内存碎片,减少内存页表条目,减少 TLB(Translation Lookaside Buffer)Miss,提高性能。

在 JDK 应用层,我们尝试了不同的 GC 算法,包括 CMS GC、G1 GC、ZGC。其中,ZGC 在测试中表现出了最好的性能。ZGC 使用了读屏障和染色指针等技术,并发处理垃圾回收,允许在几毫秒范围内执行非常小的暂停。但是,由于我们的数据特点,不同 GC 算法的尝试只能缓解问题,并不能完全解决和达到我们的性能需求。

在数据交互层,我们尝试使用了 Direct Buffer。Direct Buffer 允许 Java 和 C++ 直接访问内存区域,无须进行数据拷贝。同时,Direct Buffer 不受 Java 垃圾回收管理,能有效减小 GC 的性能损耗。但是,JDK 对 Direct Buffer 使用进行了封装,使用 ByteBuffer 类封装了读写操作,而且底层实现会涉及到更多的方法调用和边界检查。虽然,Direct Buffer 提供了比较高的安全和稳定性,但是我们希望追求更极致的性能,因此也需要更好的解决方案。

InfoQ:您最终是如何优化 Java 和 C++ 之间的数据交互,以提高整体处理效率的?

黄益聪:我们最终使用了 2 个优化方法实现 C++ 和 Java 之间的高效数据交互。

在内存管理,我们直接使用 Java Unsafe 方法管理内存,像操作 C++ 内存指针一样,实现内存的分配、回收、读写。Unsafe 类提供了对内存的直接访问,绕过了 JVM 对于堆内存的管理,因此可以实现更直接的内存操作,减少了一些额外的边界检查和方法调用,可能带来更高的性能。同时,Unsafe 类使用更少的内存屏障(Memory Barriers),这在需要频繁操作内存的场景下会有一定的性能优势。需要注意的是,Unsafe 方法也有一定局限性,需要非常注意代码安全,避免内存泄露、越界访问。

在代码层面,我们使用了循环共享内存池存储行情数据。在行情订阅时,预先分配好内存,仅在服务结束时,回收内存。行情接收时,数据循环写入预分配的内存池。预分配的内存足够大,依据数据吞吐率计算,以保证在新数据循环写入前,老数据已经被处理、计算完成。

通过优化,我们取得了很好的性能优化效果。Java 仅需使用 2g heap(不包括共享内存,共享内存依据业务订阅的行情确定),就保证了系统的高性能运行,tp99<2ms。

AI 模型预测与系统稳定性1.AI 模型预测服务部署

InfoQ:您是如何实现低延迟、多模型、多版本 AI 模型预测服务的高效部署的?

黄益聪:AI 模型预测服务,TensorFlow 提供了相对成熟、完整的 tf serving 服务,并且支持多模型、多版本的更新。我们基于 tf serving 定制开发了模型预测服务。在性能优化上,我们做了一些工作:

  • Use AVX2,FMA:配置和编译 TensorFlow,利用机器指令集,提升向量化和浮点计算性能
  • 数据精度裁剪,在不明显影响模型预测效果的前提下,对数据进行裁剪,比如使用 float32 代替 float64,int8 代替 int32
  • Java client to server: 我们直接使用 Java 请求 tf serving, 而不通过 Java 调用 Python client 请求 server
  • gRPC prior to http: 使用 gRPC 协议,高效二进制序列化格式,支持多路复用,更轻量、快速,节省带宽
  • 重用对象、重用连接
  • 批量数据预测
  • warm-up:在行情正式开始前,使用历史数据进行预热,提前预加载模型,缓存数据和优化预测路径

在多框架支持上,我们尝试了使用 LLM 将 Torch 代码转成 tf 代码,在人工修改校验后运行。目前,还没有开发更优的解决方案。

InfoQ:在部署这些服务时,您如何平衡性能和资源消耗?

黄益聪:我们对线上服务所需的资源消耗是比较好确定的。与面向用户的服务系统不同,我们的系统流量不会有突然的增幅或者下降,而是相对平稳。系统的资源需求与量化交易系统订阅和交易的品种数量正相关。我们业务确定好需要交易的品种、系统要求的响应时间和吞吐量后,在线下进行压测就可以确定好部署服务所需要的资源需求。2. 系统故障恢复

InfoQ:面对系统故障,您设计了哪些数据断点快速恢复策略?

黄益聪:首先,我们把单个服务拆分成了行情和交易服务,对行情数据的采集做了冗余服务。行情服务不受交易服务的影响,异步将实时行情数据存储入实时数仓。当交易服务出现故障重启时,交易服务可以快速从实时数仓读取断点之前 n 个时间窗口的数据,进行模型预测和交易服务。其次,我们还配置了守护进程对交易服务和行情服务的健康状态进行监控。最后,我还设置了一层账户风控模块,当交易异常,账户盈亏触及阈值时,及时终止系统,并发送报警提醒。

经验总结与未来展望

InfoQ:在这个全链路优化过程中,您学到了哪些关键的性能优化经验?您能分享一些具体的技术或策略,这些可能对同行业的专业人士特别有价值?

黄益聪:在全链路优化过程中,以下是我们觉得好的性能优化方法和原则:

  • data driven: 获取足够的数据以驱动优化工作。使用监控工具和指标来跟踪系统性能,了解系统瓶颈和性能瓶颈所在,例如使用监控指标、日志、分析工具等。
  •  top-down: 确定系统性能的指标和目标,例如响应时间、吞吐量等。确定影响系统性能的关键路径。从关键路径开始,逐步深入到具体的模块或组件层面,进行详细的优化工作。可以采取不同的优化手段,例如算法优化、资源利用优化、并发优化等。
  •  Continuous Optimization:性能优化是一个持续的过程,随着系统的不断演化和变化,需要持续地监控和优化系统性能,不断迭代优化过程。
  • fault tolerance and rapid recovery:充分考虑链路中可能出错的节点,并设计措施保证错误的局部影响不扩散,故障后能快速恢复或者终止。

InfoQ:您如何看待智能量化交易系统在性能优化方面的未来发展趋势?面对不断发展的技术和市场需求,您认为未来还有哪些新的挑战和机遇?

黄益聪:未来发展趋势:

  • 超低延迟交易系统:高频量化交易需要更快的执行速度和更低的延迟。未来的发展可能围绕着优化算法、硬件设备、网络架构等方面,以实现更快速的交易执行和更高的实时性能。
  • 更智能的交易决策:结合人工智能和机器学习技术,提供更智能的交易决策和应用更复杂的预测模型,包括更复杂的模型架构,更长的数据时间窗口,以优化交易策略和风险控制,进一步提高交易效率和收益。
  • 多样化市场:交易不仅局限于单一股票市场或者期货市场,还涉及到加密货币、外汇、境外市场交易、金融衍生品等多样化资产。优化性能需要考虑更多资产类型和不同市场的交易。

新的挑战:

  • 监管和法规变化:今年,国内对量化交易发布了监管新规,对交易频次,报单笔数等进行规定和监管。不同国家和地区的监管法规对于量化交易系统的要求可能不同,需要应对监管环境的变化,保证系统合规性,并在合规框架内实现性能优化。
  • 数据隐私和安全:大量敏感交易数据的处理和存储,对数据隐私和安全提出了更高的要求,需要更严格的数据安全措施和隐私保护机制。

I

发表评论

您的电子邮箱地址不会被公开。 必填项已用 * 标注

Scroll to Top