《开发高频交易系统》第二部分(译文)

论坛 期权论坛 股票     
期权匿名问答   2023-2-6 04:16   2021   0
第4章 HFT 系统基础——从硬件到操作系统

    在上一章中,我们了解了交易所的工作原理。我们回顾了交易所和匹配引擎的功能组件。本章将介绍 HFT 系统的基本硬件和操作系统 (OS)。
    本章将涵盖以下主题:

  • 了解高频交易计算机
  • 针对高频交易如何使用操作系统
  • 编译器的作用
    我们将在后面的章节中了解到,高频与交易策略的类型和您交易的资产以及您交易的交易所的能力有关。实现 100 微秒的即时交易延迟需要仔细的编程和对底层硬件的深入了解。您需要编写最好的代码来利用 CPU 及其内存架构,并最大限度地减少 I/O 操作的开销。本章的重点是获得基线(就我们应该拥有的硬件和操作系统而言),以便拥有一个能够实现良好性能的自动交易系统。后面的章节将帮助我们完善这一点,应用不同的优化技术来改善交易系统的延迟,使我们的延迟甚至低于 10 微秒。
    假设您想深入了解现代计算机系统体系结构的工作原理。在这种情况下,John Hennessy 和 David Patterson 合着的经典著作《计算机体系结构:定量方法》对此进行了详细解释,并开发了统计模型以帮助理解性能权衡。在本章中,我们将重点关注高频交易系统运行所需的部分。下一节将介绍该系统所使用的机器的硬件。
了解HFT系统

    很容易想到您可能需要一些专门的计算机硬件来执行任何低延迟交易策略。事实并非如此——大多数硬件都是普通的现成硬件。在大多数情况下,如何配置硬件更为重要。图 4.1 显示了一个主 CPU,代表了 HFT 系统的开发人员如何考虑 CPU 的架构。



图4.1——主CPU

    正如我们在前面的章节中所讨论的,HFT 系统中服务器的目的是处理基准交易功能:接收市场数据、执行算法模型以及向交易所发送订单。该系统有一个网络接口,用于向企业发送数据和从企业接收数据,或与公司内部的其他交易系统进行通信。第 5 章,动态网络,重点关注这一方面。一旦数据包离开线路,中央处理器 (CPU) 就会执行最繁重的工作。数据包将从网络接口到达主机内存;然后,CPU 会将数据包的片段拉入缓存,以便 CPU 执行核心可以对数据包的内容进行解码和操作。
    要实现低延迟,您需要考虑您的软件如何在 CPU 中执行,以及数据如何从各种硬件组件流出以供您的交易系统和算法处理。在以下部分中,我们将了解 CPU 的工作原理以及影响软件性能的一些 CPU 微架构细节。
CPU,从多处理器到多核
    CPU 是一个或多个处理器内核的集合,它们获取并执行程序指令。这些指令可以作用于存储在内存中的数据或与连接设备的接口。这些设备通常称为输入/输出 (I/O) 设备,通过一些扩展总线连接到 CPU,例如 PCI Express (PCIe)。过去,你需要在一台计算机上有多个物理芯片来实现多处理。在过去的十年中,为了应对摩尔定律强加的缩放限制,大多数出货的 CPU 在单个硅芯片上都有多个内核。随着硅特征(例如晶体管)变得越来越小,制造过程中的良率(全功能芯片的数量)成为一个问题,因此在单个封装中出现了多芯片(有时称为小芯片)的趋势。
    CPU核心非常擅长执行许多小的逻辑操作。例如,CPU 可以执行基本的算术运算(加、减、乘和除)和逻辑运算(AND、OR、NOT、XOR 和位移)。CRC32、高级加密标准 (AES) 算法的步骤和无进位乘法(例如 PCLMUQDQ)等更专业的运算也由某些 CPU 内核直接实现。CPU 还可以处理从内存加载或从输入设备读取的信息。CPU 还可以根据它在别处计算或读取的信息来改变它的执行路径。这些控制流指令是高级语言构造的构建块,例如条件语句或循环。
    当市场数据到达网络接口时,CPU 会对其进行处理。这意味着解析通过网络发送的数据,跨交易系统的不同功能部分管理该市场数据,并可能将由该市场数据触发的订单发送到交易所。在第 2 章交易系统的关键组件中,我们描述了基本元素。我们讨论了网关、订单簿和交易策略都是协同工作以触发订单的组件。对于单个 CPU 执行核心,这些操作中的每一个都必须按顺序发生,这意味着一次只能处理一个数据包。这意味着数据包可以排队等待前一个数据包完成处理;这会增加消息在交易系统可以将此新数据提供给交易策略之前等待的时间。为了减少延迟,我们希望许多处理单元并行工作,尽快移交已处理的市场数据,以继续处理已到达的后续消息。在 20 世纪 90 年代,多路服务器开始流行,在同一块主板上配备两个或更多 CPU。由于摩尔定律的限制,单 CPU 内核无法扩展性能,因此 CPU 供应商开始在单个芯片上添加多个处理内核。现代服务器可以有多个 CPU 插槽,每个插槽都有多个 CPU 内核,从而在一台机器上实现相当大的并行度。
    图 4.2 描绘了一个现代的多路系统架构。内存或 I/O 设备直接连接到特定的 CPU 插槽。这些被称为本地 CPU 。其他 CPU 可以使用互连连接到单个系统中,例如 Intel 的 Ultra Path Interconnect 或 AMD 的 Infinity Fabric。假设一个 CPU 试图访问内存或连接到另一个 CPU 的 I/O 设备。在这种情况下,这被称为访问远程资源。当我们将一个 CPU 访问其本地资源所需的时间与远程 CPU 通过互连访问其本地资源所花费的时间进行比较时,我们发现互连比仅访问本地内存要慢得多。我们称此访问时间为非统一,并将这些架构称为非统一内存访问 (NUMA)。术语   cache-coherent NUMAccNUMA 指的是即使另一个 CPU 内核修改了数据,CPU 内核也能保证具有正确的内存视图。NUMA 架构可以扩展到大量内核。可以将每个 CPU 视为一个单独的计算机系统,所有这些都通过结构相互连接。



图 4.2 – 四路 NUMA 架构。请注意 CPU 如何在此配置中形成完全连接的图形

    图 4.2 还代表了更多的组件。PCIe 是连接其他设备的总线,例如网络接口卡 (NIC)。当 NUMA 架构中存在多个 CPU 时,其他 CPU 可以通过互连总线请求数据来共享数据。
关于超线程和同步多线程的说明
    同时多线程,在 Intel CPU 上称为超线程,是 CPU 跟踪多个并行执行状态(在超线程的情况下是两个这样的状态)的技巧。当一个执行状态需要等待高延迟事件(例如从更高级别的缓存或 RAM 中获取数据)时,CPU 会切换到另一个执行状态,同时等待获取完成;这是一种自动线程,由 CPU 本身管理,使每个物理内核显示为多个虚拟内核。
    使用超线程将物理内核的数量增加一倍是一种诱惑,但这会引入难以控制的延迟,就像上下文切换一样。
    图 4.3 描述了在一个超线程内核中使用超线程。我们可以观察到,如果一个任务在同时运行另一个任务时需要等待访问内存段,那么硬件可以伪造并发执行。如果系统调用(或中断)要求访问内核(Kernel),则所有任务都将暂停。



图 4.3 – 超线程

    超线程的主要问题是它取消了任务切换的控制(在软件级别),这会产生更高的抖动和更高的延迟。
主存储器或 RAM
    主存储器通常称为随机存取存储器 (RAM),是用于程序指令和数据的大型非持久性存储器。RAM 是从 I/O 设备(如网卡或存储设备)读取任何数据的第一站。现代 RAM 可以以高吞吐量突然返回数据,但是当请求某个地址的数据并且数据可用时会以延迟为代价。
    在典型的 NUMA 架构中,每个 CPU 都有一些本地 RAM。许多配置将等量的 RAM 连接到每个 NUMA 节点,但这不是硬性要求。访问 RAM 的延迟可能非常高,尤其是在远程 NUMA 节点上。因此,我们需要其他方法来隐藏这种延迟或缓冲数据,靠近执行某些代码的 CPU。这就是缓存发挥作用的地方。
缓存
    具有许多内核的现代处理器具有每个内核的本地缓存和由单个插槽上的所有内核共享的缓存。这些缓存旨在利用程序通常在特定时间窗口内对同一内存区域中的数据进行操作这一事实。数据访问的这种空间和时间局部性为 CPU 提供了隐藏访问 RAM 的延迟的机会。
    图 4.4 显示了现代多核 CPU 的典型缓存层次结构。 L1缓存分为两部分:数据缓存和指令缓存。L2 和 L3 缓存将自由混合指令和数据,主存储器也是如此。



图4.4——缓存系统

    我们现在将讨论缓存系统的结构。
缓存结构
    不是一次从主存储器读取单个字或字节,每个缓存条目通常存储特定数量的字,称为缓存行。这一整行被同时读取和缓存。读入缓存行时,需要逐出另一行以为新缓存行腾出空间。逐出哪条线路通常是根据LRU来确定的,但也存在其他方案。不同级别的缓存具有不同的缓存行大小——这是 CPU 设计本身的属性。有关如何将数据结构与缓存行大小对齐以增加缓存命中几率的各种细节,主要是在访问许多相关数据结构时。
