哪种编程语言最适用于算法交易系统?(上)

用户头像量化小精灵
2023-03-08 发布

哪种编程语言最适用于算法交易系统?(上)

最简短的回答是:没有“最好”的语言。策略参数,性能,模块化,开发,弹性,成本都是必须考虑在内的因素。本文将对一个算法交易系统架构的必要组成部分和实时决策如何影响语言的选择进行概述。
首先,我们需要考虑算法交易系统的主要组成部分,比如研究工具,投资组合优化机构,风险管理人员,执行引擎等。接着,我们将对不同的交易策略进行研究,并探索它们对系统的设计有何影响。我们会着重讨论交易的频率和可能的成交量。

我们一旦确定了交易策略,最需要做的就是搭建整个体系的架构。这包括硬件的选择、运行系统,以及系统对罕见的、潜在的灾难性事件的抵抗力。在考虑架构的同时,性能也必须得到充分地考虑——包括研究工具和实时执行环境。

1.这个交易体系是怎么运作的?

在确定使用何种“最佳”的语言来编写自动化的交易系统之前,我们需要对需求进行定义。这个体系纯粹是以执行为基础吗?这个体系需要一个风险管理或资产配置模型吗?这个系统需要一个高效的回测吗?(对以前的市场数据进行一次交易的评估叫做“回测”。)数据的大小、算法的复杂程度会极大地影响到回测传感器的运算能力。CPU的速度和并行性常常会限制对开发的执行进行最优化。

信号生成涉及从算法生成一组交易信号,并将此类订单发送到市场,通常通过证券公司。一些策略要求高的性能,如I/O问题,网络带宽、延时等,常常成为优化系统的制约因素。所以,你的系统中的每一个部件所使用的语言都会有很大的差异。

2.策略类型,频率和数量

使用哪种算法策略会极大地影响到整个系统的设计,因此我们必须要考虑到所处的市场、与外部的资料提供者的联系、策略的频繁与数目、开发困难与性能最佳化的折中,还必须要有定制的服务器, 例如GPU或 FPGA。
此外,我们在设计时必须要考虑到与供应商的联系、API的架构、数据的及时性、储存需求、在与厂商脱机情况下的灵活性等因素。在界定技术堆栈时,策略的频率也许是一个主要的驱动因素。在使用高频策略时,我们要储存和评价海量的市场信息。通常,我们会使用使用HDF5和 kdb+等软件。
为解决 HFT应用中的海量数据,我们需要采用一种经过广泛优化的反馈和执行系统,C/C++通常是最有力的选择。而超高频策略会要求自定义硬件,例如 FPGA,交易所办公室,以及对核心/网络界面的调整。

3.科研体系

研究系统一般包括交互开发和自动脚本。前者一般是在一个 IDE中进行的,例如 Visual Studio, MatLab, R Studio。而后者则需要对大量的参数、数据进行大量的数值运算。这就要求我们选择一种能够直接测试代码的语言,并提供充分的性能来评价有着多个参数的策略。
目前,领域的代表性 IDE有微软的 Visual C++/C#,该系统包含了大量的调试工具、代码完成能力(" Intellisense")以及(经由数据库 ORM、 LINQ)的总体概览。MatLab是为许多数字线性代数和向量运算而设计的,但是采用了交互的控制台;R Studio,用成熟 IDE封装 R统计语言控制台; Linux Java和 C++的Eclipse IDE;此外还有半私有 IDE,比如 Anaconda Distribution,它包含了 Python上的 Spyder IDE。该版本包含了诸如 NumPy、 SciPy、sci-kit-learn以及 pandas等数据分析库,在一个交互(控制台)的环境中。
以上所有的语言都可以用于数字回测,且由于代码是在“背景”中进行的,因此并不需要使用GUI/IDE。在此阶段,我们首先要考虑的是执行的速度。如果回测的参数很大,C++之类的编译语言就会很有用。Python之类的解释性语言通常使用诸如 NumPy/pandas这样的高性能类库来进行测试,从而在一定程度上与编译器保持在同一个合理的竞争水平。最后,为了测试而选定的语言将取决于特定的算法要求和该语言中的库的数量。但是,在回测和学习环境中使用的语言可能与投资组合构建、风险管理和执行等方面的语言无关。

4.资产配置与风险管理

在零售算法的交易者中,证券组合构造和风险管理往往容易被忽略。这是一个很常见的错误。这些手段为保存资金提供了一种机制。他们不但会减少风险的投注,同时也会把交易本身的波动性降到最低,从而降低交易费用。
复杂的组合可能会对利润的品水平连贯性有很大的影响。建立一个稳健的策略非常简单,因为我们可以轻松地调整投资组合结构和风险管理人员来处理多种系统。所以,在设计一个算法的交易系统时,他们应当被视为一个重要的部分。
资产配置体系的任务是获得一套需要的业务,并生成一套最小化损失的真实交易集,同时维持对各类因素(如行业、资产类别、波动性等)的暴露,以及在不同的投资组合中进行最佳配置。
投资组合的构造一般可以被简单地归结为一个线性代数问题,例如矩阵分解,所以它的执行效率很大程度上取决于现有的线性代数。常用的类库有 uBLAS、 LAPACK和 C++的 NAG。MatLab还具有矩阵运算的广泛优化。Python使用 NumPy/SciPy做类似的运算。为了避免在交易系统中出现瓶颈,一个频繁调整的资产组合需要一个经过编译的矩阵来完成这个过程。
在算法交易系统中,风险管理也是非常关键的一环。风控部门尝试着预测资产组合中的过度波动与相关的效应,并分析其对交易资金的影响等。

