各种组件

各种组件

现在,我们可以开始介绍系统的各种组件了(也就是各种软件程序),这也是实际执行高频交易操作的部分。如果说网络、通信和数据库这些基础设施提供了舞台和灯光,那么这些组件就是高频交易这场大戏的演员。在我们的系统中,这些组件是用C++ 语言编写的,并且运行在Linux 操作系统的一个定制版本上,这个操作系统已经被优化过了,移除了所有我们不需要的部件, 并且被安装在多核处理器上。这些高独立性的低耦合组件将会使用我们之前提到过的TMX服务进行相互通信, 并使用数据库在必要时对数据进行存取。

我们会做一些事情来进一步提高组件的性能。首先,我们使用TOE 卡来与网络交换数据, 把处理器从这种繁重而重复的工作中解脱出来,为高频交易组件的运行留出更多的时间。当然, 我们还希望发挥多核服务器在并行处理能力方面的优势, 把各组件的任务分配到尽可能多的处理器上去,这要求组件的程序使用多线程的方式编写。对于程序员来说,这是一项相对来说很繁重的工作,至少相对于编写单线程的程序要困难得多。幸运的是,英特尔公司提供了一个叫做"进程创建模块"( threading building block, TBB ) 的C++ 运行库,它能够帮助我们处理这些麻烦的细节,在它的帮助下,我们可以节省非常多的系统开发时间(当然,还有许多令人头疼的问题)。

典型的高频交易系统的组件结构可以非常庞大。一个大型系统经常会包含数千个同时运行的组件程序实例,它们之间协同工作以完成高频交易的各种任务,这样的系统通常都具有很高的复杂性。不过,对于那些最复杂的系统而言,由于许多组件实际上都在做着非常相似的工作(如果不是完全相同的话) , 因此要把这些组件分门别类并不是一件太难的事情。比如,可以把系统中的组件分成以下5 个大类: 策略组件、监听组件、定价组件、交易组件和管理组件。因5-2 显示了这些类别的组件如何进行交互。

策略组件的任务是将人们的思路转化为其他组件所要执行的指令。举例来说,我们都知道,不同的高频交易公司会采用不同的交易策略,可能某家公司只交易股票,并且会采取刮取返还( rebate scratching )策略和吃掉动作慢的( slow-mover takeout )策略。刮取返还策略是一种基于交易所交易费返还的策略;而吃掉动作慢的策略则是在市场突然大幅变动时, 反应较快的做市商吃掉反应较慢的做市商还来不及更新的价位上的报单的策略)。另一家同样只交易股票的公司可能使用的是推动大象( move the elephant )和趋势跟踪( follow trends )策略;还有一家公司可能同时交易股票、期权和期货,并会尝试像波动率套利这样的富有挑战性的策略。因为我们的系统实现了股票、期权和期货的高频交易功能,它可以实现以上讨论过的所有这些策略。而策略组件除了将这些思路转化为其他组件可执行的指令之外,还能实现一些其他的简单功能,比如维护可交易证券的列表,这同样取决于人们想要交易什么。市场上有几十万种可以交易的证券一一大约5000 只股票和30 万种期权合约,这件看起来很小的"家务事"实际上也不是那么容易能够完成的。

监听组件的任务是获取市场数据并将它们转换成其他组件能够使用的格式。它们处在离市场数据源最近的地方,例如交易所或者CTA/OPRA 平台,监听每一个市场数据,检查其中是否有错, 在不同的数据源提供的数据不一致时进行仲裁,然后将经过处理的市场数据发布到系统的其他部分。当然, 所有的这些任务都是在非常短的时间内完成的。

定件组件的功能应该和你想的差不多。它们会实时计算各种证券的价格,交易组件会根据这些价格向交易所下单。需要说明的是,定价组件的定价过程会受到交易潜在盈利alpha 和系统的持仓水平的影响:策略组件会向定价组件发送指令,让它去寻找潜在的盈利机会;而管理组件则会根据系统的持仓水平向定价组件发送指令,调整后者的定价逻辑。

和监听组件一样, 交易组件也直接与交易所通信,但是它的任务是向交易所发送委托单和报价。它们从监听组件获取市场数据, 从策略组件获取交易指令,并且从定价组件获取证券的理论价格,最后,它们还会向管理组件报告交易结果。

管理组件的基本任务是根据交易行为和其他有意义的事件来控制其他组件的工作一一主要是交易组件的工作。例如,当一笔交易发生时,管理组件会更新交易证券的仓位,而这个仓位会被反馈给定价组件来调整其定价逻辑。管理组件还要负责其他一些重要的任务,例如在发生了一些高风险事件或者糟糕的交易时,通知交易组件修改或者停止交易。