L1 cache
     L1 高速缓存(1 级)是计算机系统中最快的可用内存,它靠近 CPU 的执行单元。L1 缓存具有 CPU 最近访问并加载到寄存器中的数据。CPU 供应商决定 L1 缓存大小。
     L1高速缓存被分为数据缓存和指令缓存。指令缓存存储有关 CPU 必须完成的操作的信息,而数据缓存存储将执行处理的数据。
L2 cache
     L2 缓存(2 级)比 L1 缓存慢但更大。现代 L2 内存缓存以兆字节 (MB) 为单位,而 L1 缓存以千字节 (KB) 为单位。L2 存储的大小因 CPU 而异。但是,它通常介于 256KB 和 8 MB 之间。当前大多数 CPU 的 L2 缓存都大于 256 KB,这在现在被认为很小。当今最强大的 CPU 具有超过 8 MB 的 L2 内存缓存。L2 缓存在性能方面落后于 L1 缓存,但它仍然比系统 RAM 快得多。L1 缓存一般比 RAM 快 100 倍,而 L2 缓存大约快 25 倍。
L3 cache
    L3 缓存最大,但也是最慢的。L3 缓存包含在现代 CPU 中。L3 缓存更类似于整个芯片可能使用的全局内存池,而 L1 和 L2 缓存专用于芯片上的每个内核。L3 缓存就是我们所说的受害者缓存:从内核本地的 L1 和 L2 缓存中逐出的任何缓存行都将在发送到主内存之前传送到 L3。它通常是完全关联的缓存,位于 CPU 缓存的重新填充路径中,用于存储从该级别缓存中逐出的所有块。所有内核共享现代 CPU 上的 L3 缓存。
共享内存
    今天的大多数计算机系统,尤其是那些有多个插槽的系统,都会产生一种用一个主内存池单一设计的错觉。我们将这些称为共享内存系统,其中在任何 CPU 上运行的程序都可以访问连接到另一个 CPU 的任何内存,就好像它是运行代码的 CPU 的本地内存一样。
    今天,有两种类型的共享内存模型:统一内存访问 (UMA)非统一内存访问 (NUMA)。UMA 使用单一内存控制器,所有 CPU 通过这个单一内存控制器与系统内存进行通信。在大多数情况下,内存控制器是所有 CPU 直接连接的独立芯片。在 NUMA 架构中,有内存控制器,内存物理连接到特定的插槽。NUMA 架构相对于 UMA 的主要优势是 NUMA 系统可以更快地扩展到更多数量的 CPUs,因为互连 NUMA 节点比将多个 CPU 连接到单个系统内存池要简单。
    在 UMA 的情况下,随着更多微处理器的添加,共享总线变得拥塞并成为性能瓶颈。这严重限制了 UMA 系统扩展可用 CPU 数量的能力,并且增加了每个 CPU 核心必须等待主内存请求得到服务的时间。
    当今市场上的所有现代多路服务器都是 NUMA 架构。每个 CPU 插槽都有其物理连接的内存池。由于每个 CPU 都存在多层缓存,因此 CPU 可能会缓存包含在另一个 CPU 内存中的旧版本数据(或者甚至另一个远程 CPU 将修改该 CPU 的本地内存)。为了解决这些情况,我们需要缓存一致性协议。这些协议使 CPU 能够确定它是否唯一拥有、共享或具有特定内存区域的本地修改版本,并在其他 CPU 尝试访问确切的内存位置时与它们共享信息。理想情况下,编写的应用程序很少需要使用这些协议,尤其是在延迟和吞吐量很重要的情况下,因为同步此所有权的成本很高。
    SMP 和 NUMA 系统通常用于 HFT 系统,其中处理可以分布在在单个内存位置工作的多个处理器之间。在设计数据结构和系统以在交易系统组件之间传递消息时,必须考虑这一点。
I/O设备
    有许多不同类型的 I/O 设备连接到计算机,例如硬盘驱动器、打印机、键盘、鼠标、网卡等等。在 HFT 中我们应该考虑的主要设备是第 5 章“运动中的网络”中描述的网卡。大多数I/O设备通过PCIe (Peripheral Component Interconnect Express)连接到CPU。PCIe 设备与 NUMA 基础设施中的特定 CPU 直接相关。在构建交易系统时,您需要考虑您的网络代码(例如市场数据网关)将哪个 CPU 保持在网络设备连接的 CPU 本地,以最大限度地减少延迟。
    我们总是试图限制使用的设备是硬盘。访问硬盘上的数据成本非常高,因此很少在 HFT 系统中使用。然而,当我们回测交易策略时,信息存储在磁盘上。我们需要以特定方式存储数据以确保快速访问。我们不会在本书中讨论这部分,因为它不是特定于 HFT 系统的。
针对高频交易如何使用操作系统

     任何高频交易软件都在OS之上运行。操作系统是硬件之上的抽象,隐藏了如何启动可执行文件、管理内存和访问设备的细节。用于减少延迟的技术之一是在适当的地方打破这种抽象并直接与硬件交互。这些应用程序是用户(程序员)和硬件之间的接口。
    该操作系统有几个主要功能,包括:

  • 抽象对硬件资源的访问
  • 进程调度
  • 内存管理
  • 一种存储和访问数据的方法
  • 一种和其他计算机系统交流的方法
  • 中断管理
    对于 HFT 系统,主要的关键功能是进程调度。我们将在后面的章节中详细描述调度任务的过程。
用户空间和内核空间
    操作系统的核心是它的内核。内核是位于应用程序和硬件之间的具有高度特权的代码块。内核通常提供许多服务,从管理网络和通信的协议栈到以设备驱动程序的形式在硬件设备之上提供抽象。内核具有很高的特权,可以控制系统的工作方式,包括从任意物理内存地址读取和写入、创建和销毁进程,甚至可以在系统上运行的应用程序使用数据之前更改数据。内核必须小心保护,只有受信任的代码才能在内核上下文中运行,称为内核空间。
    用户空间是应用程序运行的地方。用户空间进程是具有多个线程的独立虚拟内存空间。用户空间进程的特权往往要低得多,需要内核的特殊支持才能访问设备、分配物理内存或更改机器状态。交易系统在用户空间中运行,但构建低延迟交易系统的挑战之一是尽量减少硬件和交易系统之间的抽象数量。毕竟,在不同格式之间转换数据、将上下文切换到内核或其他进程以传递消息或处理不必要的硬件状态更改所需执行的代码越多,运行关键交易系统代码所浪费的时间就越多。
    一个重要的概念是地址空间的分离。正如我们将看到的,这部分与操作系统如何分配内存和 CPU 理解内存有关,但这也是一项安全性和稳定性功能。未经明确许可,一个进程不应影响内核或另一进程。如果没有共享内存或类似的通信技术,用户空间中的进程几乎无法直接相互交互。这同样适用于内核,因为进程可以直接与内核交互的方式很少。内核旨在保护对其敏感资源和数据结构的访问。
进程调度和CPU资源管理
    任何软件都首先被编译并位于持久的长期存储(一些固态驱动器或硬盘)上。当我们想要启动交易系统(或任何软件)时,我们调用存储在磁盘上的一个或多个可执行文件。这导致操作系统创建一个或多个进程。
    OS会将软件加载到主存中,创建一个虚拟内存空间,并调用一个线程来执行刚刚加载的代码。运行的软件、虚拟内存空间和一个或多个线程的这种组合称为进程。一旦加载,操作系统最终将调度进程的主线程。调度程序负责确定与进程关联的线程将在何处以及何时执行。调度程序可以跨多个执行核心管理线程的执行,这些线程可以跨多个物理 CPU 插槽并行调度。调度器是在众多 CPU 内核之上的抽象,就像在上一节中描述的现代计算机系统中一样。
    当我们的进程多于可用的执行核心时,调度程序可以限制线程在介入与另一个等待线程交换之前执行多长时间。这称为多任务处理。将正在运行的进程从一个更改为另一个的动作称为上下文切换
    上下文切换是一个高昂的操作。OS保存被切换进程的执行环境,恢复被重启进程的环境。如前所述,交易系统利用多个内核来实现实时并行。可用的物理执行核心越多,并行运行的线程就越多,通常将一个线程映射到一个执行核心。
    现代操作系统中使用两种传统的进程调度方法:

  • 抢占式多任务:Linux 和大多数操作系统都采用抢占式多任务处理方法。抢占式多任务旨在保证一个进程不能独占系统。每个进程都有特定的运行时间。这段时间称为时间片。调度程序将在该时间片到期后停止进程运行。除了防止进程消耗太多时间之外,这种方法还允许调度程序做出全局处理决策。许多抢占式多任务调度程序试图了解 NUMA 拓扑并在其资源附近执行线程,但这通常很难实现。
  • 协作式多任务处理:这主要是因为它将允许进程运行到进程自愿决定停止运行为止。我们将进程自愿选择停止运行的行为称为屈服(yielding)。这种方法对于实时操作系统是典型的,因为工程师不希望延迟敏感代码被调度程序或其他正在运行的任务中断。您可以想象,这在用于某些关键安全过程的实时控制系统中将是灾难性的,或者如果您延迟订单到达市场,直到其他人获得该流动性很久之后。诸如 Linux 之类的操作系统具有一种可用的协作式多任务处理形式,如果谨慎使用,它对于对延迟敏感的代码很有用。通常,这是为了支持使用 Linux 的实时应用程序。
    几乎所有的任务调度器实现都提供了多种机制来调整调度器的行为。这可以包括基于每个进程的指导,例如优先级、NUMA 和执行单元关联、内存使用提示、I/O 优先级规则等。Linux 允许将多个调度规则应用于正在运行的进程,从而使某些任务组可以使用实时调度规则。其中许多设置在设计低延迟系统时很有用,但需要谨慎使用;不正确的优先级排序可能会导致优先级倒置或其他死锁情况。
    调度程序将始终对其默认配置中的所有资源和进程保持相同的公平性。这提供了在预定限制时间内从一组请求中授予每个请求的保证,即使调度请求原语是不公平的或随机的。在第 6 章 HFT 优化——体系结构和操作系统中,我们将解释如何通过限制上下文切换的次数来使此进程调度专门用于 HFT 系统。
