1.3 用于金融的Python
前一小节介绍了科技在金融中发挥作用的一些领域:
- 金融行业中的科技成本;
- 作为新业务和创新业务引擎的科技;
- 作为金融行业进入门槛的科技;
- 不断提升的速度、频率和数据量;
- 实时分析的兴起。
本节,我们分析Python如何帮助你应对这些方面的多种挑战。不过首先让我从更为基础的方面——语言和语法——介绍用于金融的Python。
1.3.1 金融和Python语法
在金融环境中迈出使用Python第一步的大部分人都可能要攻克某个算法问题。这和想要解出微分方程、求取积分或者可视化某些数据的科学工作者类似。一般来说,在这一阶段,对正规开发过程、测试、文档或者部署没有太多的思考。然而,这一阶段似乎是人们特别容易爱上Python的时候,主要原因是Python的语法总体上和用于描述科学问题或者金融算法的数学语法相当接近。
我们可以通过一个简单的金融算法来说明这一现象——通过蒙特卡洛模拟方法估计欧式看涨期权的价值。我们将考虑Black-Scholes-Merton(BSM)模型(参见第3章),在这种模型中期权潜在风险遵循几何布朗运动。
假定我们使用如下数值化参数进行估值:
- 初始股票指数水平S0=100;
- 欧式看涨期权的行权价格K=105;
- 到期时间T=1年;
- 固定无风险短期利率r=5%;
- 固定波动率σ=20%。
在BSM模型中,到期指数水平是一个随机变量,由公式1-1给出,其中z是一个标准正态分布随机变量。
公式1-1 Black-Scholes-Merton(1973)到期指数水平
(1-1)
下面是蒙特卡洛估值过程的算法描述。
1.从标准正态分布中取得 I 个(伪)随机数 z(i ),i∈{1,2,…,I }。
2.为给定的 z (i ) 和公式1-1计算所有到期指数水平ST(i)。
3.计算到期时期权的所有内在价值hT(i)=max(ST(i )−K,0)。
4.通过公式1-2中给出的蒙特卡罗估算函数估计期权现值。
公式1-2 欧式期权的蒙特卡洛估算函数
(1-2)
现在,我们将这个问题和算法翻译为Python代码。读者可以使用IPython跟踪单独的步骤——但是在这一阶段实际上并不是必需的。
首先,我们从参数值开始。这真的很简单。
接下来是估值算法。这里,我们第一次使用NumPy,它使我们的第二项任务变得相当轻松。
第三步是打印结果。
输出可能是如下所示[4]:
有下面3个方面值得注意。
语法
Python语法与数学语法相当接近,例如,在参数赋值的方面。
**翻译
**
每条数学或者算法语句一般都可以翻译为单行Python代码。
向量化
NumPy的强项之一是紧凑的向量化语法,例如,允许在单一代码行中进行10万次计算。
这段代码可以用于IPython等交互式环境。但是,需要频繁重用的代码一般组织为所谓的模块(或者脚本),也就是带有.py后缀的Python(文本)文件。本例的这种模块如例1-1所示,可以保存为名为bsm_msc_euro.py的文件。
例1-1 欧式看涨期权的蒙特卡洛估值
这一小节中的简单算法示例说明Python的基本语法很适合为经典的科学语言二重奏——英语和数学——提供补充。在科学语言组合中添加Python似乎使其更加全面。我们现在拥有:
用于写作和谈论科学和金融等问题的英语;
用于简洁、精确地描述抽象特征、算法、复数等并为其建模的数学;
从技术上建立抽象特征、算法、复数等的模型并加以实现的Python。
数学和Python语法
几乎没有任何编程语言像Python这样接近数学语法。因此,数值算法很容易从数学表示翻译为Python实现。使用Python,可以在这些领域中高效地进行原型化、开发和代码维护。
在某些领域中,使用伪代码是常见的做法,从而引入了第4个语言家族成员。举个例子,伪代码的任务是以更技术性的方式表示金融算法,不但仍然接近于数学表示,而且和技术实现已经相当接近。除了算法本身,伪代码还考虑了计算机的工作原理。
采用这种方法一般是因为使用大部分编程语言时,技术实现和正式的数学表现形式距离相当“遥远”。大部分编程语言都必须包含许多只在技术上必要的元素,在数学和代码之间很难看到等价的元素。
时下,Python常常以伪代码方式使用,因为它的语法和数学很类似,而且技术“开销”可以控制到最低。这一点是通过该语言所体现的一些高层概念实现的,这些概念不仅有其优势,也带来了风险和其他代价。不过可以肯定,可以在需求出现的时候使用Python,从一开始就遵循其他语言可能需要的严格实现和编码方法。从这个意义上说,Python可以在两个世界中提供最佳的平衡:高层次的抽象和严格的实现。
1.3.2 Python的效率和生产率
从较高的层次看,使用Python的好处可以从3个维度衡量。
效率
Python如何更快地获得结果、节约成本、节约时间?
生产率
Python如何在相同的资源(人员、资产等)下完成更多的工作?
质量
Python能够让我们做哪些替代技术所不能做到的事情?
对这些特性的讨论当然不可能很全面。然而,可以将某些参数作为出发点。
在更短的时间里得到成果
Python效率较为明显的领域之一是交互式的数据分析。这些领域从IPython等有力工具和pandas之类的程序库获益良多。
考虑一位正在撰写硕士论文的金融专业学生,她对Google的股价感兴趣,想要分析5年的历史股价信息,以了解股价变动在这段时间内的波动性。她希望找到证据证明这种变动性与某些典型的模型假设相反,是随时间变动而决非固定。而且,结果应该进行可视化,主要的工作如下:
- 从网络上下载Google的股价数据;
- 计算收益率的滚动标准差(波动率);
- 绘制股价数据和结果图表。
这些任务很复杂,在不久之前还被认为是专业金融分析师才能完成的。而在今天,即使是金融专业的学生也可以轻松地对付这类问题。我们来看看具体的做法——此时还不用操心语法的细节(后续的章节中将对所有细节进行解释)。
首先,确保所有必要的库可用。
其次,读取数据(例如从Google网站)。
第三步,实现对波动率的必要分析。
最后一步,绘制结果图表。为了生成内联图表,我们使用IPython的“魔法”命令%matplotlib,加上inline选项。
图1-1展示了在IPython进行的这一简短交互会话所得到的图形化结果。用4行代码就足以完成金融分析中遇到的典型复杂任务:数据收集、复杂和重复的数学计算以及结果的可视化,几乎令人觉得不可思议。这个例子中可以看到,pandas使整个时间系列的处理变得就像浮点数上的数学运算那样容易。
将这个例子转换到专业的金融环境中,可以看出金融分析师们在应用提供高层次抽象的合适Python工具和库的时候,能够将焦点放在自身的领域上,而不用关心复杂的技术细节。分析师们可以快速反应,几乎实时提供宝贵的深刻见解,确保自己比竞争对手先行一步。这种效率的提高很容易转换为可度量的财务效果。
确保高性能
一般来说,Python的语法相当简洁,编码效率相对高是为人们所接受的说法。但是,由于Python本质上是解释型语言,因此存在一种偏见,认为Python对于金融学中的计算密集任务来说过于缓慢。确实,在某些特定的实现方法下,Python可能确实很慢,但是,它并不一定都那么缓慢——它可以在几乎任何应用领域中表现出高性能。理论上,人们至少可以找到3种提高性能的策略。
**范型
**
一般来说,Python可以用许多不同的方式得出相同的结果,但是这些方式的性能特性有相当大的区别;只要选择合适的方式(例如,特定的库),就可以显著地改善效果。
编译
现在,有许多高性能库提供重要函数的编译版本,或者将Python代码静态或者动态地(在运行时或者调用时)编译为机器代码,这种代码的速度要快好几个数量级;比较流行的高性能库有Cython和Numba等。
并行化
许多计算任务(特别是金融学中的计算任务)可以从并行执行中得到很大好处;这对Python来说不足为奇,可以轻松地实现。
使用Python实现高性能计算
Python本身不是一种高性能计算技术。但是,Python已经发展成为一种访问当前高性能技术的理想平台。在这个意义上,Python已经成为高性能计算的“黏合剂”语言。
后续的章节将详细介绍这3种技术。现在,我们打算坚持用简单而实际的例子介绍这3种技术。
金融分析中相当常见的任务之一是在大量数字上计算复杂的数学表达式。在这方面,Python本身就提供了所有必须的功能:
Python解释程序在本例中需要15秒时间来完成2500万次函数f的计算。
使用Numpy可以完成相同的任务,它提供了优化(也就是预先编译)的函数,处理这种基于数组的运算:
使用Numpy将执行时间大幅缩减到1.7秒。
甚至有一个库是专门用于此类任务的,这个库称作numexpr,得名于“数值表达式”(Numerical Expressions)。它编译表达式,改善NumPy通用功能的性能,例如,在执行期间避免数组在内存中复制:
使用这种更特殊的方法进一步将执行时间降低到1.2秒。而且,numexpr还内建并行执行单独运算的功能。这使我们能够使用一个CPU的所有可用线程:
本例中,利用2个核心、4个线程,执行时间进一步下降到0.5秒。总体的性能提升了30倍。特别要注意的是,这类改善不需要修改基本问题/算法,也不用了解任何有关编译和并行化问题的知识,即使是非专业人士也可以从较高的层次上去利用这种功能。当然,人们必须知道存在这些功能。
这个例子说明,Python提供了一些选项,更好地利用现有资源——也就是说,提高生产率。采用串行化技术,每秒可以完成2100万次计算,而并行化方法每秒可以计算将近4800万次——这只需要告诉Python使用所有可用CPU线程(而非仅使用一个线程)即可实现。
1.3.3 从原型化到生产
从执行速度的角度看,交互式分析的效率和性能当然是Python值得考虑的两个好处。在金融学中使用Python的另一个好处初看似乎比较细微;但是细看之下就会发现它本身是一个重要的战略因素。这就是以端到端(从原型化到生产)的方式使用Python的可能性。
当今全球金融机构的金融开发过程往往是一个分离的两步式过程。一方面,量化分析师(“quants”也称“宽客”)负责模型开发和技术原型化。他们喜欢使用MatLab和R等工具和环境实现快速、交互式的应用程序开发。在开发的这一阶段,性能、稳定性、异常管理、数据访问分离和分析等问题都不重要。人们的主要目标是一种概念验证或者原型,展现某种算法或者整个应用程序主要的必需功能。
一旦原型完成,IT部门中的开发人员接管工作,他们负责将现有原型代码翻译为可靠、易于维护和高性能的生产代码。这一阶段通常在用于满足生产性能的C++或者Java语言中有一个范型转换的过程。而且,正规的开发过程还要应用专业工具、版本控制等技术。
这种两步式方法通常会产生一些意外的结果。
效率低下
原型代码不能重用;算法必须实现两次;多余的工作消耗时间和资源。
多种技能集
不同部门展现不同的技能集合,使用不同的语言实现“相同的工作”。
遗留代码
代码必须以不同的语言存在和维护,往往使用不同的实现风格(例如,从架构的观点上看)。
另一方面,使用Python可以实现从最初的交互式原型化步骤到高可靠性、易于维护的生产代码的合理化端到端过程。不同部门之间的沟通变得更加简单,工作人员的培训也更为合理,只有一种主要语言覆盖金融应用构建的所有领域,还避免了在开发过程不同步骤中使用不同技术的低效和冗余性。总而言之,Python可以为金融应用开发和算法实现提供一致性的技术框架。