可以看到,我们的监听组件、定价组件、交易组件和交易所之间是通过有方向的、有些循环的相互作用连接在一起的。这就是对任何高频交易系统都非常重要的低延迟链路圈。一笔市场数据从交易所传来,监听组件会获得它,在一系列检查和处理之后再将它传到系统的其他部分,定价组件使用它对证券重新定价,而交易组件则可能使用这个新的价格向市场报单。这些事情的处理过程进行得越快,我们的系统就越有竞争力。因此,当实现一个高频交易系统时,我们会发挥我们所能想到的任何技术或者逻辑上的优化手段的优势,来将这个过程的耗时减少几毫秒甚至是几微秒。而其他一些组件之间的通信,比如策略组件和定价组件之间的通信, 因为对延迟并不敏感,所以我们也就不会花太多工夫让这种数据通路变得更快。

我们接下来将要逐一讨论上面这个组件清单中的各个关键成员。除非特别说明,否则这些组件的实例都会运行在我们所有的远程服务器上。下面的讨论并没有穷尽系统中的所有组件, 一个真实的系统通常还会包含具有各种其他功能的组件,但是我们已经把所有基础的组件都包括在内了。我们对组件功能的描述只关注其最基础的工作职能,并忽略了一些特别伤脑筋的细节问题。当总结了每一个组件的具体任务之后,我们会描述一个具体的场景, 来展示这些组件是如何进行交互协作,并最终完成高频交易这项工作的。

策略组件

策略组件的任务是将专业人员下达的命令转化为具体的各个其他功能组件所能够执行的指令,主要包括三种组件:策略服务器、证券列表管理器和合规管理器。

策略服务器

你将会在接下来看到,系统中大多数的组件都是高度专业化的,一般来说它们只做一件事情。策略服务器的基本功能是从专业人员(包括交易员、量化分析师、系统支持工程师)处获取命令,并将它们转化成具体的指令,下达给其他的各个组件,而这种转化过程则主要取决于下达命令的人所希望实现的策略。例如,如果公司希望实现一个基于股价相对于股指期货价格变动的滞后效应的交易策略,那么它会让策略服务器通知股票定价组件计算期货指数中的每一只成分股由于期货价格变动而产生的alpha 。而在其他组件启动的时候,策略服务器也会告诉它们之后的行为模式。从这个角度来说, 策略服务器看起来很像一家依靠交易员人工交易的公司里每天的例行晨会, 在晨会上,风控经理和交易员会在开盘前聚在一起, 确定这一天的交易策略和交易额度限制。

在策略服务器组件的设计中,一个重要的考虑是, 将策略的转化过程集中在一处,而不是将它分散到多个地方,因为这样会使得系统相对来说更容易维护。假设这些策略(比如说趋势跟踪策略)指令零碎地分散在各个地方,那么当你想要修改策略的实现时,需要在许多地方都进行修改,这很显然会导致你更容易错过一些东西。策略服务器组件的指令和其他组件之间的交互对时间并不敏感,所以只需要把它放在我们的控制服务器上就行了。

证券列表管理器

证券列表管理器组件的功能看起来并不太复杂,不过仍然是非常重要的。它记录着系统可能交易的所有证券。具体说来,它维护着一张包括股票、期货合约和期权合约的列表,这张列表还包含这些可交易证券的一些其他细节信息:对股票来说,这些细节包括预期的分红时间和收益公告时间等;对期权来说,这些细节包括到期日、执行价格之类的信息。期货合约和股票的列表可以由人工输入来完成,但是由于期权合约的数目太多了,所以最好还是使用一种更加自动化的方法来处理期权的列表。

几乎每天都会有新的期权合约上市。举个例子,假设AcmeExplosives 公司的股票目前的价格大约在50 美元左右,那么看涨期权的最高执行价格会是80 美元,如果股价涨到了60 美元,交易所一般来说就会在市场上挂出一个新的执行价格为90 美元的看涨期权。大多数新的合约都是在隔夜的非交易时间段挂牌交易的, 因此证券列表管理器必须在每天交易结束后,或者在第二天开盘前从期权清算公司( Options Clearing Corporation , OCC ) 或各个独立的期权交易所获取这些新的合约,它同样也会在日内查询这些信息源,看看是否有新的执行价格的期权挂牌。我们只需要在控制服务器上部署这种证券列表管理器组件就够了。

合规管理器

对任何交易公司来说,"合规"这两个字看起来都挺好笑的,这是指用一些法规条文来规范交易的行为。其中的多数规则主要涉及的是填写报告、交易员的交易资格,以及诸如此类的与高频交易系统设计无关的事情。不过还是有一些规则会对高频交易过程中的实时行为产生影响,这些规则必须在系统中体现出来。