内存管理
    软件需要在内存中提供其指令和数据才能执行。操作系统指示 CPU 哪个内存属于哪个进程。
    操作系统必须跟踪分配了哪些内存区域,将内存映射到每个进程,并指定分配给给定进程的内存量。内存管理单元访问的地址空间称为物理地址空间。这是您计算机上可用的物理内存。CPU 会将此空间的一部分分配给正在执行的进程。这些细分的空间被称为虚拟地址空间。内存管理单元的工作是实时将该空间从物理空间映射到逻辑空间,以便 CPU 可以快速找出虚拟地址对应的物理地址。
分页内存和页表
    现代操作系统不知道进程正在访问或存储的对象或数据。相反,操作系统专注于基本的系统级内存单元。操作系统管理的最基本的内存组是一个页面。页面是物理内存中大小均匀且精确对齐的区域,其大小通常由 CPU 在体系结构上确定。可以使用 CPU 中内置的称为内存管理单元 (MMU) 的硬件将页面映射到特定的虚拟地址。通过将不同的物理页面重新映射到连续的虚拟范围,应用程序开发人员不必考虑硬件如何管理内存或页面在物理内存中的位置。操作系统执行的每个进程都有其页面映射,称为页表。
    图 4.5 表示使用页面的进程。任何物理页面都可以存在于多组页面映射中。这意味着可能运行在不同 CPU 内核上的各种线程可以访问其地址空间内的同一内存页。



图 4.5 – 页面和进程

    物理地址和虚拟地址的来回转换由 CPU 中的硬件自动完成。因此,如果我们正在翻译的信息位于靠近 CPU 的快速位置,翻译的性能将会提高。实际上,用于存储此信息的位置页表通常位于 CPU 中的专用寄存器中,但这只有在页表很小的情况下才有可能。CPU 中一个称为转换后备缓冲区 (TLB) 的专用高速缓存用于任何实际的页表。由于页表是内存中的数据结构,如果进程的地址空间太大而无法放入 TLB,大多数 CPU 都有硬件将相关页表从其他 CPU 的缓存甚至主内存中拉入 TLB 。
    分页会损害进程的性能。当 TLB 中存在缓存未命中时,操作系统必须从内存中的其他位置加载数据。在 HFT 系统中,我们有时会通过增加页面大小来最小化 TLB 缓存未命中的影响。大于 4 KB 标准基页大小的虚拟内存页面称为大页面。对于大数据集上的频繁访问模式,大页面可以提高内存速度。大页面是有代价的——跟踪大页面的 TLB 有时比管理标准页面的 TLB 小几个数量级,这意味着如果映射了许多大页面,则可能需要更频繁地访问内存。因此,必须谨慎使用大页面。
系统调用
    系统调用意味着用户空间应用程序向操作系统内核请求服务。系统调用是应用程序与操作系统通信的一种方式。系统调用是软件向操作系统内核发出的执行某些敏感操作(例如操纵硬件状态)的请求。请求现代操作系统上的一些关键系统调用来处理进程创建和终止、管理磁盘上的文件、管理 I/O 设备以及与外界通信。
    当请求系统调用时,如果请求被允许,内核将执行该操作。对于许多系统调用,如果调用成功完成,应用程序会收到来自内核的一些响应。系统调用完成后,如果时间片中还有时间,或者没有更高优先级的任务等待 CPU 时间,调度程序可以安排请求任务恢复。内核将结果提供给应用程序,然后在该过程完成后将数据从内核空间传输到内存中的用户空间。
    一些特定的系统调用,例如获取系统日期和时间,可能需要几纳秒才能完成。更扩展的系统调用,例如连接到网络设备或与磁盘上的文件交互,可能需要几秒钟。大多数操作系统为每个系统调用启动一个单独的内核线程,以最大限度地减少瓶颈。多线程操作系统可以同时处理多个系统调用。HFT 系统将大量使用这种并发执行的概念,例如使用线程。
    现代版本的 Linux 提供虚拟动态共享对象 (vDSO),将一些特殊的内核空间函数导出到用户空间,尤其是那些与检索当前系统时间相关的函数。vDSO 的强大之处在于,这些函数在内核的控制下,因此了解硬件细节,直接在用户空间进程中执行。不像 open 和 read 系统调用需要进入内核的整个过程(因此需要完整的上下文切换),诸如 clock_gettime 的函数(至少在 CLOCK_MONOTONIC 的情况下)具有非常低的调用开销,因为调用是在 vDSO 中。
线程
    任何进程中最基本的分工是线程。通过跨多个线程进行工作,可以实现并行性。单个进程内的所有线程共享一个公共虚拟内存空间。每个进程,一个或多个线程的分组,都有自己独特的内存空间。交易系统的主要活动是在不同功能(可能是进程)之间共享数据,以决定发送订单。在优化并发功能之间的通信时,将考虑线程或进程的使用。这也会影响您构建在线程和进程之间传递数据的方式。线程之间传递的数据可以利用内存分配中的并发性,允许您通过简单地向另一个线程提供指向数据结构中的消息的指针来传递数据。在进程之间传递数据要么需要一个由两个进程映射的共享内存池,要么将消息序列化到某个队列中,如第 6 章 HFT 优化 - 体系结构和操作系统中所述。
    除了能够共享内存之外,线程的响应时间比进程快。如果一个进程被分成许多线程,一个线程的输出可能会在它完成执行时立即返回。它们的上下文切换时间也比进程短。
    因为任何 HFT 系统都需要系统调用,所以必须抵消成本。我们将在第 6 章 HFT 优化 - 体系结构和操作系统中了解如何从线程和进程中获益。
中断管理
    中断请求是外围设备在发生某些事情时提醒 CPU 的方式。然后 CPU 将停止其中一个处理核心并将上下文切换到分配给该设备的中断处理程序。限制可以创建上下文切换的中断次数;我们还将在第 6 章 HFT 优化——体系结构和操作系统中回顾这一点。
    图 4.6 描述了在单核模型中使用中断(或系统调用)对 CPU 执行任务的时间的影响。我们可以观察到调度器会在当前运行的任务和内核中的中断上下文之间切换。内核花费更多的时间来处理中断请求,然后可用于运行用户任务的 CPU 时间就更少了。



图 4.6 —— 中断或系统调用对任务调度的影响

    图 4.7 显示了两个 CPU 内核的好处,有两个不需要共享时间的任务。这个例子表明,如果我们将任务固定到给定的核心,我们将减少上下文切换的次数并减少内核中断的影响。此示例还假设中断请求仅由一个内核提供服务。因此,只有任务 1 会中断以服务硬件。



图 4.7 —— 两个 CPU 内核的优势

    第 6 章,HFT 优化——体系结构和操作系统,详细介绍了将任务固定到给定内核的任务调度。
    在前两节中,我们了解了硬件、操作系统以及它们在 HFT 系统中的作用。我们现在将处理最后一部分:编译和库,它们对于 HFT 系统也是必不可少的。