5.执行系统

执行系统的任务是从证券组合构造和风险管理部件中接收筛选的交易信号,然后把它们传送给券商或者其它进入市场的工具。在大多数的零售业的算法交易策略中,这需要将 API或者 FIX与诸如交互经纪人这样的经纪商联系起来。在选择语言的时候,主要的考虑因素是 API的质量, API语言包装的可用性,执行的频率和期望的滑动点。
API质量是指其文件的良好程度、性能如何、是否要求单独的软件存取、还是能够以无头的方式创建一个网关(也就是没有 GUI)。大部分 API都有 C++和 Java界面。而 C#, Python, R, Excel和 MatLab的特定语言包装器的开发则由该语言的开发社区来决定。每个附加的插件(特别是 API封装)都会导致系统中的 bug,因此我们要经常对这些插件进行测试,并保证有效维护。
在算法的执行中,执行频率是最关键的。像 C++/Java这样的静态语言往往是最好的实现方法,但同时我们需要在开发时间、测试和维护上进行权衡。像 Python和 Perl这样的动态类型的语言通常都“足够快”。

6.体系结构规划与发展历程

以上对交易系统的各部件,其频率和数量需求进行了论述,但是尚未涉及系统的基本结构。在对特定语言进行更深入地探讨之前,我们先来探讨一下最优的体系结构。

1)绩效考量
在大部分的交易策略中,绩效是一个很重要的考量。在高频率策略中,这是最关键的要素。效能包含许多问题,例如运算法则的执行、网络时延、带宽、资料输入输出、并发/平行及扩充。以上各个方面都有大量的教材,因此本文仅简要地介绍一下。目前,我们将从其影响性能的角度来探讨体系结构和语言的选择。
C++, Java, Python, R和 MatLab都包含了为基础数据结构和算法工作而设计的高性能库。C++中有 Standard Template Library,而 Python中则有NumPy/SciPy。在这些库中可以发现一些常用的数学任务;编写新的执行口令并没有什么优势。
有一个例外是,当硬件架构要求高度定制,而某种算法正在大量使用专用扩展(例如,定制高速缓存)。但是,重造常常会耗费更多的时间去发展和优化其它的交易架构。
由于科研设备经常都在同一机器上,所以延迟常常是由执行系统造成的。在前一种情况下,执行路径上的多个点会出现延迟。为了更高速运行,执行人员需要密切地了解内核的优化和网络的传输。
在定量交易开发人员的工具包中,缓存是很有用的。缓存是指把频繁存取的资料储存在一种可供更高效能存取的方法,其代价是资料可能会出现停滞。一个常见的例子是,在 Web开发中,数据被从一个硬盘上的关联数据库中提取出来,然后放到内存中。随后的数据请求不会通过主数据库而是直接从刚刚的缓存数据中获取,因此整体的性能表现就会得到很大的改善。
高速缓存在处理事务时很有用。比如,可以将策略组合的目前状态保存在高速存储硬盘中直至一下一次重置,这样就不必在每次交易算法周期内重置清单。
但是,高速缓存并非完全无问题。首先,高速缓存的存储器是不稳定的,因此需要大量的基础架构来进行高速缓存的数据更新。另外一个问题是堆叠,也就是在非常高的负荷下执行多个新的高速缓存拷贝,因而造成级联失效。
运行时,执行人员必须清楚地了解在程序过程中如何分配内存。Java、 C#、 Python等新的语言标准都提供了自动的垃圾回收,即在对象超过一定的范围时,可以动态地分配内存。
垃圾收集在开发期间很有用,因为这样可以降低 bug和提高可读性。但是,在一些高频率的交易策略中,这种方法通常是次优的。Java中的高频交易策略可以通过调整垃圾回收和堆来实现,而C++没有提供本机内存回收器,所以必须将所有存储器的分布/重新分布都当作文件执行的一部分。尽管可能会产生悬空指针,但是在一些应用程序中,C++可以很好地控制对象在堆上的出现。在选定一门语言时,情务必了解垃圾回收程序的工作原理,并确定其可以对具体的用例进行修改。
在处理器速度停滞的情况下,并行化作为一种优化手段变得越来越重要。消费图像硬件(主要是在电子游戏中使用)的出现,促使了包括数以百计的核心图形处理单元(GPU)的发展。这种 GPU的价格目前是非常能令人接受的。像 Nvidia的 CUDA这样的先进架构,在学术界和金融领域都得到了广泛的应用。
这种 GPU的硬件一般仅应用在定量金融的研究领域。现在,大部分的现代语言都提供了并行/多线程的支持。因为所有的运算通常是相互独立的,所以可以很容易地对逆向测试仪进行优化。
在软件工程和运营方面的扩充意味着,系统能够处理不断增长的负荷,表现为要求越大、处理器利用率越高、内存分配越大。在算法交易中,当一种策略可以获得更多的资金而同时还能获得稳定的收益时,就可以进行扩张。如果交易技术可以在没有瓶颈的情况下支持更大的交易量和更高的延迟,则可以进行扩展。
执行人员难以预测瓶颈在何处发生,因此严格地记录,测试,分析和监控将会极大地促进系统的扩充。应当明确的是,除了语言之外,整个技术堆叠的可伸缩性。有些语言在特定的情况下表现得优于其它语言,但是没有哪一种语言比另外一种“更好”。

(未完待续)

评论

需要帮助?

试试AI小助手吧