一个具体的例子是,一些期权交易所对期权做市商有"合法价差"的要求。这种要求对做市商在一个期权上的买卖价差进行限制。大多数期权交易所在正常的交易日都会要求期权做市商所报的买卖价差不超过5 美元,不过这个价差实在太大了, 所以大多数时候它都没什么实际意义。合法价差的范围则窄得多(至少在交易日的开始时段内) , 另外,它还会根据期权的到期时间和申买报价进行调整。合规管理器维护着所有诸如此类的规则细节,并且在必要时向对应的组件提供这些规则(在合法价差规则的例子中, 合规管理器组件会向系统的做市组件提供这些信息)。同样,合规管理器组件只需要部署在系统的控制服务器上。

监听组件

我们的系统中有四种监昕组件,其任务是从外部收集市场数据和信息,并且将它发送给系统中的其他组件,它们分别监听股票市场数据、期权市场数据、期货市场数据和各种新闻。

股票市场监听器

股票行情监听器组件通过原生API 与交易所连接,并监听股票市场的行情——当前的申买价、申卖价以及各种其他交易信息,这些行情既由交易所独立发布,同时也会被统一数据平台转发,然后将可疑的数据过滤掉,把经过过滤的数据以广播的方式发送给系统的其他组件。对可疑数据的过滤是非常关键的。每天市场上会有数亿条数据被发布,其中的一些有可能因为人为的或技术上的各种原因出错。你决不会希望你的系统被这些有瑕疵的数据所误导,向市场进行错误的报价或下单. 这会让你亏掉很多钱。需要注意的是,我们发布的不仅仅是委托单簿顶部的行情,而是全市场深度行情。股票监听器还发布所有交易该股票的市场的状态(期权和期货监听器也是如此)。

任何一个交易市场都有好几种可能的当前状态。例如,在晚上,大多数的交易所处于收盘状态,而在白天的很长一段时间内,它们处于开盘状态。显然,你不希望你的系统在交易所收盘时段内去做任何交易。另一种常见的状态是速动市场( fast market ), 这种状态通常出现在市场经历了突然的非正常大幅波动的时刻。在此状态下,交易所可能会对一些交易规则做出修改。监听组件在这时需要向系统发送市场状态的变化,让其他组件能够对这种变化做出反应。

期权市场监听器

期权市场监听器组件的工作和股票市场监听器并没有多大不同,只不过它的数据源是各个期权交易所和OPRA 平台。因为期权市场上的合约数目远远超过股票市场, 因此期权市场监听器会比那些监听股票市场的同伴们忙得多。

期货市场监听器

与股票以及期权市场监听器一样,期货市场监听器组件监听、清洗并向系统中的其他组件发布各种股指期货行情,比如我们之前提到过的E-mini 标普500 指数期货合约( ES )。除此以外, 这个组件同样会发布来自于芝加哥商品交易所的欧洲美元期货合约行情数据。欧洲美元期货合约的持有者可以在未来某段时间以约定利率借入或者拆出一笔金额。LIBOR 是伦敦银行间拆借利率( London interbank offer rate )的缩写,它在市场中广泛地用于无风险利率的基准,也是期权定价的输入参数之一。我们接下来会看到,一个叫做"利率由线生成器"的组件会使用这些欧洲美元期货合约的价格来推导出无风险利率。

新闻监听器

市场新闻监听器组件的任务有点像一个坐在电脑前盯着彭博终端屏幕的交易员,它会不停地搜索一些能够引发市场兴趣的关键词,比如一家上市公司发布公告改变了之前的股利分配方案, 或者发布了一份新的盈利公告,这样的信息会对股票价格或者期权价格产生影响。一旦探测到了这种信息,市场新闻监听器就会马上把它广播给系统中其他可能会对这些信息做出反应的组件。例如,一个用来实现事件驱动交易策略的组件很显然会订阅这样的新闻,还有我们之后将要提到的期权定价组件,同样也需要订阅这些信息来获取关于股利变化之类的新闻,从而修改股利预期并更新对期权的定价。

定价组件

我们接下来讨论的这些组件会直接或间接地为我们所要交易的证券进行定价。

隐含波动率生成器

股票或股指的波动率是对于其价格变化的频率和幅度的一种数值上的描述,它同时也是期权理论价格的计算中最重要的因素之一。对于波动率这个概念,最困难的地方是,虽然有很多地方需要用到它,但没有直接的方法可以测量它。不过你可以从当前的期权价格反推出一个隐含的股价波动率,而这就是我们所讨论的这个组件一直在做的事情。隐含波动率生成器会一直监控市场上期权的当前价格一一申买价、申卖价以及上一笔成交价,并且用一个期权定价公式(例如布莱克-斯科尔斯公式)来反推出股价的隐含波动率。