编译器的作用

    编译器将用一种编程语言(源语言)编写的人类可读代码翻译成另一种语言,通常是一种特定于机器的语言,尽管这可以是虚拟机。他们将代码从高级语言翻译成低级语言。它们可以生成中间代码、汇编语言、目标代码或机器代码。它们还在加速软件运行时方面发挥着重要作用。通过改进开发人员希望在硬件中高效执行表达内容的抽象,编译器变得越来越聪明。添加了新的编程范式以改进软件工程。在 20 世纪 90 年代,Python 和 Java 使每个人都可以使用面向对象的编程。我们建议读者阅读 Aho、Lam、Sethi 和 Ullman 合著的《Compilers: Principles, Techniques, and Tools》一书,也称为 Dragon Book。本书将深入解释编译器是如何设计的。
    在 HFT 系统中,编译器可以帮助优化我们花费大部分时间的代码部分:循环。《Advanced Compiler Design and Implementation》,由 Steven Muchnick 撰写,描述了编译器可以进行的循环优化。我们必须记住,HFT 系统的关键部分是时空权衡(增加内存使用和缓存利用率,同时减少执行时间)。我们可以谈谈使用这种范式进行优化的几个例子:

  • 循环展开是这种权衡的一个例子。因为展开循环时迭代次数较少,所以退出检查的开销减少了。此外,分支指令更少,这可能会产生开销,具体取决于体系结构。在完全展开循环的情况下没有退出测试。展开循环可以导致编译器可以进行的进一步优化(例如,在前面的完全展开版本中,所有数组偏移量都是常量,这是编译器可能能够利用的)。
  • 函数内联可以在被调用方用这个函数本身的汇编代码代替函数调用,为汇编代码提供更多的优化机会。
  • 表格和计算。编译器可以帮助创建数据结构以避免重新计算。它们将保存已计算值的值。
    动态链接允许链接器创建一个较小的二进制文件,其中依赖库的位置将被替换为存根。动态链接器通常会在应用程序启动时通过从磁盘加载适当的共享对象来加载该库。只有在需要依赖的时候才会加载到内存中。如果多个正在运行的进程使用同一个库,则库的代码内存可以在多个进程之间共享。然而,这种效率是有代价的:库函数
通过过程链接表 (PLT) 调用时被间接引用。这种间接寻址会导致额外的开销,尤其是当库中的一个短函数被频繁调用时。典型的 HFT 系统将尽可能使用静态链接来避免这种开销。
总结

    在本章中,我们开发了一个关于计算机如何工作以及如何考虑各种组件的整体性能影响的概念模型。多个硬件和软件中的每一个都必须以适合交易系统的方式工作。这通常需要了解硬件和软件如何交互,以便规避或优化低效算法或交互的负面影响。
    然后我们将使用本章中开发的基础知识作为基础。以下章节将建立在优化 HFT 系统的操作系统、内核和应用程序的基础上。这将包括减少上下文切换的影响、安全访问共享数据结构的技术,以及其他减轻底层硬件和软件低效组件的方法。
    下一章将重点介绍网络。我们将解释 HFT 系统中网卡的作用,以及如何优化与交易所的通信以减少延迟。
第5章 动态网络

    在上一章中,我们深入讨论了硬件和操作系统。任何交易系统都必须从交易所收集数据,并根据这些数据做出决策。为此,通信对于高频训练 (HFT) 系统的性能至关重要。在本章中,我们将回顾交易系统如何深入通信、如何在高频交易系统中使用网络以及如何监控网络延迟。
    在本章中,我们将讨论以下主题:

  • 了解HFT系统的网络
  • HFT 中系统间的网络通信
  • 重要的协议概念
  • 为HFT交易所设计金融协议
  • 内部网络和外部网络
  • 了解网络包生命周期
  • 监控网络
  • 重视时间分配
    以下部分将介绍网络基础知识;我们将介绍我们稍后将优化的基础知识。
了解HFT系统的网络

    交易系统接收市场数据并对交易所接收/发送订单。分布在交易系统内不同机器上的众多进程需要相互通信——例如,在整个设计中跟踪某个投资头寸的进程将需要向所有组件发送有关给定资产头寸的信息。网络定义了设备如何相互连接。需要联网才能将数据从一台机器传输到另一台机器(通过扩展,传输到交换机)。
    网络是所有 HFT 系统的基础,需要像软件系统的设计决策一样仔细考虑。在任何系统中确保通信的设备称为网络接口卡 (NIC)。它允许运行软件的计算机与外界进行通信。当我们了解交易系统的工作原理时,我们必须检查分层模型,该模型用于描述操作系统中计算机相互通信所需的网络堆栈。
学习网络概念模型
    开放系统互连 (OSI) 模型可以说是现代网络环境中计算机如何相互通信的最常见描述。 OSI 模型是用于描述网络系统功能的概念框架。以下屏幕截图描述了 OSI 模型的完整七层以及通常在每一层实现的相关操作:



图 5.1 —— 七层OSI模型

    该模型分为七个独立的层,每个层都具有特定的功能,只与相邻层通信,不与其他所有层通信。此处更详细地描述了这些层:

  • 会话层,表现层和应用层:这三层可以重新组合(以简化),因为这些是我们将在软件级别使用的层。在 HFT 中,我们关注以下四个层,因为它们提供了高级优化机会。
  • 传输层:这管理交付并包含数据包中的错误。系统间数据的排序、数据包大小和传输是网络层的责任。在金融领域,我们主要使用两种协议:传输控制协议(TCP)用户数据报协议(UDP)
  • 网络层:这从数据链路层接收帧并使用逻辑地址将它们传送到预期目的地。我们将使用称为 Internet 协议 (IP) 的寻址协议。与 IP 版本 6 (IPv6) 不同,IP 版本 4 (IPv4) 是一种轻型且用户友好的协议,是金融领域使用最广泛的协议。
  • 数据链路层:该层通过使用奇偶校验循环冗余校验 (CRC) 等技术检测错误来纠正可能在物理层发生的错误。
  • 物理层:这是两台机器用来通信的媒体,包括光纤、铜缆和卫星。所有这些媒体都有不同的特性(延迟、带宽和衰减)。根据我们想要构建的应用程序类型,我们将利用一个与另一个。该物理层被认为是 OSI 模型的最低层。它涉及通过网络以电或光方式从发送方的物理层向接收方的物理层传送原始非结构化数据位。网络集线器、电缆、中继器、网络适配器和调制解调器是在物理层找到的物理资源的示例。
    从图 5.2 中层的分组方式可以看出,我们经常同时引用其中的几个层。例如,我们可以将第 5-7 层称为软件层,将第 1-3 层称为硬件层,将第 4 层混合在两者之间。这很常见,以至于经常使用整合软件、传输和硬件层的简化模型,如下所示:



图 5.2 —— 简化OSI模型

    现在我们已经讨论了数据包在两台通信计算机上通过网络堆栈时必须采用的高级分层路径,我们将讨论如何为 HFT 设计网络。
HFT 中系统间的网络通信

    当设计人员为 HFT 系统构建网络时,他们关注的是不同的通信模式。由于微秒很重要,因此他们必须考虑使用微波网络或 Cisco 交换机相对于另一台交换机的优势。
    网络创新有可能使交易发生巨大变化。
    下图表示网络的抽象模型。当两个设备进行通信时,它们需要一种介质来传输数据。它们通过连接到网络设备(例如交换机)的物理连接进行通信。交换机负责将数据包从网络的一部分移动到另一部分,我们可以在其中找到发送方发送数据的接收方:



图 5.3 —— 网络的抽象模型

    每个网络组件对于网络延迟都是必不可少的。这些都是延迟的来源:

  • NIC 将信号从计算机转换到网络,反之亦然。 NIC 处理数据的时间可以忽略不计,但不为零。 NIC 被选择用于低延迟数据路径和其他功能,例如:

  • 总线:总线将数据从计算机的一个组件传输到另一个组件。我们可以找到三种主要类型的总线:外围组件互连 (PCI)PCI  eXtended (PCI-X) PCI Express (PCIe)。他们都有不同的速度。 2017-2018 年,业界开始使用 PCIe 5.0,工作速率为每秒 63 GB (GB/s)。尽管 PCIe 6 于 2019 年发布,但 PCIe 5.0 是网卡最快的总线。
  • 端口数:NIC 卡可以有不同数量的端口:1、2、4 或 6。它可以让一台机器同时访问多个网络。但是,也可以在同一台机器上安装多个 NIC。
  • 端口类型:NIC 可以有不同类型的连接。 Registered Jack-45 (RJ-45) 端口是一种类型的端口。它使用名为 5 类 (Cat5) 6 类 (Cat6) 的双绞线电缆。我们可以拥有的另一种常见电缆类型是同轴电缆,它连接到 Bayonet Neill-Concelman (BNC) 端口。最后一种是与光纤电缆配合使用的光学端口。
  • 网络速度:标准支持的网络速度是单通道每秒 100 吉比特 (Gbps)、25 Gbps 和 10 Gbps 信令。任何其他(即 400 Gbps、50 Gbps、40 Gbps 等)都包含多个并行通道。数据中心和金融应用每天都在使用 10 Gbps 和 25 Gbps 的以太网。
  • 专用集成电路 (ASIC):集成了通过 PCIe 和网络本身与主机 PC 接口的功能。


  • 集线器:集线器是一种具有将局域网 (LAN) 网络连接在一起的多个端口的设备。当数据包通过端口进入系统时,它会在整个 LAN 中被复制,从而允许所有接收者看到所有数据包。集线器充当网络中所有设备的中央连接点。这项技术几乎已经过时。Metamako/Exablaze 重新启用了这项技术,它是 HFT 应用程序的一种节省延迟的方法。
  • 交换机:交换机工作在数据链路层(第2层),有时也工作在网络层(第3层);因此,它可以支持任何数据包协议。它的主要作用是在局域网中过滤和转发数据包。
  • 路由器:路由器至少加入两个网络,并促进数据包从一个网络上的主机传递到另一个网络上的主机。在高频交易系统中,路由器位于交易系统的入口处(第 2 章交易系统的关键组件中的Gateways)。路由器找到将数据包从一台主机转发到另一台主机的最佳方式。
    主要组件(例如路由器、NIC 和交换机)将在 HFT 系统中引入延迟。
了解交换机的工作原理
    交换机是 HFT 网络内通信的主要支持者。观察下图:



图 5.4 —— 交换机的抽象模型

    图 5.4 表示交换机的抽象模型。入口和出口是行业中用来表示任何网络设备的输入和输出 (I/O) 的词。交换机工作在网络二层。它的主要功能是通过应用转发规则将数据包从其输入传输到其输出,您可以在上图中将其视为入口接口出口接口。交换机处理两种操作,如下所述:

  • 配置数据包转发:对于一个简单的交换机,该模型只是观察端口上的媒体访问控制 (MAC) 地址并将流量交换到该端口。更复杂的交换机(即支持第 3/4 层的交换机)将允许对其他匹配模式(即 IP 地址或端口)进行操作。
  • 转发/过滤决策:交换机读取配置表以相应地转发数据包并在必要时删除数据包。
    交换机在启动时设置一次,然后在需要新转发条目时即时生成表,例如在更新路由表时。
    解析器首先处理新的数据包(数据包主体独立缓存,不可用于匹配)。解析器定义交换机的协议,从报头中识别和提取信息。
    之后,将提取的标头字段发送到匹配操作表(组件匹配标头字段以执行操作)。入口和出口在匹配操作表中是分开的。入口匹配操作决定出口端口和数据包路由到的队列,而两者都可能改变数据包标头。数据包可能
由基于入口处理的控制流转发、复制、丢弃或触发。出口匹配操作在每个实例的基础上修改数据包标头(例如,对于多播副本)。要跟踪帧到帧的状态,可以将操作表(计数器、监管器等)链接到流。
    元数据,类似于包头字段,可以由阶段之间的包携带。所有元数据实例都是入口端口、传输目的地和队列,数据从一个表移动到另一个表,而不修改数据包的解析表示。
    除了网络结构之外,网络指标的关键部分是速度。我们将在下一节中定义一些速度指标。
带宽、吞吐量和数据包速率/大小
带宽是两台主机之间交换的数据包的理论数量。通信到达预定目的地的速度称为吞吐量。两者之间的主要区别在于吞吐量衡量的是实际数据包交付,而不是理论数据包交付。您可以通过查看平均数据吞吐量来了解有多少数据包到达了目的地。数据包必须有效地到达目的地才能提供高性能服务。不丢失任何数据包非常重要。例如,如果我们想通过增量更新来构建订单簿,丢失数据包意味着订单簿不连贯。
    在评估和测量网络性能时,数据包大小和数据包速率是需要考虑的两个重要标准。网络性能因这些参数的设置而异。吞吐量值与数据包大小成比例上升,然后下降直到达到饱和值。增加数据包大小会增加发送的数据量,从而提高吞吐量。
    以下屏幕截图说明了网络吞吐量(以千比特/秒或 Kbps 为单位)与数据包速率(以字节为单位的每秒数据包数):



图 5.5 —— 不同数据包大小的吞吐量与数据包速率

    图 5.5 中显示的两行中的每一行对应于不同的数据包大小(512 字节和 1,024 字节)。当数据包速率增加时,网络吞吐量会提高,因为提高数据包速率意味着增加数据量,从而提高吞吐量。此外,该图表显示,随着数据包数量的增加,吞吐量会下降,直到接近饱和点。大数据包的吞吐量增长比小数据包快,1024字节数据包的吞吐量峰值在50个数据包时达到。
    当达到接口的最大吞吐量时,多个入口接口尝试将出站数据包提交到同一出口接口可能会导致缓冲。
交换机排队
交换机的主要功能是将数据包路由到正确的接收者。当传入数据过多时,处理数据的时间可能比该数据到达交换机的时间更长。为了不丢失任何数据,必须有一个缓冲区。该缓冲区将存储等待处理的数据。交换机的主要作用是在输入端口上接收数据包。它查找目的地以获得输出端口,然后将数据包放入输出端口队列。流向输出端口的大数据流会使输出端口队列饱和。如果队列中有太多数据,这将导致显着的延迟。如果缓冲区已满(数据包丢失),数据可能会丢失。如果市场数据包丢失,则无法建立订单簿,从而中断交易。下图描述了交换机的队列:



图 5.6 —— 交换机排队

    重要问题之一是队首 (HOL) 阻塞。当许多数据包被即将离开队列的数据包阻止在队列中时,会出现此问题,这会增加延迟或数据包的重新排序。事实上,如果许多数据包在一个队列中被阻塞,交换机将继续处理其他数据包到另一个输出;这将导致接收到的数据包不按顺序。
    我们看到了排队如何影响数据包传输;现在,我们将讨论两种主要的交换模式。
交换模式——存储转发与直通
    在处理数据包并将数据包转发到正确的出口端口之前,交换机必须根据交换机制接收和检查各种字节。有两种交换模式,详见此处:

  • 直通交换模式有两种形式,如下:

  • 无碎片交换
  • 快速转发交换


  • 存储转发交换
    两种交换类型都根据以太网帧的目标 MAC 地址做出转发决策。他们解析以太网报头中源MAC地址的位;他们记录 MAC 地址并创建 MAC 表。在帧可以从出口端口传输之前,交换机必须接收和审查的帧数据量因交换机类型而异,如以下屏幕截图所示:



图 5.7 —— 基于接收到的帧字节的交换模式

    图 5.7 显示了三种模式并表示应接收多少信息。在这里,我们将详细了解它们,如下:

  • 存储转发模式:
    在转发帧之前,交换机必须完全接收到该帧。转发此帧的决定基于目标 MAC 地址查找。为确认数据的完整性和准确性,交换机使用帧的帧校验序列 (FCS) 字段。如果 CRC 值不匹配,则该帧无效并被丢弃。在传输帧之前,将检查目标和源 MAC 地址以查看它们是否匹配。
    默认情况下,接受 64 字节到 1,518 字节之间的任何帧大小,其他大小将被丢弃,导致比其他三种方法更高的延迟。

  • 直通交换模式:
这种模式允许以太网交换机在收到帧的前面些字节时做出转发选择。这种模式有两种类型,如下所述:

  • 无碎片交换:此模式要求交换机在转发前解析帧的前 64 个字节。
  • 快速转发交换:一次直通交换在收到帧的目标 MAC 地址时转发帧,这意味着只需要前 6 个字节。
    我们看到了两种主要的交换模式;我们现在将描述交换机可以执行数据包转发的不同层。
第1层交换
    物理层交换机,也称为第 1 层交换机,是 OSI 模型物理层的一部分。第 1 层交换机可以是电子可编程接线板。它无非就是在端口之间建立物理连接。该链接由软件指令建立,允许自动或远程配置测试拓扑。第 1 层交换机不读取、更改或使用数据包/帧标头来路由数据。这些交换机对数据完全不可见,并且延迟非常低。在测试设置中,端口之间的透明连接至关重要,因为它们可以让测试像连接设备的跳线一样准确。 Arista/Cisco 是第 1 层交换机的一个示例。
第 2 层交换(或多端口网桥)
    第 2 层交换机具有两个功能,如下所述:

  • 在第 1 层(物理层)传输数据
  • 检查接收和发送的任何帧的错误
    这种类型的交换机需要 MAC 地址才能将帧转发给正确的接收者。所有接收到的 MAC 地址都将保存在一个转发表中。该表允许交换机以非常有效的方式转发数据。与可以基于 IP 地址传输数据包的更高级别的交换机(高于 3)不同,第 2 层交换机不能使用 IP 地址并且没有优先级机制。
第3层交换
第 3 层交换机是一种设备,其作用如下:

  • 基于源地址和目标地址分析和路由数据包的具有智能 IP 路由的路由器
  • 同一子网上的交换机链接设备
    我们现在将讨论能够使用公共地址从许多私有 IP 地址路由数据的系统。
网络地址转换
将私有 IP 地址转换为公共地址的过程称为网络地址转换 (NAT)。大多数路由器使用 NAT 来允许许多设备共享一个 IP 地址。当机器与交换机通信时,它会寻找到交换机的方向。此请求作为数据包从机器发送到路由器,然后转发给企业。路由器必须首先将源 IP 地址从私有本地地址转换为公共地址。如果数据包包含私有地址,接收服务器将不知道将信息发送回何处。由于 NAT,信息将使用路由器的公共地址而不是笔记本电脑的私有地址返回到笔记本电脑。
    对于使用它的任何设备,NAT 都是一项资源密集型操作。这是因为 NAT 需要读写每个 IP 数据包的头和负载信息来完成地址转换,这是一个耗时的过程。它会增加中央处理器 (CPU) 和内存的消耗,这可能会降低吞吐量并增加数据包延迟。因此,在实际网络中安装 NAT 时,了解 NAT 对网络设备(特别是路由器)的性能影响变得至关重要,尤其是对于 HFT。大多数现代交换机至少可以在 ASIC 中执行静态 NAT,但越来越多的交换机也可以执行动态 NAT,但性能会有所下降。
    我们详细研究了如何传输数据包。我们现在将描述设置数据包转发规则的协议。