也许这听起来有点奇怪,不过我们会做解释。对一个期权定价公式而言,标准的输人参数包括当前的股价、预期股利、执行价格、距到期日的时间、无风险利率,当然,还有波动率。如果要根据公式计算出期权的理论价格,那么你要做的就是搜集所有的这些参数,然后把它们放到公式中去。但是如果你已经看到了市场上的期权价格,同时还知道除了波动率之外的其他几个参数, 那么你就可以把公式改写一下,然后反推出要得到这个价格的波动率应该是多少,这就是隐含波动率的概念。

波动率曲线生成器

上面已经提到,标准的期权定价公式中需要波动率这个参数。对于一个期权交易者,特别是期权做市商而言,无论怎么强调波动率的重要性都不为过。在期权交易中,可以说波动率就是期权的"价格" , 而那些几块几分的权利金之类的东西是第二位的。期权交易者的脑子里经常想的不是买卖期权,而是买卖波动率。如果一个高频交易系统以1美元的价格买入了100 股某公司的股票,并很快地以1.02 美元的价格把它们卖了出去,那么看起来这是一笔不错的股票交易;而对于高频期权交易而言, 一笔好的交易是, 系统以30点的波动率买入100 份期权,然后很快以32 点的波动率将它们卖出。

波动率曲线生成器的工作是持续地计算并向系统发布由不同执行价格和到期时间的期权价格根据期权定价公式所反推出的隐含波动率, 主要是为期权定价组件服务。在这里,这些期权的隐含波动率以曲线的形式表现出来。最常见的一种曲线是一条简单的正交坐标轴曲线, x 轴(水平轴)表示期权的执行价格,而y 轴(纵轴)则表示波动率。图5-3 中画出了一条这样的曲线。

这条曲线显示, 任意一个执行价格上期权的隐含波动率受到两个输入参数的影响。一个是隐含波动率,还有一个是我们手头的存货,即在这些执行价格上的期权的仓位。回想一下最基本的倾斜做市策略。该策略的基本思路是要完成双向交易(也就是一买一卖, 或者一卖一买),为此,在一笔交易之后,需要修改你的申买价(如果刚刚卖出)或申卖价(如果刚刚买入), 让你的报价在市场上更有吸引力,从而增加反向交易完成的概率。

在期权交易中,这种倾斜策略不仅可以通过修改实际的期权报价来完成,还能够通过修改波动率曲线的方式来完成。对于期权来说,这种修改波动率曲线的方式尤其方便,因为实际上会有好几个期权( 例如同一个执行价格上的看涨期权和看跌期权)在计算理论价格时使用相同的波动率,因此修改一个波动率实际上同时修改了多个期权的报价。如我们刚才所说的,波动率就是价格。如果你已经买入了一些某些执行价格上的期权头寸(买入波动率),为了完成反向的交易,你完全可以通过调低在相应执行价格区域的波动率来让你成为一个有竞争力的卖家。

如果你已经非常习惯地把波动率看作期权价格的一种形式,也许很快就能想出第三个影响波动率曲线的因素, 它非常类似于股票中alpha 的概念。考虑两条波动率曲线, 其中一条是基于标普500 指数的期权波动率曲线,而另一条则是基于纳斯达克100 指数的期权波动率曲线。假如你相信( 一些高频交易者的确是这么认为的)这两条曲线上的波动率存在领先-滞后效应(其中一条曲线上的波动率水平发生改变,引发了另一条曲线上的波动率随后发生同向变化)。在某个时刻,基于标普500 指数的期权的隐含波动率曲线因为某种原因突然上升,那么你应该非常迅速地向上调整另一条基于纳斯达克100指数的波动率曲线,来抓住这个非常短暂的相对低估的机会买入波动率,然后当市场做出向上的调整之后,再卖出波动率以实现获利。

图5-3 中的曲线给出了一些给定的不同执行价格上的期权隐含波动率,而另一种常见的波动率曲线刻画的则是不同到期时间的期权隐含波动率。波动率曲线生成器既可以将这两个维度上的波动率曲线分别发布,也可以把它们合在一起形成一张波动率由面。图5-4 给出了一张波动率由面的形状,我们将在后面用它来讨论波动率套利策略。

利率曲线生成器

任何一个标准的期权定价公式都需要无风险利率这个输入参数,利率曲线生成器组件所做的就是持续地计算并且向系统中发布利率曲线(也叫做收益率曲线)。和波动率曲线一样,利率曲线也画在一个很简单的正交坐标轴中,显示不同期限上的利率水平。图5-5 给出了一条利率曲线的示意图。

利率曲线生成器主要使用当前欧洲美元期货合约的市场价格来计算利率水平,我们在前面提过,欧洲美元期货合约在芝加哥商品交易所进行交易,期货市场监听器会将它的行情发布到系统中。这种计算利率的过程有点乏味:一张欧洲美元期货合约锁定了以未来某个时点为开端的一段时间内的借款水平,因此这种期货合约的价格中也就隐含了远期利率,我们可以从中得到一个相对应的即期利率,而这也就是我们所想要的。利率曲线生成器组件会在每收到一个欧美元期货报价时重新计算即期利率,然后将它插入到固定到期时间的利率当中,形成类似图5-5 中的一条利率曲线。