重要的协议概念

    当两个设备需要通信时,一旦它们有办法将信号从发送方传输到接收方,我们就需要有协议来设置通信规则。协议就像一种语言,两个组件同意在系统中使用以进行通信;它设定了通信规则。下图表示交易所和交易系统的网络基础设施:



图 5.8 —— 交易机构和交易服务器的交易网络基础设施

    在第 2 章“交易系统的关键组件”和第 3 章“了解交易机构动态”中,我们看到交易机构、市场数据馈送处理程序和市场参与者是传统交易系统的三个主要组件。
    通过网关服务器,匹配接收来自市场参与者的订单。馈送处理商从证券交易所获取数据,并以最短的延迟将其交付给感兴趣的市场参与者。为了传输市场数据,我们使用 FIX Adapted for STreaming (FAST) 协议(稍后在 FAST 协议部分中描述)。
    我们现在将讨论高频交易的以太网协议。
使用以太网进行 HFT 通信

    以太网是连接有线 LAN 或广域网 (WAN) 中的设备最常用的协议。该协议设置设备之间的通信规则。
    以太网指定网络设备如何构建和发送数据,以便同一 LAN 或公司网络上的其他设备可以识别、接收和处理数据。该协议高度可靠(抗噪声)、快速和安全,由电气和电子工程师协会(IEEE)802.3工作组于1983年设计。该技术不断改进以获得更好的速度。
    不同的规范——802.3X 和 802.11X——定义了另一种类型的支持,例如 100BASE-T,它被称为我们今天仍在使用的快速以太网
使用IPv4作为网络层
IP 协议运行在 OSI 模型的网络层,而 TCP 和 UDP 模型运行在互联网层。因此,该协议负责根据主机的逻辑地址识别主机,并通过底层网络在它们之间路由数据。
    IP 寻址系统提供了一种唯一标识主机的技术。 IP 使用尽力传递,这意味着它不能保证数据包将被发送到预期的主机,但它会尽最大努力做到这一点。 IPv4 中的逻辑地址是 32 位。
    在使用 IPv4 协议时,我们可以使用三种不同的寻址模式,详见下文。

  • 单播模式
    只有一个指定的主机以这种方式接收数据。目标主机的 32 位 IP 地址存储在目标地址字段中。在这种情况下,客户端将数据传输到所需的服务器,如下图所示:



图 5.9 —— 单播模式

    如上图所示,机器 A机器 C 发送信息。

  • 广播模式
    在这种模式下,数据包被发送到一个网段中的所有主机。目标地址字段中包含一个特定的广播地址 255.255.255.255。当在网络上看到此数据包时,主机有义务对其进行处理。在这种情况下,客户端传输所有服务器接收到的数据包。广播很少用于 HFT 系统,因为它几乎无法控制哪些机器将接收流量,并且可能会产生不必要的开销。您可以在下图中看到广播模式的说明:



图 5.10 —— 广播模式

    如上图所示,机器 A 向所有机器发送信息。

  • 组播模式
    这种模式是前两种模式的混合,因为数据包既不会传输到单个主机,也不会传输到网段上的所有主机。此数据包中的目标地址字段具有以 224.x.x.x 开头的唯一地址,可由多个主机提供服务。主机将订阅特定的多播馈送。一台机器使用 Internet 组管理协议 (IGMP) 与它希望订阅特定馈送的上游服务进行通信。许多交换机都具有监控来自主机的 IGMP 流量和侦听订阅源的逻辑。这使交换机能够确定应将多播流量复制到哪些主机。未实施 IGMP 侦听的交换机将多播流量视为广播流量。您可以在下图中看到多播模式的说明:



图 5.11 —— 多播模式:机器 A 向机器 B 和 C 发送信息

    在本节中,我们回顾了网络层及其组件。我们现在将讨论传输层以及 UDP 和 TCP 协议。
传输层的UDP和TCP
以太网上的 TCP/IP 或 UDP 是证券交易所和其他市场参与者最常用的通信协议。市场数据馈送等非必要数据通常使用 UDP 传输,以减少延迟和开销。 IP 是 TCP 和 UDP 协议簇中最重要的协议之一。使用 TCP/IP 协议执行订单等关键数据。
    TCP 指定计算机如何连接到另一台机器以及我们如何在它们之间传输数据。该协议是可靠的,并通过网络提供端到端 (E2E) 字节流。
    面向数据报的协议 (UDP) 用于广播和多播类型的网络传输。 UDP 与 TCP 不同,因为它不确保数据包传送。
    主要区别如下所示:

  • TCP是面向连接的协议,UDP是无连接协议。
  • 因为UDP没有任何机制检测错误,所以UDP比TCP快。
  • TCP开始通信需要握手而UDP不需要。
  • TCP检测错误并且有错误修复,而UDP检测错误则是当存在问题时将包丢弃。
    UDP 没有 TCP 的会话、排序和交付保证功能。 UDP 用于延迟很重要的地方,因为数据是在数据报的基础上传递的。市场数据通常出于以下两个原因之一使用它,如下所述:

  • 面向数据报的交付可能延迟较低(但如果丢失某些内容,恢复会更加复杂)。
  • 多播本质上不支持面向连接的协议(因为通信是多对多通信类型)。
    这通常通过应用层协议中的序列号来解决,并提供带外机制来请求重新传输丢失的序列号。现在有一种趋势是使用 UDP for Orders(UFO),它可以让我们更快地发送订单。
为高频交易设计金融协议

    让我们回到第 2 章交易系统的关键组件中介绍的下图。了解交易系统和交易所之间的通信方式非常重要:



图 5.12 —— 交易所与交易系统间的通信

    两个实体必须说同一种语言才能相互交流。为此,他们使用了网络中使用的协议。该协议用于任何交易所(有时称为Venues)的交易。根据Venue的不同,可能会有多种协议。如果给定Venue和您的交易系统之间的协议相同,则可以建立连接。根据Venues的数量,一个Venue将频繁使用给定的协议,而另一个Venue将使用不同的协议。交易系统需要建立在理解其他协议的基础上。尽管他们的协议因Venue不同而不同,但他们创建连接和开始交易的过程是相似的,如下所示:

  • 他们建立一个登录,指定谁是交易发起者,谁是接收者,以及连接将如何继续存在。
  • 接下来,他们询问他们对不同公司的期望,例如通过订阅进行交易或接收价格更新。
  • 然后他们获得订单以及价格变化。
  • 然后他们发送心跳以维持连接。
  • 最后,他们说再见。
    我们现在将在下一节中介绍金融信息交换 (FIX) 协议。
FIX协议
因为它是交易中最常用的协议,金融信息交换 (FIX) 协议是我们将在本章中讨论的协议。它成立于 1992 年,旨在处理 Fidelity Investments 和 Salomon Brothers 在国际实时交易中的证券交易。包括外汇 (FX)、固定收益 (FI)、衍生品和清算。这是一个基于字符串的协议,这意味着人们可以阅读它。它与平台无关,是开放的,并且有多种风格。
    有两种不同类型的消息,如下所述:

  • 不包含任何财务信息的行政通知
  • 程序发送的消息以获取价格更改和订单
    这些消息的内容是一个键值对列表,类似于字典或地图。预定义标签作为键;每个标签都是对应于特定特征的数字。值(可能是数字值或文本值)与这些标签相关联。考虑以下场景:

  • 如果我们希望发送 1.23 美元的订单,假设价格标签上有数字 44。因此,44=1.23 将出现在订单消息中。
  • 字符 1 分隔所有对。这表明如果我们使用与前面示例中 FIX 消息定义中的数量相对应的标签 38 添加数量 100,000,我们将得到 44=1.23|38=100000。 | symbol 代表字符 1。
  • 8=FIX.X.Y 是所有消息中使用的前缀。此前缀表示 FIX 版本号。版本号由 X 和 Y 表示。
    10=nn 等于校验和。校验和是消息二进制值的总和。这有助于检测污染。
    这是一个 FIX 消息示例:
8=FIX.4.42|9=76|35=A|34=1|49=TRADER1|52=20220117-12:11:44.224|56=VENUE1|98=0|108=30|141=Y|10=134    此处列出了前面 FIX 消息中的必要字段:

  • 包含数字 8 和值 FIX.4.42 的标签。这与 FIX 版本号相同。
  • 8(BeginString),9(BodyLength)。
  • 35 (MsgType)、49 (SnderCompID) 和 56 (SnderCompID) 是高于 FIX4.42 的版本号。
  • 标签 35 指定消息类型。
  • 从标签 35 到标签 10 的字符数由 body-length 标签表示,即 9。
  • 校验和存储在字段 10 中。该值是通过将所有字节的美国信息交换标准代码 (ASCII) 表示形式的十进制值乘以 256 得出的,除了校验和字段(这是最终字段)。
    现在我们知道了 FIX 协议是什么,我们将详细了解如何在交易中使用该协议。
FIX 通信协议
为了能够进行交易,交易系统需要两个连接:一个用于接收价格更新,另一个用于下订单。 FIX 协议通过为以下每个连接使用不同的消息来遵守此标准。
    我们将首先讨论价格变化连接,然后描述订单连接。

  • 价格变化
    在构建交易系统时,首先要获取的信息是价格更新。价格更新是来自其他市场参与者的订单。交易系统将启动与交易所的连接以建立连接并订阅价格更新。我们将交易系统定义为发起者,交易所定义为接收者或接受者,如图 5.13 所示。
    交易系统需要交易者选择交易的金融工具的价格。为此,交易系统与交易所建立连接以订阅流动性更新。发起方(即交易系统)与接受方(即交易所)之间的连接如下所示:



图 5.13 —— 交易系统要求更新价格

    接受者和发起者之间发送的 FIX 消息如下图所示:



图 5.14 —— 使用 FIX 协议获取价格更新的交易系统

    当交易系统收到这些价格更新时,它会根据信号更新账簿并下订单。

  • 订单
    交易系统需要的第二个馈送是与订单方的交易所通信。交易系统(发起方)将与交易所(接收方)建立通信。一旦建立通信,发起者将向交易所发送订单。当交易所需要发送有关订单的更新时,它将使用此通道进行通信。
    通过与交易所发起交易会话,交易系统将向交易所发送订单。在此活跃交易时段开放时,订单通讯将传送至交易所。交易所将使用 FIX 消息来传输这些订单的状态。下图对此进行了描述:



图 5.15 —— 交易系统向交易所发送订单

    下面的屏幕截图描述了发起者和接受者之间发送的 FIX 消息:



图 5.16 —— 使用 FIX 协议向交易所发送订单的交易系统

    因为 FIX 协议是基于字符串的,所以解析器可能需要一些时间来处理流。 FAST 协议的开发速度比 FIX 协议更快。
FAST协议
FAST 协议是 FIX 协议的高速版本。市场数据通过在 UDP 之上运行的 FAST 协议从交易所或馈送处理程序传输到市场参与者。FAST 消息具有用于传输元数据和有效负载数据的各种字段和运算符。 FAST 被设计为使用尽可能少的带宽。因此,它使用了多种压缩技术,如下所述:

  • 第一个基本方法是增量更新,它只提供变化——例如当前股票价格和之前的价格——而不是持续传输所有股票及其相关数据。
  • 第二种方法对每个数据字使用可变长度编码来压缩原始数据。虽然这些策略可以跟上提要处理程序提供的更高数据速度,但它们显着增加了处理复杂性。
    必须对压缩的 FAST 数据流进行实时解码和分析,以将其转换为可处理的数据。如果处理系统跟不上数据流,关键信息就会丢失。此外,解压缩数据流会增加必须成功处理的带宽量。因此,必须满足两个不同的标准才能设计高性能交易加速器,如下所示:

  • 首先,各种协议的解码必须以尽可能短的延迟完成。
  • 其次,它必须以给定的数据速率维持数据处理。深入了解 FAST 协议对于检查现代交易系统的数据速率是必要的。
    UDP协议用于发送FAST消息。多个 FAST 消息打包在单个 UDP 帧中以减少 UDP 开销。 FAST 通信不提供任何大小信息或帧定义。相反,每个字母都由一个模板指定,在解码流之前必须理解该模板。大多数馈送处理商通过提供不同的模板要求来设计他们的 FAST 协议。必须小心,因为单个解码错误将丢弃整个 UDP 帧。模板定义一组字段、序列和组。这些组指定一组字段。
    FAST 属于为提高带宽和通信速度而开发的一系列协议,称为简单二进制编码 (SBE)。我们现在将讨论比基于字符串的通信协议更有效的协议。
ITCH/OUCH 协议
    ITCH 和 OUCH 被认为是二进制协议。 OUCH 通常采用 TCP,而 ITCH 是多播或 TCP。 ITCH主要是做行情数据,而OUCH是做订单的。在专利侵权诉讼影响 FAST 之后,纳斯达克于 2000 年创建了这些协议。基于 ITCH 的 交易所馈送在行业中被广泛使用。因为有许多不同于纳斯达克的交易所使用它,所以它有不同的版本。芝加哥期权交易所 (CBOE) 也是另一个大量使用 ITCH 变体(例如 CBOE 协议)的主要交易所。
    让我们研究另一个——芝加哥商品交易所 (CME) 市场数据协议。
CME 市场数据协议
CME 还创建了针对 HFT 优化的 SBE 协议。
    除了先前的协议之外,许多其他专有二进制协议以低延迟场所而闻名。所有这些协议都被认为是负责与交易所连接/交互的外部协议。我们现在将讨论为外部网络制定的交换协议和为内部网络制定的协议之间的区别。
内部网络和外部网络
查看图 5.8 时,我们可以观察到网络的两个不同级别。有使用先前协议与外界对话的网络级别,也有公司网络(内部网络)内的联网。下图说明了交易和交换网络中外部网络和内部网络之间的主要区别:



图 5.17 —— 内部网络和外部网络

与风险服务器通信的交易服务器使用内部网络,而上图左侧的交易系统将通过外部网络与交易所连接。
     内部网络将用于以下活动:

  • 内部市场数据分布
  • 信号共享
  • 订单录入
    在此网络中,必须尽量减少主机(服务器)之间的跳数。最好的系统将是一个系统,其中存在一个纯粹存在于 NIC 上的系统(换句话说,现场可编程门阵列 (FPGA),我们将在第 11 章高频 FPGA 和加密中讨论)。交换机和路由器的选择对网络延迟具有决定性作用。
    外部网络将用于订单输入和市场更新的交易所本机协议。
    我们现在知道哪个网络可以被认为是内部网络和外部网络。我们也知道数据包将使用哪个硬件从一个地方到另一个地方。在下一节中,我们将描述数据包的结构并进一步深入研究数据包的生命周期以及数据包从一个点移动到另一个点时发生的情况。
了解数据包生命周期
在学习网络概念模型部分,我们解释说,为了优化交易所和交易系统之间的通信,我们将使用铜线或光纤。这根线连接到 NIC。该电汇将从交易所传输包含市场数据的数据包和去往交易所的订单。
    我们首先需要讨论我们在此线路上传递的消息。本节将使用我们在本章中定义的 FIX 协议。让我们考虑以下 FIX 消息示例:
8=FIX.4.2|9=95|35=X|34=5|49=NYSE|52=20160617-23:12:05.551|56=TRADSYS|268=1|279=1|269=1|270=110|271=5|37=9|10=209|.    此 FIX 消息将是图 5.18 中所示数据包的有效负载。
    数据包有两个主要部分。标头包含 OSI 模型每一层的信息和包含 FIX 消息的有效载荷,如下所示:



图 5.18 —— 包头

    以太网层将代表数据链路层(如图 5.19 所示)、网络层的 IP 报头和传输层的 TCP 报头。 FCS 是添加到此数据包的错误检测代码。如前所述,数据包(或帧)的每一层都包含每一层的信息。我们将在图 5.20 中详细说明该数据包在机器中是如何处理的,但首先请观察下图:



图 5.19 —— 头部和 OSI 层

    在下图中,您可以跟踪携带市场数据更新的数据包通过系统到达交易系统(在此架构上运行的应用程序之一)的生命周期:



图 5.20 —— 市场数据在操作系统中流动

    我们将详细讨论将数据包从线路传输到应用程序(我们的交易系统)的所有必要步骤。我们将首先讨论发送/接收路径。
了解发送/接收 (TX/RX) 路径中的数据包寿命
连接到交易系统的交易所向交易系统发送一个数据包。铜线将把这个数据包传送到机器。以下是数据包将遵循的步骤:

  • NIC 接收数据包并验证 MAC 地址(分配给 NIC 的唯一标识符 (UID))地址是否与其 MAC 地址相对应。如果是这样,这个 NIC 将处理这个数据包。
  • 然后 NIC 验证 FCS 是否正确(校验和操作)。
  • 当这两个验证完成后,网卡会使用直接内存访问(DMA)操作将数据包复制到负责接收数据的缓冲区(接收(RX)缓冲区)。
  • 在图5.20中,RX缓冲区是一个循环缓冲区(或ring buffer),它是一种使用固定大小缓冲区的数据结构,端到端相连(主要是为了避免使用锁)。 DMU 允许 I/O 设备绕过 CPU 直接向主内存传输数据或从主内存接收数据,从而加快内存操作。
  • 然后 NIC 触发一个中断,让 CPU 处理这个数据包。中断处理程序通常分为两半——上半部分和下半部分。上半部分处理任何需要紧急完成的工作,下半部分处理所有其他处理。上半部分将管理诸如确认中断和将数据从网络移动到缓冲区以供下半部分进行后续处理等活动。处理器会从用户空间切换到内核空间,查找中断描述符表(IDT),调用相应的中断服务程序(ISR)。然后,它将切换回用户空间。这些操作是在 NIC 驱动程序级别完成的。
  • 然后 CPU 将在空闲时启动下半部分(软中断请求 (soft-IRQ))。我们将从用户空间切换到内核空间。驱动程序分配一个套接字缓冲区SK-buff(也称为 SKB)。SKB 是一种内存数据结构,包含数据包标头(元数据)。它包括指向数据包标头的指针,显然还有有效负载。对于缓冲区(RX 缓冲区)中的所有数据包,NIC 驱动程序动态分配一个 SKB,用数据包标头更新 SKB,删除以太网标头,然后将 SKB 传递到网络堆栈。套接字是在软件层面发送和接收数据的端点。
  • 我们现在将解决网络层。我们知道网络层包含IP地址。该层将验证 IP 地址和校验和并删除网络标头。验证 IP 地址时,会将地址与路由查找进行比较。如果某些数据包被分片,则该层将负责重新组合所有分片的数据包。完成此操作后,我们将处理下一层。
  • 传输层特定于 TCP(或 UDP)协议。该层处理 TCP 状态机。它会将数据包数据排入套接字读取队列。然后,最后,它会发出可以在读取套接字中读取消息的信号。
    我们将通过讨论负责写入和读取网络数据的软件层来结束本节。