股票定价组件

股票定价组件是我们的系统中一个相当重要的组件, 它计算所有经过alpha 调整的股票价格。计算这些价格的基础是股票的当前市场价,股票市场监听器会将它们发布到系统中,而计算alpha 的方法则有很多(我们在之前章节中讨论配对交易策略时曾经提到过这些方法)。举个例子,在一个基于股价对股指期货变动滞后效应的策略,股票市场监听器会监听由期货市场监听器发送的标普指数期货合约的价格。根据指数期货合约价格变动的方向和幅度,以及之前观察到的股价变动与指数期货价格变动之间的关系(例如beta ),定价组件计算出一个alpha 因子,并使用这个因子对当前的股票定价做出修改。

期权定价组件

对于每一个我们想要交易的期权合约,期权定价组件都会为它计算一个当前的理论价格,以供做市组件使用。这个理论价格基于当前的股票价格(由股票定价组件提供)、波动率(由波动率曲线生成器提供)、无风险利率(由利率曲线生成器提供)、预期股利、执行价格和距离到期日时间(最后三个参数由证券列表管理器提供)计算得到。这个组件可以使用很多种期权定价公式来计算期权的理论价格,当然, 其中最著名的一种还是布莱克-斯科尔斯期权定价公式,但是它只能用于计算欧式期权的理论价格(欧式期权只能在到期日执行)。对于许多美式期权而言(美式期权可以在到期日之前的任何一天执行) , 它们的定价需要使用一种二叉树模型, 还有另一个基于树结构的模型一一三叉树模型,它有一个很相似的"近亲"叫做有限差分法( finite difference method , FDM )。 对于这些模型的进一步探讨超出了本书的范围(市场上有很多书对这些模型的讲解都很不错)。在这个假想的系统中,我们将使用有限差分法为美式期权定价。它是一个非常高效的模型,同时还能够与计算机的并行处理配合得很好,而并行计算也是我们将尽可能多使用的技术之一。

不论使用哪一种公式,在股价变动后对期权价格的重新计算都需要花上一些时间。为了在交易中减少这种时间开销,我们将使用一种在很早以前被用在人工期权交易中的技巧。由于变动最频繁的期权定价参数是标的股票的价格和其波动率,我们会在每个交易日开始之前以标的股票当前的价格和波动率水平为中心,预先计算期权在一系列可能的价格和波动率之下的理论价格,对于所有不同执行价格和到期时间的期权,我们都会重复这项工作。那么到了标的股票价格真正发生变化时,期权定价组件就不需要重新计算其理论价格了, 而只需要查询一个含有所有这些预先计算过的理论价格的三维矩阵就够了。

这种方法在之前就被人工期权交易员们广泛使用。每天早上,这些交易员和他们的书记员都会打印出一厚摞这样的单子,这些单子上记录着标的股票在不同价格和不同波动率之下期权的理论价格,这些交易员会在交易时段不停地查这些单子(当然,如果股票的价格变动超出了预先计算的范围,他们也会收到一些新的单子),这样他们就可以方便地获得期权的理论价格,而不需要花太多时间重新计算。计算这样的一些矩阵实际上并不像看起来那么容易。首先,即使是预先计算也要花掉不少时间, 你不可能为所有可能的标的股票价格和波动率水平都进行预先的计算, 事实上你只是选择一些比较合理的、离散的价格和波动率水平,并计算对应的期权理论价格,然后通过插值的方法得到在所有可能的价格和波动率水平下的期权理论价格。另一个挑战在于,插值不能太少,否则它会降低插值所获得的价格的准确率;如果插值的频率太高,又会使得计算所花的时间太长,这也违反了你的初衷。图5-6给出了一个预先计算出的价格矩阵。

做市组件

做市组件的功能是为系统进行做市的每一种股票和期权合约计算出一个买卖差价。计算买卖差价的依据包括:当前的市场状态、策略服务器的指令,以及股票定价组件和期权定价组件的定价水平。股票的做市组件同时还会考虑当前的持仓水平(存货),并且据此对市场做出倾斜调整。我们之前提过,期权的倾斜调整已经包含在生成波动率曲线的过程中,因此做市组件中不再进行这样的调整。此外,期权的买卖价差还会考虑一些其他因素,比如对冲交易的成本、融资成本(例如,借款买入期权时的成本),以及所谓的"波动率的波动率" (回想一下, 波动率实际上是期权价格的一个代理变量,在一个波动率变动频繁的期权和波动率比较稳定的期权之间,做市商会为持有波动率变动频繁的期权要求更多的风险补偿)。

交易组件

系统中的交易组件包括四类:报价引擎、电子眼(包括一种专门执行期权价差交易的组件)、股票定位器和对冲器。它们直接与交易所进行交互,完成交易执行工作。

股票报价引擎

股票报价引擎的功能是将做市商组件对股票的报价(包括买价、卖价和相应的股票数量)传递给交易所。和监听组件一样,报价引擎组件也是使用交易所的原生API 编程实现的,因此,我们在每一家交易所的报价引擎组件都是不同的(例如,不使用FIX 协议)。虽然向交易所的报价引擎传送报价这个概念看起来很简单,但是在实践中它却是一项非常冗长复杂的工作。各交易所在很多方面都存在着一些细微的差,例如在一个报价包中最多能容纳多少个报价、接收报价的频率、如何向报价引擎发送收到报价的信号等。把这些细微的差别都弄清楚是非常重要的,因为对做市商而言,报价是和交易捆绑在一起的义务,并且报价几乎时时刻刻都需要更新。如果你想改变报价,但却因为某种原因失败了,你很有可能会眼睁睁地看着别人把你来不及更新的报价给吃掉,强迫你做出一笔坏的交易。

股票报价引擎的另一项任务是对安全控制进行正确设置,大多数(但不是全部)交易所都有这样的控制策略,以保证做市商不会做出一些他们并不想要的交易。例如,交易所可能会让你设定X和Y的值, 如果你在Y 秒内完成了X 笔交易,交易所就会自动地将你在市场中的所有报价都置为无效。另一个常见的例子则被称为"心跳监视器" ,这里的概念是,报价引擎每隔一段时间向交易所发送一条简单的信息( 被称为一个"心跳" ) 来告诉交易所这个引擎是能够使用的,或者说"活着"。如果交易所探测不到你的"心跳",那么它将认为你那边出了问题,并将你的报价从市场中移出。

股票电子眼

股票电子眼( electronic eye , EE ) 是一个与股票报价引擎很类似的组件、它根据市场的买卖价差和数量以及策略服务器的指令向某家特定的交易所(使用原生API ) 发送委托单(举例来说,策略服务器可能会向电子眼发送指令,告诉电子眼是否使用比报价引擎更紧的报价)。不过报价引擎向市场发送限价单(也就是它们的报价) ,电子眼则发送不成即撤委托单。报价引擎只发送被动报单,电子眼则进行主动交易。

期权报价引擎

与股票报价引擎相同,只不过是对期权进行报价。

期权电子眼

与股票电子眼相同,只不过用于期权交易所。

期权价差策略执行器

与期权电子眼一样,期权组合策略执行器下单的类型也是"不成即撤单",但是它不只对一个期权合约进行下单,而是对一组标准的期权合约组合进行下单,这类组合称为价差或者策略。一个单一的期权合约通常被用来实现一些简单的投资目标,例如对股票价格可能的剧烈下跌进行保险等;而价差组合则可以用在诸如对股票价格可能的超出某个价格范围的变动一一涨过某个高价或者跌穿某个低价一一进行保险之类的目的上,换句话说,也就是对潜在的离波动率进行保险。一个典型的例子是跨式策略(我们之前在第3 章中曾讨论过),它由相同执行价格上的一个看涨期权和一个看跌期权组成,这种组合策略能够用来降低整个投资组合的波动率风险暴露(一个叫做vega 的风险度量)。期权价差策略执行器会监控价差委托单簿,例如芝加哥期权交易所的复杂委托单簿( complex order book,COB ),并且根据策略服务器的指令进行交易。

股票定位器

要卖空一只股票,交易者可以从别人的账户上借到股票,并且在某个时刻将这些股票买回来归还给借方。卖空股票有很多种可能的原因, 对股票高频交易者而言,其中的一种原因是, 他想要吃掉一张市场上的买单,但是账户上并没有对应的股票;对于期权高频交易者而言,他可能想要卖空一只股票来进行期权的delta 对冲。不论你因为什么原因需要卖空股票,原则上(至少这是一种好的做法)你都需要在卖出之前先借入这些股票。股票定位器组件的任务就在于此,它使用与股票经纪商( 借入股票的通常来源) 之间的连接来保证在卖空之前有足够的股票可以借入。我们只需要在控制服务器上配置这个组件就够了。

自动对冲器

回想一下之前描述的跳过delta 策略,我们讨论过一个期权做市商在一笔期权交易之后如何通过交易一定数量的股票来对期权头寸进行delta 对冲。自动对冲器组件的任务就是进行这种对冲操作,其最基本的原理就是在一笔期权交易之后,根据在当时计算出的期权的delta 值买入或者卖空一定数量的股票。在实践中,还会有一些别的考量。首先,也是最重要的,期权的delta 值像它的理论价值一样,同样会随着时间改变,因此,对冲的头寸必须根据delta 值的改变不断地进行再调整,这就要求自动对冲器持续地监控期权头寸的delta值变动,并且以此为根据买卖股票来保持组合的delta 中性。同样,当一个期权到期、执行或者被执行时,以及期权交易不成功或者被调整(参见"管理组件" 一节中对仓位管理器的讨论)时,也需要对相应的股票头寸进行改动。