软件层接收包
一旦有效负载写入名为读取队列的读取套接字,唯一缺少的步骤就是让应用程序(交易系统)读取有效负载。我们知道操作系统会安排应用程序在可能的情况下(公平规则)从套接字中读取数据。一旦交易系统(应用程序)读取有效载荷(在本例中为理解数据包生命周期部分中的 FIX 消息),它将开始解析消息的不同标签和值。
    当我们回顾交易系统为读取市场数据而必须执行的所有步骤时,HFT 主要关心完成操作所需的时间(以微秒或纳秒为单位)。因此,我们将看到如何改进这条路径。
    由于网络在速度方面至关重要,因此我们需要能够对其进行监控。在下一节中,我们将讨论监控技术。
监控网络

    网络对于高频交易至关重要。从关键路径中节省微秒以在网络中发送订单是关键。在网络搭建和系统运行的过程中,对网络流量进行分析是必不可少的。在高频交易中,安全性不是真正的问题,因为网络大部分时间都位于同一地点。我们将给予更多权重的监控部分是分析数据丢失、延迟和中断的数量。我们需要确保网络正常运行并提供最佳性能。
数据包捕获和分析
捕获以太网帧以供检查或分析称为数据包捕获。这个词也可以指数据包捕获程序生成的文件,通常以 .pcap 格式保存。抓包是一种典型的网络故障排除工具,也用于查找网络流量中的安全漏洞。数据包捕获提供了重要的取证信息,可以在出现订单数量被拒绝的问题后加强调查,这看起来像是网络延迟问题。
什么是数据包捕获,它是如何工作的?
可以通过多种方式捕获数据包。可以通过网络设备(例如路由器或交换机)执行数据包捕获,这些设备具有称为测试接入点 (TAP) 的特定硬件(我们将在下一节中介绍)。最终目标决定了使用的方法。无论使用何种机制,数据包捕获都是通过创建通过网络中给定位置的部分或所有数据包的副本来工作的。
    最简单的入门方法是从您的系统中捕获数据包,但有一些限制。默认情况下,网络接口仅处理发往它们的流量。您可以将接口置于混杂模式或监控模式,以获得更全面的网络活动视图。请记住,此方法仅捕获网络的一部分。例如,在有线网络上,您只会观察到计算机所连接的本地交换机端口上的活动。
    端口镜像、端口监控和交换端口分析器 (SPAN) 是路由器和交换机上的功能,允许我们复制网络流量并将其传输到特定端口。许多网络设备都具有数据包捕获功能,可用于直接从硬件的命令行界面 (CLI)用户界面 (UI) 诊断问题。
    专用网络 TAP 非常适合在特别大或繁忙的网络上进行数据包捕获。 TAP 是一种收集数据包的昂贵方式,但不会影响性能,因为它们是专用硬件。为了使 TAP 有效,有必要捕获两个方向(传输 (TX) 和 RX)。我们需要同时挖掘 RX 和 TX 端来构建完整的画面。
以太网 TAP——无源与有源 TAP 的权衡
网络 TAP 是再现流量以进行监控和分析的最精确技术。有多种网络分路器,每种分路器在网络正常运行时间和分析可靠性方面都有自己的优势。此方法可以是无源和有源网络分路器。无源和有源 TAP 之间的区别可能令人困惑。
无源网络TAP
其网络端口之间没有物理分隔的设备称为无源网络 TAP,如下图所示。这意味着流量可以继续跨网络端口流动,即使设备断电也能保持连接:



图 5.21 —— 无源网络TAP

    这适用于具有 10/100 米 (10/100M) 铜接口和光纤 TAP 的网络 TAP。光纤 TAP 的工作原理是将入射光分成两条或更多条路径,并且不需要电力。尽管10M 或 100M 铜线 TAP由于网络端口之间缺乏物理隔离导致它们完全是无源的,但在使用时依然需要电力。在这样的情况下,链路在断电期间保持运行,没有故障转移时间或链路恢复延迟。
有源网络TAP   
由于 TAP 内部使用的电气组件,有源 TAP 在网络端口之间具有物理隔离,这与无源 TAP 不同。因此,他们需要一种故障安全机制,以确保即使 TAP 断电,网络也能保持运行。该系统通过在小工具打开时保持一组继电器打开来工作。当断电时,这些中继切换到通过 TAP 的直接流量,确保网络运行。您可以在下图中看到对此的说明:



图 5.22 —— 无源网络TAP

    这两个 TAP 将有助于捕获市场数据以分析延迟并解决网络中的问题。如果此数据的时间不准确,则仅获取此数据是不够的。在 HFT 中准确测量时间是必不可少的。在下一节中,我们将解释如何操作。
重视时间分配

    正如您在本书中所理解的那样,高频交易与时间作斗争。这是我们必须确保获得正确交易模型的最关键资源。因为我们发送订单根据到达时间来决定是否执行,所以我们在构建交易策略时需要确保其执行与交易所所用时间匹配。我们将需要使用时间同步服务来实现这种测量精度。
时间同步服务
在开始本节之前,我们需要谈谈获取精确时间。在世界任何地方,我们都可以拥有精确的时间,而无需工程时间分配。我们使用全球定位系统 (GPS)全球导航卫星系统 (GNSS),因为它们使用原子钟。
网络时间协议 (NTP) 服务是使用最广泛的服务之一,用于将我们的计算机的正常运行时间与时间服务器同步。该服务有几个层,称为 strata,如这里更详细的描述:

  • Stratum 0:最高层,使用 GNSS 卫星。
  • Stratum 1:获取时间服务器的层,与stratum 0时钟一对一直连。您可以通过该层完成微秒级的同步。
  • Stratum 2:连接到 stratum 1 的多个服务器的层。
    最多有 15 层有助于获得不同类型的精度。返回的时间戳最大为64位时间戳,可以精确到皮秒级。在不久的将来有一天,128 位的时间戳将会到位,我们甚至可能获得飞秒级的精度。
精确时间协议 (PTP) 是一种基于网络的时间同步标准,力求达到纳秒级或皮秒级的精度。 PTP 设备使用硬件时间戳而不是软件,它专为一个独特的目的而设计:保持设备同步。PTP 网络提供比 NTP 网络高得多的时间分辨率。与 NTP 设备不同,PTP 设备将为同步消息在每个设备中花费的时间量加上时间戳,从而允许设备延迟。
    这两种同步机制使用来自卫星的每秒脉冲 (PPS) 信号,提供高精度。这些信号的精度从每秒 12 皮秒到几微秒不等。
为什么时机在高频交易中如此重要?
在订单中插入时间戳时,HFT 需要准确的协调世界时 (UTC) 才能跟踪市场订单。大多数 HFT 在专用 LAN 上运行许多计算机系统,每个 LAN 使用单个 PTP 超级主时钟,LAN 上的每台计算机都与该超级主时钟同步。超级主时钟需要从外部来源获取时间,因此每个物理位置都必须有一位超级主时钟。这些并行的高速计算机系统必须协调算法来处理市场买方和卖方数据。在日志文件和所有交易活动的网络分析中,还利用了时间戳和计算机同步。
    了解和分析 LAN 延迟对于 HFT 性能至关重要。如果时间同步不精确到微秒,HFT 将难以同时优化硬件和软件。对于非同一地点的交易者,实时市场数据通过电缆、交换机和路由器传输,延迟从 1 毫秒到 5 毫秒不等。与不在同一地点的交易者相比,在同一地点的 HFT 将延迟降低到 5 微秒以下,从而使他们有大量时间来处理市场数据。
    准确衡量市场行为和算法信号至关重要,因此衡量的准确性必须非常高。
总结

    在本章中,我们讨论了通信和网络的重要性。我们了解了高频交易的网络组件。我们深入讨论了适用于快速通信的以太网协议。我们描述了金融协议的设计,最后讨论了时间分配的价值。您现在已具备了解高频交易网络的知识。
    在下一章中,我们将最终开始讨论如何优化我们在本章和前几章中讨论过的所有谜题。
分享到 :
0 人收藏
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

积分:399277
帖子:79856
精华:0
期权论坛 期权论坛
发布
内容

下载期权论坛手机APP