我们可以很清楚地知道, 当期权做市商试图按照这种常规的方式进行delta 对冲时,会给那些试图抢在他们对冲之前交易股票的高频股票交易者带来机会。因为这个原因,一些期权做市商并不使用标的股票,而是使用一种指数合约来进行delta 对冲( 例如我们之前曾提到过的Spider ETF ,如果标的股票在标普500 指数中的话)。这么做需要一点技巧, 因为使用ETF 进行时,用于对冲的ETF 数量不仅取决于期权的delta ,还取决于标的股票的beta 值。但是,如果做市商不希望被这些跳过delta 交易者占便宜的话,他也没有别的选择。

除了delta 对冲之外一一也就是试图抵消由期权价值相对标的股票价格变动的敏感性所导致的组合价值变化一一自动对冲器还负责进行rho 对冲。rho 是期权价值相对于无风险利率变化的敏感性的一个测度,当无风险利率变化时,期权价值也会发生变化。交易者可以使用一种很类似于delta 对冲的方式来对冲这种风险暴露,而这种对冲所使用的工具则是欧洲美元期货合约(我们在介绍利率曲线生成器时提到过它),所使用的因子是rho。rho 和delta 一样,会随时间发生变化, 因此需要重复地进行计算和对冲操作。

管理组件

以下将要讨论管理组件, 这些组件并不会参与到高频交易的工作中,但是它们所负责的监控以及报告任务仍然是非常重要的。

熔断器

在任何一个交易时刻,高频交易系统在美国各个交易所中会有超过100 万个报价, 每一个报价都代表着一个以该价格进行交易的义务。当然,我们的系统会在一天中持续不断地修改这些报价来保证只在我们想要的价格上进行交易。这些报价本身就会让我们暴露在很大的风险之下,如果我们不能成功地以最快的速度来更新这些报价的话,就会有人非常愿意以一些对我们来说很差的价格和我们进行交易,这也就是"捡我们的便宜" 。而我们现在拥有一个如此复杂的系统,可能会有非常多的原因导致我们在市场中报出很差的价格。市场价格的改变非常之快,实际上在被别人"捡便宜" 之前,没有足够的时间来让人们通过监控发现这些问题。所以,我们需要一个专门的系统组件来监控我们所能想到的任何可能导致较差报价的状况,并且在这种状况出现时自动通知其他组件相应地调整各自的行为。

这种状况的一个例子是丢失市场数据连接。在不知道当前市场价格的情况下,你几乎是不可能知道应该以什么样的价格进行交易的。当熔断器检测到市场数据连接丢失时,它会向所有的交易组件发送消息,并告诉它们停止交易。以自动报价组件为例,在收到这个消息后, 它可能会将市场中所有的报价都撤回,也可能暂时性地将买卖价差拉大以保证这些报价不会成交。其他的一些情形包括系统触及了持仓限额、异常迅速的成交(例如在Y 秒内交易了超过X 张合约或股票)、发生了坏的交易以及系统的一些重要组件(例如监听组件或定价组件)功能失效等。

交易日志

这个组件的任务就和它的名字所显示的那样简单。它维护着一份系统所做的每一笔交易的日志。对于每一笔交易,它会记下交易的证券名称、交易价格、买卖方向、交易所名称以及交易的对手方(如果交易所提供的话)等各种信息。

仓位管理器

和交易日志一样,仓位管理器的任务也非常简单,但却非常重要。仓位管理器只是监听交易回报,为每种交易的证券维护一个动态仓位,并且在这些仓位发生变化时向系统进行报告。需要注意的是,并不是只有交易才会导致仓位的变化。对于交易所而言,还不时会发生在一个交易日结束时通知某个交易者其交易被取消(这笔交易会被抹掉,就像它从未发生一样)或者调整(这意味着交易量或者价格被修改了)的事情。交易取消和调整通常是由交易所自身或者交易一方的" 明显错误"导致的。对于期权的仓位而言,仓位管理器还需要同时考虑期权到期、执行和被执行等情况,它们都会导致期权仓位的变动。

风险管理器

高频交易者最基本的要求就是,以一个价格买入,并以一个更高的价格卖出。风险管理器所要考虑的就是在买入后卖出前所发生的事情,也就是高频交易者在等待双向交易完成时所面临的金融风险。

它会不停地衡量我们持有的头寸所面临的风险。假设一个高频交易者想要以1.00 美元的价格买人PDQ 公司的股票并以1.01 美元的价格卖出,现在我们看看表5-2 所示的交易过程。

在第1笔交易中,交易员花了500 美元买入这只股票。和所有的股票投资一样,这500 美元现在面临着风险。如果股票的价格下跌,交易员会因此亏损, 有可能亏掉全部500 美元。在第2 笔交易后,他的仓位变成了100 股因此他面临风险的资金也变成了100 美元(他在这笔交易中所赚得的利润与当前面临的风险无关)。在第3 笔交易后,他的风险暴露变成了200 美元,在第4 笔交易后继续增加到600美元。风险管理器的主要目的就是跟踪我们交易的每只股票的风险暴露。不过我们的风险管理器组件做的还不只是监控这些风险暴露。当某只股票的风险暴露超过了一个事先设定的阈值,它会自动发出交易指令来减少它。假设我们对PDQ 公司股票的风险暴露阈值为800 美元,让我们接下来看看表5-3 中的交易序列。

在时刻6 的交易之后,风险管理器识别出我们在PDQ 股票上的仓位已经超过了800 美元的阈值水平。于是在时刻7 ,它自动卖出了100 股,这笔交易让风险暴露回到阈值,但也导致了一定的亏损。在上面的场景中,我们在这里仍然有7 美元的净收益(在第2 笔交易中盈利8 美元,减去第7 笔交易中亏损的1 美元)。风险管理器主要关心的是管理风险暴露。如果需要以亏损8 美元甚至更多的代价卖出股票, 它同样会执行这种降低风险的交易。

对期权而言, 风险管理器的任务要更加复杂一些。股票投资组合只有一个风险来源:股票市场价格的变化。而期权投资组合则不只是对股票的市场价格的变动敏感(用期权的术语来说,这种敏感性表现在delta 上) , 对其他一些因素的变化也同样敏感。期权组合的其他风险暴露由其余的一些希腊字母给出:gamma (组合价值对股价变化的二阶导数)、vega ( 组合价值对波动率变化的敏感性)、theta(组合价值对时间变化的敏感性)以及rho (组合价值对无风险利率变化的敏感性)。我们知道,自动对冲器承担了delta 对冲和rho 对冲的任务,尽管如此,风险管理器还是会持续计算所有的这些风险暴露,至少将它们显示给交易员和风险管理员,并将这些风险暴露值发送给系统中的其他组件(例如熔断器)。

除了根据当前的市场状态计算风险暴露之外, 风险管理器同样会持续地进行一些假设分析,在各种情境下计算风险度量值。例如,它很可能会在一系列可能的标的股票价格( 既可能高于市场价,也可能低于市场价)下计算股票和期权的delta 值。这样, 交易员就能看到它们的风险会怎样根据市场的变动发生变化。这个组件很显然是系统中最不可或缺的组件之一,因此,我们不仅要将它们部署在控制服务器上,还要将它们部署在每一个远程服务器上。

盈亏计算器

毫无疑问,我们会不停地重复问一个问题:我们在赚钱吗?盈亏计算器的工作就是回答这个问题。最基本的每日交易盈亏计算是这样进行的:对于每一种交易的证券,计算其在交易日结束时的价值和交易日开始时的价值之差。而对于那些当天有交易的证券,使用交易价格来替代交易日开始时的价格(因为你在交易日开始时并不持有它),然后减去所有的成本和开销(交易费用等)。如果你想在日内计算盈亏,那么就使用当前价值替代交易日结束时的价值。计算结果就是这种证券的当日盈亏,把它们合在一起就是你当天的交易操作的整体盈亏。过程就是这样,我们不需要在远程服务器上做这些事情,所以只要把这个组件部署在控制服务器上就行了。

在大多数交易公司, 有两种计算盈亏的方式,它们有时被称为"前台盈亏计算"和"后台盈亏计算" 。前者使用理论价值来计算盈亏,其目的是为交易提供参考; 后者则使用"逐日盯市"价值,根据市场上实际观测到的价值来计算盈亏。长期来看,这两种计算方法得到的结果是基本相符的而如果是计算一两天内的盈亏,用这两种计算方法得到的结果有些差异也并不奇怪。

报告盈亏的方式有无数种。你可以计算每个交易台的盈亏,可以计算每个时间段的盈亏,也可以计算每种证券类别的盈亏,还有很多其他计算盈亏的方式。但最基本的计算方法都是一样的。对于期权的盈亏,把盈亏按照各个希腊字母进行分配是一种很有帮助的计算方式。例如, " delta 盈亏"是一种不错的衡量delta 对冲效果的指标,"Vega 盈亏"则能够衡量波动率管理的水平,对其他希腊值来说也是如此。如果你知道这种将盈亏进行分配的方法对把你的系统调整得更好会大有帮助。