Python金融大数据分析 第2版

978-7-115-52133-0
作者: [德]伊夫·希尔皮斯科(Yves Hilpisch)
译者: 姚军
编辑: 武晓燕

图书目录:

详情

《Python金融大数据分析 第2版》分为5部分,共21章。第1部分介绍了Python在金融学中的应用,其内容涵盖了Python用于金融行业的原因、Python的基础架构和工具,以及Python在计量金融学中的一些具体入门实例;第2部分介绍了Python的基础知识以及Python中非常有名的库NumPy和pandas工具集,还介绍了面向对象编程;第3部分介绍金融数据科学的相关基本技术和方法,包括数据可视化、输入/输出操作和数学中与金融相关的知识等;第4部分介绍Python在算法交易上的应用,重点介绍常见算法,包括机器学习、深度神经网络等人工智能相关算法;第5部分讲解基于蒙特卡洛模拟开发期权及衍生品定价的应用,其内容涵盖了估值框架的介绍、金融模型的模拟、衍生品的估值、投资组合的估值等知识。 《Python金融大数据分析 第2版》本书适合对使用Python进行大数据分析、处理感兴趣的金融行业开发人员阅读。

图书摘要

版权信息

书名:Python金融大数据分析(第2版)

ISBN:978-7-115-52133-0

本书由人民邮电出版社发行数字版。版权所有,侵权必究。

您购买的人民邮电出版社电子书仅供您个人使用,未经授权,不得以任何方式复制和传播本书内容。

我们愿意相信读者具有这样的良知和觉悟,与我们共同保护知识产权。

如果购买者有侵权行为,我们可能对该用户实施包括但不限于关闭该帐号等维权措施,并可能追究法律责任。

著    [德]伊夫·希尔皮斯科(Yves Hilpisch)

译    姚 军

责任编辑 武晓燕

人民邮电出版社出版发行  北京市丰台区成寿寺路11号

邮编 100164  电子邮件 315@ptpress.com.cn

网址 http://www.ptpress.com.cn

读者服务热线:(010)81055410

反盗版热线:(010)81055315


Copyright © 2018 by O’Reilly Media, Inc.

Simplified Chinese Edition, jointly published by O’Reilly Media, Inc. and Posts & Telecom Press.,Ltd, 2018. Authorized translation of the English edition, 2018 O’Reilly Modia, Inc., the owner of all rights to publish and sell the same.

All rights reserved including the rights of reproduction in whole or in part in any form.

本书中文简体版由O’Reilly Media, Inc. 授权人民邮电出版社有限公司出版。未经出版者书面许可,对本书的任何部分不得以任何方式复制或抄袭。 版权所有,侵权必究。


本书分为5部分,共21章。第1部分介绍了Python在金融学中的应用,其内容涵盖了Python用于金融行业的原因、Python的基础架构和工具,以及Python在计量金融学中的一些具体入门实例;第2部分介绍了Python的基础知识以及Python中非常有名的库NumPy和pandas工具集,还介绍了面向对象编程;第3部分介绍金融数据科学的相关基本技术和方法,包括数据可视化、输入/输出操作和数学中与金融相关的知识等;第4部分介绍Python在算法交易上的应用,重点介绍常见算法,包括机器学习、深度神经网络等人工智能相关算法;第5部分讲解基于蒙特卡洛模拟开发期权及衍生品定价的应用,其内容涵盖了估值框架的介绍、金融模型的模拟、衍生品的估值、投资组合的估值等知识。

本书适合对使用Python进行大数据分析和处理感兴趣的金融行业开发人员阅读。


O’Reilly以“分享创新知识、改变世界”为己任。40多年来我们一直向企业、个人提供成功所必需之技能及思想,激励他们创新并做得更好。

O’Reilly业务的核心是独特的专家及创新者网络,众多专家及创新者通过我们分享知识。我们的在线学习(Online Learning)平台提供独家的直播培训、图书及视频,使客户更容易获取业务成功所需的专业知识。几十年来O’Reilly图书一直被视为学习开创未来之技术的权威资料。我们每年举办的诸多会议是活跃的技术聚会场所,来自各领域的专业人士在此建立联系,讨论最佳实践并发现可能影响技术行业未来的新趋势。

我们的客户渴望做出推动世界前进的创新之举,我们希望能助他们一臂之力。

“O’Reilly Radar博客有口皆碑。”

       ——Wired

“O’Reilly凭借一系列非凡想法(真希望当初我也想到了)建立了数百万美元的业务。”

       ——Business 2.0

“O’Reilly Conference是聚集关键思想领袖的绝对典范。”

       ——CRN

“一本O’Reilly的书就代表一个有用、有前途、需要学习的主题。”

       ——Irish Times

“Tim是位特立独行的商人,他不光放眼于最长远、最广阔的领域,并且切实地按照Yogi Berra的建议去做了:‘如果你在路上遇到岔路口,那就走小路。’回顾过去,Tim似乎每一次都选择了小路,而且有几次都是一闪即逝的机会,尽管大路也不错。”

       ——Linux Journal



近来,Python无疑是金融业的重要策略性技术平台之一。当我于2013年开始编写本书第1版时,仍然在许多演讲中不懈地介绍Python在金融方面相比其他语言及平台的竞争优势。到2018年年底,这已经不再是个问题:全世界的金融机构现在都尽最大努力利用Python及其强大的数据分析、可视化和机器学习程序库生态系统。在金融领域之外,Python还常常成为编程入门课程(例如计算机科学课程项目)选择的语言。

除了容易理解的语法和多重范型方法之外,形成这一局面的主要原因之一是,Python已经成为人工智能(AI)、机器学习(ML)和深度学习(DL)领域的“头等公民”。这些领域的许多流行的软件包和程序库都直接用Python(如ML所用的scikit-learn)编写,或者用Python包装器(例如DL所用的TensorFlow)。

金融本身正在进入一个新时代,这一发展有两个主要的推动力。首先是基本上所有金融数据都可以编程访问——一般来说,这种访问是实时的,也是催生“数据驱动金融”的原因。几十年前,大部分交易或者投资决策是由交易员和投资组合管理人推动的,这些人阅读报纸,或者通过私下交谈进行学习。此后出现了一些终端,可通过计算机和电子通信,将金融数据实时传递到交易员和投资组合管理人的桌面上。今天,即使是一分钟产生的海量金融数据,个人(或者团队)都无法应付。只有处理速度和计算能力与日俱增的机器,才能应对金融数据的容量和速度。这意味着,全球大部分股票交易量是由算法和计算机驱动的,而不是交易员。

第二个主要推动力是在金融中越来越重要的人工智能。越来越多的金融机构试图利用ML和DL算法改善运营,以及它们的交易及投资表现。2018年初,第一本关于“金融机器学习”的专著出版,强调了这种趋势。毫无疑问,还会有更多的图书涌现。这导致了可以称为“人工智能优先金融学”的现象,用可参数化的ML及DL算法代替传统的金融理论。传统的金融理论可能非常优雅,但在数据驱动、人工智能优先的金融学实践中不再有太大的用处了。

面对这一金融时代的挑战,Python是合适的编程语言和生态系统。本书涵盖有监督学习和无监督学习的基本ML算法(以及深度神经网络),但焦点是Python的数据处理和分析能力。想要全面叙述AI当前和未来在金融中的重要性,需要一整本书的篇幅。不过,大部分AI、ML和DL需要大量的数据,因此无论如何应该首先掌握数据驱动金融学。

本书第2版更多的是一次升级,而非更新。例如,这一版增加了关于算法交易的一整个部分(第4部分)。这一主题最近在金融业变得相当重要,在散户中也很受欢迎。本版还增加了一个入门部分(第2部分),介绍Python基本编程和数据分析,这些知识将为本书的后续几个部分奠定基础。另一方面,第1版的某些章节完全删除了。例如,关于Web技术和对应库(如Flask)的部分删除,因为现在已经有专门介绍这些知识的图书。

在第2版中,我力图涵盖更多金融相关主题,聚焦于对金融数据科学、算法交易和计算金融学特别有用的Python技术。和第1版中一样,我采用的是实用方法,实现和图示先于理论细节,通常将重点放在整体上,而不是某些类、方法或者晦涩难懂的函数参数化选项。

描述完第2版的基本方法之后,我还必须强调,这本书既不是介绍Python编程,也不是介绍一般金融知识的图书。在这两个方面,都有大量出色的知识来源。本书定位于这两个激动人心的领域相互交叉的方面,并假定读者有一定的编程(不一定是Python)和金融背景。这些读者将学习把Python及其生态系统应用于金融领域的方法。

Jupyter Notebook和本书配套代码可以通过Quants平台访问和执行。读者可以在Python Quants官网免费注册。

我的公司(Python Quants)和本人还提供了许多帮助读者掌握Python金融数据科学、人工智能、算法交易和计算金融学的资源。你可以从访问如下站点开始:

在我们前几年所提供的服务中,最令我自豪的是“Python算法交易认证计划”(Certificate Program in Python for Algorithmic Trading)。它提供了超过150小时的实时和录制教程,超过1200页的文档,5000行以上的Python代码以及50多个Jupyter Notebook。这一课程每年开设多次,每一次我们都进行更新和改进。这些在线课程是同类中的首创。通过与萨尔州应用技术大学的合作,成功完成该课程者将获得正式的大学文凭。

除此之外,我最近还启动了新的“The AI Machine”项目和公司,以实现自动化算法交易策略部署的标准化。我们希望通过这一项目,以系统化、可伸缩的方式实施多年来在这个领域传授的方法,以便利用算法交易领域的许多机遇。近来,此类项目即便对于像我们这样规模较小的团队来说也是可能的,这应该归功于Python以及数据驱动和人工智能优先金融学。

我以如下的话作为第1版前言的结束:

对于Python确立金融行业中重要技术地位这一事实,我确实感到很兴奋。我敢肯定,它在未来将会起到更重要的作用,例如在衍生品和风险分析或者高性能计算领域中。我希望本书能够帮助专业人士、研究人员和学生在面对这一迷人领域中的挑战时,最大限度地利用Python。

当我在2014年写下上述文字时,还无法预测Python在金融学中将会变得多么重要。2018年,我因为自己的期许和希望已经被大大超越而感到快乐。也许,本书的第1版对此起到了小小的作用。无论如何,读者都应该感谢不懈努力的开源开发者们,如果没有他们,就不可能书写Python的成功故事。


 

这个元素表示提示或者建议。


 

这个元素表示一般注解。



 

这个元素表示警告或者注意事项。


补充材料(特别是Jupyter Notebook和Python脚本/模块)可以从Python Quants下载。

本书的目的是帮助读者完成工作。一般而言,你可以在你的程序和文档中使用本书中的代码,而且也没有必要取得我们的许可。但是,如果你要复制的是核心代码,则需要和我们打个招呼。例如,你可以在无须获取我们许可的情况下,在程序中使用本书中的多个代码块。但是,销售或分发O’Reilly图书中的代码则需要取得我们的许可。通过引用本书中的示例代码来回答问题时,不需要事先获得我们的许可。但是,如果你的产品文档中融合了本书中的大量示例代码,则需要取得我们的许可。

在引用本书中的代码示例时,如果能列出本书英文原书的属性信息是最好不过(但不是必需的)。属性信息通常包括书名、作者、出版社和ISBN。例如:“Python for Finance, 2nd Edition, by Yves Hilpisch (O’Reilly). Copyright 2019 Yves Hilpisch, 978-1-492-02433-0.”

在使用书中的代码时,如果不确定是否属于正常使用,或是否超出了我们的许可,请通过permissions@oreilly.com与我们联系。

Safari(原Safari Books Online)是供企业、政府、教育工作者和个人使用的会员制培训与参考平台。

会员有权访问来自250个出版商(包括O’Reilly Media、Harvard Business Review、Prentice Hall Professional、Addison-Wesley Professional、Microsoft Press、Sams、Que、Peachpit Press、Adobe、Focal Press、Cisco Press、John Wiley & Sons、Syngress、Morgan Kaufmann、IBM Redbooks、Packt、Adobe Press、FT Press、Apress、Manning、New Riders、McGraw-Hill、Jones & Bartlett和Course Technology)、数以千计的图书、培训视频、学习路径、交互教程和推荐书目。

更多信息请访问O’Reilly官网。

如果你想就本书发表评论或有任何疑问,敬请联系出版社:

美国:

O’Reilly Media. Inc.

1005 Gravenstein Highway North

Sebastopol, CA 95472

中国:

北京市西城区西直门南大街2号成铭大厦C座807室(100035)

奥莱利技术咨询(北京)有限公司

我们还为本书建立了一个网页(官方网站),其中包含了勘误表、示例和其他额外的信息。

关于本书的技术性问题或建议,请发邮件到:bookquestions@ oreilly.com

欢迎登录我们的网站,查看更多我们的图书、课程、会议和最新动态等信息。

我要感谢所有为本书的实现提供帮助的人,特别是O’Reilly的团队,他们在许多方面改进了我的手稿。感谢审稿人休·布朗(Hugh Brown)和杰克·万托布拉斯(Jake VanderPlas),本书从他们有价值的反馈和许多建议中获益匪浅。余下的任何错误责任当然在我。

迈克尔·施韦德(Michael Schwed)曾与我紧密协作十多年的时间,值得我特别感谢。多年以来,我已经从他的工作、支持和Python技巧中得到多方面的好处。

我还要感谢Refinitiv公司(前Thomson Reuters)的詹森·拉姆晶达尼(Jason Ramchandani)和豪尔赫·桑托斯(Jorge Santos),他们不仅持续支持我的工作,还为开放源码社区做出了贡献。

和第1版一样,本版也从我数年来参加的数十次“Python金融”讨论以及数百小时的“Python金融”培训中得到很大的益处。在许多情况下,来自参与者的反馈有助于改进我的培训材料,这些材料往往最终成为本书中的某个章节。

本书第1版的写作花费了大约一年的时间。总体上,编写和升级第2版也花了大约一年,这比我的预期要长一些,主要的原因是为了这个话题我经常忙于旅行和商务演讲。

写作需要许多独处的时间,无法与家人共度。因此,我要感谢桑德拉、莉丽、亨利、阿道夫、佩特拉和海因茨的理解和支持——不仅仅是在编写本书的时候。

和第1版一样,我将本书的第2版献给我可爱、坚强且富于同情心的妻子桑德拉。多年以来,她赋予家庭新的意义。感谢你。

Yves

德国萨尔州,2018年11月


本书由异步社区出品,社区(https://www.epubit.com/)为您提供相关资源和后续服务。

本书提供如下资源:

要获得以上配套资源,请在异步社区本书页面中点击,跳转到下载界面,按提示进行操作即可。注意:为保证购书读者的权益,该操作会给出相关提示,要求输入提取码进行验证。

如果您是教师,希望获得教学配套资源,请在社区本书页面中直接联系本书的责任编辑。

作者和编辑尽最大努力来确保书中内容的准确性,但难免会存在疏漏。欢迎您将发现的问题反馈给我们,帮助我们提升图书的质量。

当您发现错误时,请登录异步社区,按书名搜索,进入本书页面,点击“提交勘误”,输入勘误信息,点击“提交”按钮即可。本书的作者和编辑会对您提交的勘误进行审核,确认并接受后,您将获赠异步社区的100积分。积分可用于在异步社区兑换优惠券、样书或奖品。

我们的联系邮箱是contact@epubit.com.cn。

如果您对本书有任何疑问或建议,请您发邮件给我们,并请在邮件标题中注明本书书名,以便我们更高效地做出反馈。

如果您有兴趣出版图书、录制教学视频,或者参与图书翻译、技术审校等工作,可以发邮件给我们;有意出版图书的作者也可以到异步社区在线提交投稿(直接访问www.epubit.com/selfpublish/submission即可)。

如果您是学校、培训机构或企业,想批量购买本书或异步社区出版的其他图书,也可以发邮件给我们。

如果您在网上发现有针对异步社区出品图书的各种形式的盗版行为,包括对图书全部或部分内容的非授权传播,请您将怀疑有侵权行为的链接发邮件给我们。您的这一举动是对作者权益的保护,也是我们持续为您提供有价值的内容的动力之源。

“异步社区”是人民邮电出版社旗下IT专业图书社区,致力于出版精品IT技术图书和相关学习产品,为作译者提供优质出版服务。异步社区创办于2015年8月,提供大量精品IT技术图书和电子书,以及高品质技术文章和视频课程。更多详情请访问异步社区官网https://www.epubit.com。

“异步图书”是由异步社区编辑团队策划出版的精品IT专业图书的品牌,依托于人民邮电出版社近30年的计算机图书出版积累和专业编辑团队,相关图书在封面上印有异步图书的LOGO。异步图书的出版领域包括软件开发、大数据、AI、测试、前端、网络技术等。

异步社区

微信服务号


这一部分介绍Python的金融应用,包括两章。


银行本质上是技术公司。

——胡戈·班齐格

Python是一种高级的多用途编程语言,广泛用于各种非技术和技术领域。在Python网站上,你可以找到如下行动纲领:

Python是一种具备动态语义、面向对象的解释型高级编程语言。它的高级内建数据结构与动态类型及动态绑定相结合,使其在快速应用开发上极具吸引力,也适合于作为脚本或者“黏合剂”语言,将现有组件连接起来。Python简单、易学的语法强调可读性,因此可以降低程序维护成本。Python支持模块和软件包,鼓励模块化和代码重用。Python解释程序和大量标准库可以以源代码或者二进制的形式免费取得,它们用于所有主要平台,并且可以随意分发。

上述纲领很好地描述了Python成为当今主要编程语言之一的原因。当前,在学校、Web公司、大型企业和金融机构以及任何科学领域,都有初学者和熟练的专业开发人员在使用Python。

Python有如下特征。

开放源码

Python和大部分可用的支持库及工具都是开源的,通常都有相当灵活和开放的许可证。

解释型

CPython参考实现是该语言的一个解释程序,在运行时它将Python代码翻译为可执行字节代码。

多重范型

Python支持不同的编程和实现范型,例如面向对象和命令式、函数式或者过程式编程。

多用途

Python可以用于快速、交互式代码开发,也可以用于构建大型应用程序;它可以用于低级系统操作,也可以承担高级分析任务。

跨平台

Python可用于大部分重要的操作系统,如Windows、Linux和Mac OS;它用于构建桌面应用和Web应用;可以在庞大的群集和强大的服务器上使用,也可以在树莓派这样的小设备上运行。

动态类型

Python中的类型通常在运行时推知,而不像大部分编译语言那样静态声明。

缩进感知

和大部分其他编程语言不同,Python使用缩进标记代码块,缩进标记代替了圆括号、方括号或者分号。

垃圾收集

Python具有自动垃圾收集机制,避免程序员来管理内存。

关于Python语法及其意义,Python增强提案20——即所谓的“Python之禅”——提供了重要的指导方针。每个交互shell都可以用命令import this访问它:

In [1]: import this
        The Zen of Python, by Tim Peters

        Beautiful is better than ugly.
        Explicit is better than implicit.
        Simple is better than complex.
        Complex is better than complicated.
        Flat is better than nested.
        Sparse is better than dense.
        Readability counts.
        Special cases aren't special enough to break the rules.
        Although practicality beats purity.
        Errors should never pass silently.
        Unless explicitly silenced.
        In the face of ambiguity, refuse the temptation to guess.
        There should be one-- and preferably only one --obvious way to do it.
        Although that way may not be obvious at first unless you're Dutch.
        Now is better than never.
        Although never is often better than *right* now.
        If the implementation is hard to explain, it's a bad idea.
        If the implementation is easy to explain, it may be a good idea.
        Namespaces are one honking great idea -- let's do more of those!

Python对于某些人来说可能还是个新事物,但是它已经出现了很长时间。实际上,早在20世纪80年代,荷兰人吉多·范·罗苏姆(Guido van Rossum)就开始了开发工作。他现在仍然活跃在Python开发中,被Python社区授予“仁慈独裁者”的称号。2018年7月,罗苏姆在数十年积极推动Python核心开发工作之后让位。下面是Python开发的里程碑:

值得注意的是,在开发之中有两个可用的主要版本,更重要的是,它们从2008年起并行使用,这有时候令Python初学者感到困惑。到本书编著之时,这种情况可能还将持续一段时间,因为仍有大量可用和生产代码是用Python 2.6/2.7编写的。本书第1版基于2.7.x版本,但第2版将全部使用Python 3.7。

Python作为一个生态系统,而不仅是一门编程语言,其主要特征是有大量可用的库和工具。这些库和工具通常必须在需要(例如,绘图库)时导入或者作为单独的系统进程(例如,Python交互开发环境)启动。导入意味着使某个库可用于当前命名空间和当前Python解释程序进程。

Python本身自带了一组大型的程序库和模块,它们叫作Python标准库,该标准库在不同方面增强了基本解释程序。例如,基本数学计算可以在不做任何导入的情况下完成,而更专业的数学函数必须通过math模块导入:

In [2]: 100 * 2.5 + 50
Out[2]: 300.0

In [3]: log(1)❶

        --------------------------------------------------------------
        NameError                      Traceback (most recent call last)
        <ipython-input-3-74f22a2fd43b> in <module>
        ----> 1 log(1)❶

        NameError: name 'log' is not defined

In [4]: import math ❷

In [5]: math.log(1)❷
Out[5]: 0.0

❶ 没有进一步导入,就会发生错误。

❷ 导入math模块后,可以执行计算。

在任何安装中math都是可用的标准Python库,但是还有许多库是可选安装的,它们可以通过和标准模块相同的方式使用。这些库来自不同的(Web)来源。然而,通常建议使用某种Python程序包管理器,确保所有库相互一致(这个主题的更多内容参见第2章)。

目前为止介绍的代码示例都使用Python交互式环境:IPython和Jupyter。它们可能是本书写作时最广泛使用的Python交互式开发环境之一。虽然IPython刚开始出现时只是一个增强的shell,但是现在它已经有了集成开发环境(IDE)的许多典型特性(例如,支持性能分析和调试)。IPython中缺乏Vim(也可与IPython集成)等高级文本/代码编辑器所提供的功能,因此,将IPython与某种文本/代码编辑器组合使用、组成Python开发过程基本工具集的情况很常见。

IPyhon从许多方面增强了标准交互式shell。它提供了改进的命令行历史功能,并且能够进行简单的对象检查。例如,在函数名称后添加一个?就可以打印函数的帮助文本(添加??将提供更多信息)。

IPython最初有两个流行版本:一个shell版本和一个基于浏览器的版本(Notebook)。Notebook变体非常实用和流行,从而演变为一个独立的语言无关的项目Jupyter。考虑到它的背景,Jupyter Notebook继承了大部分IPython的有益特性也就不足为奇了,它还提供了更多的新功能,例如可视化。

使用IPython的更多细节请参见VanderPlas(2016版,第1章)。

Python不仅对专业软件开发人员有很大的吸引力,临时开发人员、领域专家和科研开发人员也使用它。

专业软件开发人员寻求高效构建大型应用程序所需的一切工具。Python支持几乎所有编程范型,有强大的开发工具。从理论上说,Python可以应对任何工作。这些类型的用户通常构建自己的框架和类,也依靠基础的Python和科学栈进行工作,并且尽最大的努力利用生态系统。

科研开发人员和领域专家通常频繁使用某些库和框架,构建他们长年改进和优化的应用程序,并且根据特定的需求调整生态系统。这组用户通常参与较长的交互式会话,快速建立新代码原型,并探索和可视化其研究及领域数据集。

临时开发人员喜欢在确定Python具有优势的特定问题上使用Python。例如,访问Matplotlib的展示页面,复制Matplotlib提供的某一段可视化代码,根据特殊需求调整这些代码等。

Python用户还有另一个重要的群体:编程入门者,也就是刚刚开始编程的人。现在,Python在大学、专业院校甚至中小学校中已经成为向学生介绍编程的流行语言[1]。这种现象的主要原因之一是其基本语法即使对于非开发人员也很容易学习和理解。此外,Python支持几乎所有编程风格[2]

某些库的集合被统称为科学栈(Scientific Stack),其中包括以下程序库。

NumPy

NumPy提供多维数组对象,以存储同构或者异构数据;它还提供操作这一数组对象的优化函数/方法。

SciPy

SciPy是子库和函数的集合,它可以实现科学或者金融中常常用到的重要标准功能;例如,你可以找到3次样条插值和数值积分的函数。

Matplotlib

Matplotlib是非常流行的Python绘图和可视化库,提供2D和3D可视化功能。

pandas

pandas在NumPy基础上构建,可提供更丰富的时间序列和表格数据的管理与分析;它与Matplotlib在绘图上、与PyTables在数据存储和读取上紧密集成。

scikit-learn

scikit-learn是流行的机器学习(ML)程序库,为许多不同的ML算法(如估值、分类或者聚类)提供统一的应用编程接口(API)。

PyTables

PyTables是流行的HDF5数据存储库封装器;这个库可实现基于层次数据库/文件格式的优化磁盘I/O操作。

根据特定的领域或问题,科学栈可以通过更多的库进行扩展,这些库多半在一个或者多个上述的基本库基础上构建。但是,最小公分母(或称基本组成部分)通常是NumPy ndarray类(见第4章)和pandas DataFrame类(见第5章)。

仅从编程语言来讲,有许多其他语言在语法和简洁性上可与Python比肩。例如,Ruby也是相当流行的语言,可与Python相提并论。在该语言的网站上,你可以找到如下的描述:

一种动态的开放源码编程语言,重视简洁性和效率。它具备简洁的语法,阅读自然、易于编写。

大部分Python使用者可能也赞成用相同的陈述描述Python本身。但是,对于许多Python用户而言,它与Ruby等同样具有吸引力的语言之间的区别在于科学栈。这使Python不仅是优秀、简洁的语言,还可以代替Matlab或者R等领域专用语言和工具集。此外,它默认提供各种人员(如熟练的Web开发人员或者系统管理员)所需要的任何功能。Python还擅长与R等领域特定语言交互,因此,你所要做的决策通常不是“用Python还是其他语言?”,而是以哪一种语言为主。

现在,我们对Python已经有了大致的认识,接下来简短地介绍一下科技在金融中的作用就很有意义了。这将使我们更好地评判Python在金融行业中已经承担的任务,更重要的是,还可以评判未来承担的任务。

在某种意义上,科技对于金融机构(例如与生物技术公司相比)或者财务部门(与其他企业职能部门相比,如后勤)没有什么特别的作用。然而,近年来,在创新和监管的刺激下,银行和其他金融机构(如对冲基金)越来越多地发展成为技术公司而不仅仅是金融中介机构。科技成为了全球几乎所有金融机构的重要资产,具备导致竞争优势和劣势的潜力。某些背景信息可以解释这种发展的原因。

银行和金融机构共同组成了每年在科技上投入最多的行业。因此,下面的陈述不仅说明科技对金融行业的重要性,也说明了金融行业对科技的重要性:

美国马萨诸塞州弗雷明汉,2018年6月14日——根据国际数据公司(IDC)的一系列“金融服务IT开销指南”称,全球金融服务公司在信息科技(IT)上的开销将从2018年的4400亿美元增长到2021年的近5000亿美元。

——IDC

特别是,银行和其他金融机构正在参与业务及运营模式数字化的竞争:

2017年,北美地区银行在新科技上的开销高达199亿美元。

银行开发当前系统并致力于新的技术解决方案,以增强其在全球市场上的竞争力,吸引对新的网络和移动科技感兴趣的客户。对于为银行业提供新思路和软件解决方案的全球金融科技公司来说,这是一个巨大的机遇。

——Statista

当今的大型跨国银行通常雇佣数千名开发人员,以维护现有系统并构建新系统。具有大量科技需求的大型投资银行每年的科技预算往往达到数十亿美元。

科技发展对金融行业的创新和效率增进也有贡献。通常,这一领域的项目统称为“数字化项目”:

金融服务业在过去数年中已经历了科技先导的彻底变革。许多高管期望IT部门改进效率,促进游戏规则的创新——同时降低成本,继续支持遗留系统。与此同时,金融科技初创企业正在逐步蚕食原有市场,提出对客户友好的解决方案,这些方案是从头开始设计的,不受遗留系统的阻碍。

——普华永道第19次年度全球CEO调查报告(2016年)

效率提高的副作用之一就是,金融机构往往必须在更为复杂的产品或者交易中寻求竞争优势。这当然会使风险增大,并使风险管理、监控和监管越来越困难。2007年和2008年的金融危机说明了这些发展带来的潜在危险。同样,“算法和计算机失控”也给金融市场带来潜在的风险。2010年5月的所谓“闪电崩盘”事件戏剧性地展现了上述风险,自动化卖出导致某些股票和股票指数在当日大幅度下跌。本书第4部分将介绍与金融工具算法交易相关的内容。

一方面,在其他条件不变的情况下,随着时间的推移,科技的进步会降低成本。另一方面,金融机构持续在科技上投入巨资,以增大市场份额、保持自身地位。在今天的金融市场上取得一席之地往往需要在科技和熟练人员上大规模投资。考虑衍生品分析领域的一个例子:

在整个软件生命期中,采用内部OTC(衍生品)定价策略的公司仅在一个完整的衍生品库的构建、维护和改进上就需要投入2500万~3600万美元。

——Ding 2010

构建一个完善的衍生品分析库不仅成本高昂和费时,而且需要有足够的专业人士来进行这项工作。这些专业人士必须有正确的工具和技术,才能完成相应的任务。随着Python生态系统的发展,与10年前相比,这些工作变得更加高效,相关的成本也有了显著的下降。第5部分介绍衍生品分析,仅用Python及标准库就构建了一个规模虽小却强大且灵活的衍生品定价库。

下面,我们引用另一段美国长期资本管理公司(LTCM)的陈述,以进一步支持关于科技和人才的观点。LTCM曾是最受尊敬的计量对冲基金,但是在20世纪90年代末破产:

Meriwether在最新型计算机系统上花费了2000万美元,并雇用一个由一流金融工程师成的团队在LTCM操纵该系统,他们在康涅狄格州的格林尼治开始工作。这是行业级别的风险管理。

——Patterson 2010

Meriwether花费数百万美元才能得到的计算能力,在今天只需要几千美元就能实现。第2章介绍了在云中建立交互式金融分析、应用开发和Python部署的方法。这种专业基础设施每月的起始费用仅为几美元。另一方面,大型金融机构的交易、定价和风险管理已经变得非常复杂,导致现在必须部署具有数万个计算核心的IT基础架构。

金融行业有一个方面非常受科技进步的影响:金融交易决策和执行的速度及频率。Lewis最近的著作(2014)生动而详细地描述了所谓的“闪电交易”——也就是以可能的最高速度进行的交易。

一方面,可用数据的时间标度越来越小,使实时反应成为必需的能力。另一方面,交易的速度和频率的提高使数据量进一步增大。这两方面相互补充,推动了金融交易平均时间标度的系统性下降。这种趋势在10年前就已经开始:

复兴资本公司的“大奖章”基金在2008年获得了80%的惊人增长率,它以闪电般速度的计算机抓住了市场极端活跃的机会。Jim Simons是当年世界盈利最高的对冲基金管理人,收入达到25亿美元。

——Patterson 2010

单只股票30年的每日股价数据大致包含7500个报价。这类数据是大部分现代金融理论的基础。例如,现代投资组合理论(MPT)、资本定价模型(CAPM)和风险价值(VaR)等理论都以每日股价数据为基础。

相比之下,苹果公司(AAPL)典型交易日报价次数大约为15000——两倍于30年日终报价的数量(参见1.4节的例子)。这带来了许多挑战。

数据处理

只考虑和处理股票或者其他金融工具的日终报价是不够的。在每周的7天、每天的24小时内,某些金融工具上发生的事情“太多了”。

分析速度

决策往往必须在几毫秒甚至更短的时间内做出,有必要构建独自的分析能力工具,并实时分析大量数据。

理论基础

虽然传统金融理论和概念远称不上完美,但是它们经受了时间的考验(有些时候受到排斥);对于毫秒级计量能力很重要的今天,仍然缺乏在很长时间内证明是稳定的一致性概念和理论。

总体上,上述挑战都只能由现代科技应对。令人有些惊讶的是,缺乏一致性理论的问题也常常通过技术方法处理。在这种情况下,高速算法利用的是市场微观结构要素(例如,订单流、买卖价差),而不依赖于某种金融推理方法。

金融行业中有一个学科的重要性正在强劲增长:金融和数据分析。这种现象与行业中速度、频率和数据率飞速增长有紧密的关系。实际上,实时分析可以视为行业对这种趋势的反应。

粗略地讲,“金融和数据分析”指的是将应用软件、科技,与(可能是先进的)算法、数据收集、数据处理及分析方法相结合,以获得深刻的洞察力、做出决策或者满足监管需求的学科。这类分析的例子包括银行零售部门中某个金融产品定价结构的变化对销售情况影响的估算。另一个例子是投资银行衍生品复杂投资组合信用价值调整(CVA)的大规模隔夜计算。

金融机构在这种环境下主要面对两种挑战。

大数据

在“大数据”这一术语出现之前,银行和其他金融机构就必须处理海量数据。然而,单一分析任务所处理的数据量随着时间的推移而有了很大的增长,从而要求计算能力有所提高并有更大的内存与存储能力。

实时经济

过去,决策者只能依赖结构化的定期计划、决策和风险管理过程,而今天决策者面对的是实时完成这些任务的需求。过去在后台通过隔夜批量运行可以完成的任务,现在已经转向前台实时执行。

同样,人们可以观察到科技和金融/商业发展之间的相互作用。一方面,市场上出现了通过现代科技的应用不断改进分析方法的速度和效率的需求。另一方面,科技的进步使几年甚至几个月之前认为不可能(或者由于预算约束而不可行)的新分析方法成为可能。

分析领域的一个重要趋势是利用中央处理单元(CPU)的并行结构和通用计算图形处理单元(GPGPU)的大规模并行结构。现在的GPGPU往往有1000多个计算核心,有时候有必要彻底反思并行性对不同算法的意义。用户通常必须学习新的范型和技术才能利用这种硬件,这仍是障碍。

1.2节介绍了科技在金融中发挥作用的一些领域:

本节,我们分析Python如何帮助你应对这些方面的多种挑战。不过首先让我从更为基础的方面——语言和语法介绍用于金融的Python。

在金融环境中迈出使用Python第一步的大部分人都可能要攻克某个算法问题。这和想要解出微分方程、求取积分或者可视化某些数据的科学工作者类似。一般来说,在这一阶段,对正规开发过程、测试、文档或者部署没有太多的要求。然而,这一阶段似乎是人们特别容易爱上Python的时候,主要原因是Python的语法总体上和用于描述科学问题或者金融算法的数学语法相当接近。

我们可以通过一个简单的金融算法——通过蒙特卡洛模拟方法估计欧式看涨期权的价值来说明这一现象。我们将考虑Black-Scholes-Merton(BSM)模型,在这种模型中期权的潜在风险遵循几何布朗运动。

假定我们使用以下数值化参数进行估值:

在BSM模型中,到期指数水平是一个随机变量,由公式1-1给出,其中z是一个标准正态分布随机变量。

公式1-1 Black-Scholes-Merton(1973)到期指数水平

下面是蒙特卡洛估值过程的算法描述。

(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 欧式期权的蒙特卡洛估算函数

现在,我们需要将这个问题和算法翻译为Python代码。下面的代码将实现一些必要的步骤。

In [6]: import math
        import numpy as np ❶
 
In [7]: S0 = 100. ❷
        K = 105. ❷
        T = 1.0 ❷
        r = 0.05 ❷
        sigma = 0.2 ❷
 
In [8]: I = 100000 ❷
 
In [9]: np.random.seed(1000) ❸
In [10]: z = np.random.standard_normal(I) ❹
 
In [11]: ST = S0 * np.exp((r - sigma ** 2 / 2) * T + sigma * math.sqrt(T) * z) ❺
 
In [12]: hT = np.maximum(ST - K, 0) ❻
 
In [13]: C0 = math.exp(-r * T) * np.mean(hT) ❼
 
In [14]: print('Value of the European call option: {:5.3f}.'.format(C0)) ❽
        Value of the European call option: 8.019.

❶ NumPy在这里作为主程序包使用。

❷ 定义模型并模拟参数值。

❸ 随机数生成器种子值固定。

❹ 提取标准正态分布随机数。

❺ 模拟期末价值。

❻ 计算期权到期收益。

❼ 计算蒙特卡洛估算函数。

❽ 打印输出估算结果。

以下3个方面值得注意。

语法

Python语法与数学语法相当接近,例如参数赋值的方面。

翻译

每条数学或者算法语句一般都可以翻译为单行Python代码。

向量化

NumPy的强项之一是紧凑的向量化语法,例如,允许在单一代码行中进行10万次计算。

这段代码可以用于IPython或Jupyter Notebook等交互式环境。但是,需要频繁重用的代码一般组织为所谓的模块(或者脚本),也就是带有.py后缀的Python(文本)文件。本例的模块如例1-1所示,可以将其保存为名为bsm_msc_euro.py的文件。

例1-1 欧式看涨期权的蒙特卡洛估值

#
# Monte Carlo valuation of European call option
# in Black-Scholes-Merton model
# bsm_mcs_euro.py
#
# Python for Finance, 2nd ed.
# (c) Dr. Yves J. Hilpisch
#
import math
import numpy as np

# Parameter Values
S0 = 100. # initial index level
K = 105. # strike price
T = 1.0 # time-to-maturity
r = 0.05 # riskless short rate
sigma = 0.2 # volatility

I = 100000 # number of simulations

# Valuation Algorithm
z = np.random.standard_normal(I) # pseudo-random numbers
# index values at maturity
ST = S0 * np.exp((r - 0.5 * sigma ** 2) * T + sigma * math.sqrt(T) * z)
hT = np.maximum(ST - K, 0) # payoff at maturity
C0 = math.exp(-r * T) * np.mean(hT) # Monte Carlo estimator

# Result Output
print('Value of the European call option %5.3f.' % C0)

这一小节中的简单算法示例说明,Python的基本语法很适合为经典的科学语言二重奏——英语和数学来提供补充。在科学语言组合中添加Python能使其更加全面。我们现在拥有:

 

数学和Python语法

几乎没有任何编程语言像Python这样接近数学语法。因此,数值算法很容易从数学表示翻译为Python实现。通过Python,我们可以在这些领域中高效地进行原型化、开发和代码维护。

在某些领域中,使用伪代码是常见的做法,这引入了第 4 个语言家族成员。举个例子,伪代码的任务是以更技术性的方式表示金融算法,不但与数学表示接近,而且还接近于技术实现。除了算法本身,伪代码还考虑了计算机的工作原理。

采用这种方法一般是因为,使用大部分编程语言时,技术实现和正式的数学表现形式的距离相当“遥远”。大部分编程语言都必须包含许多只在技术上需要的元素,但在数学和代码中很难看到等价的元素。

时下,Python常常以伪代码的方式被使用,因为它的语法和数学很类似,而且技术“开销”可以控制到最低。这一点是通过该语言所体现的一些高层概念实现的,这些概念不仅有其优势,也带来了风险和其他代价。不过可以肯定,我们可在需求出现的时候使用Python,从一开始就遵循其他语言可能需要的严格实现和编码方法。从这个意义上说,Python可以在两个世界:高层次的抽象和严格的实现中提供最佳的平衡。

从较高的层次看,使用Python的好处可以从以下3个维度衡量。

效率

Python如何更快地获得结果、节约成本、节约时间?

生产率

Python如何在相同的资源(人员、资产等)下完成更多的工作?

质量

Python能够让我们做哪些替代技术所不能做到的事情?

对这些特性的讨论当然不可能很全面。然而,可以将某些特性作为出发点。

1.在更短的时间里得到成果

Python效率较为明显的领域之一是交互式的数据分析。这些领域从IPython、Jupyter Notebook等有力工具和pandas之类的程序库获益良多。

假设你是一位正在撰写硕士论文的金融专业学生,对标普 500 指数感兴趣,想要分析 1 年的历史指数水平,以了解指数在这段时间内的波动性,你希望找到证据证明这种变动性与某些典型的模型假设相反,它是随时间变动而非固定。而且,应该对结果进行可视化,你要进行的主要的工作如下:

这些任务很复杂,在不久之前还被认为是专业金融分析师才能完成的。而在今天,即使是金融专业的学生也可以轻松地对付这类问题。我们来看看具体的做法——此时还不用操心语法的细节(后续的章节将对所有细节进行解释):

In [16]: import numpy as np ❶
         import pandas as pd ❶
         from pylab import plt, mpl ❷

In [17]: plt.style.use('seaborn') ❷
         mpl.rcParams['font.family'] = 'serif' ❷
         %matplotlib inline

In [18]: data = pd.read_csv('../../source/tr_eikon_eod_data.csv',
                           index_col=0, parse_dates=True) ❸
         data = pd.DataFrame(data['.SPX']) ❹
         data.dropna(inplace=True) ❹
         data.info() ❺
         <class 'pandas.core.frame.DataFrame'>
         DatetimeIndex: 2138 entries, 2010-01-04 to 2018-06-29
         Data columns (total 1 columns):
         .SPX    2138 non-null float64
         dtypes: float64(1)
         memory usage: 33.4 KB

In [19]: data['rets'] = np.log(data / data.shift(1)) ❻
         data['vola'] = data['rets'].rolling(252).std() * np.sqrt(252) ❼
         In [20]: data[['.SPX', 'vola']].plot(subplots=True, figsize=  
            (10, 6)); ❽

❶ 导入NumPy和pandas。

❷ 导入matplotlib并配置Jupyter绘图样式和方法。

❸ pd.read_csv()可以读取远程或者本地存储的逗号分隔值(CSV)形式数据集。

❹ 选取一个数据子集,删除NaN(非数值)值。

❺ 显示关于数据集的一些元信息。

❻ 以向量化的方式(在Python级别上“无循环”)计算对数收益率。

❼ 得出滚动年化波动率。

❽ 最后绘制两个时间序列。

图1-1展示了这一简短交互会话所得到的图形化结果。用几行代码就足以完成金融分析中的典型复杂任务:数据收集、复杂和重复的数学计算以及结果的可视化,令人觉得不可思议。从这个例子中可以看到,pandas使整个时间系列的处理变得就像浮点数上的数学运算那样容易。

图1-1 标普500收盘价和年化波动率

将这个例子转换到专业的金融环境中,可以看出金融分析师在应用提供高层次抽象的合适的Python工具和库的时候,能够将焦点放在自身的领域上,而不用关心复杂的技术细节。分析师可以快速反应,几乎实时地提供宝贵的洞见,确保自己比竞争对手先行一步。这种效率的提高很容易转换为可度量的财务效果。

2.确保高性能

一般来说,Python的语法相当简洁,编码效率相对高是为人们所接受的说法。但是,由于Python本质上是解释型语言,因此存在一种偏见,认为Python对于金融学中的计算密集任务来说速度过于缓慢。确实,在某些特定的实现方法下,Python可能确实很慢,但是,它并不一定都那么缓慢——它可以在几乎所有应用领域中表现出高性能。理论上,人们至少可以找到3种提高性能的策略。

惯例和范型

一般来说,Python可以用许多不同的方式得出相同的结果,但是这些方式的性能特性有相当大的区别;只要选择合适的方式(如特定的实现方法、明智地使用数据结构、通过向量化避免循环或者使用pandas等特定库),就可以显著地改善效果。

编译

现在,有许多高性能库可以提供重要函数的编译版本,或者将Python代码静态或者动态地(在运行时或者调用时)编译为机器代码,这种代码的速度比纯Python代码要快好几个数量级。比较流行的高性能库有Cython和Numba等。

并行化

许多计算任务(特别是金融学中的计算任务)可以从并行执行中得到很大好处;这对Python来说不足为奇,可以轻松地实现。

 

使用Python实现高性能计算

Python本身不是一种高性能计算技术。但是,Python已经发展成为一种访问当前高性能技术的理想平台。在这个意义上,Python已经成为高性能计算的“黏合剂”语言。

本节坚持使用简洁实用的例子介绍上述3种策略(后续的章节将详细介绍这些策略)。金融分析中相当常见的任务之一是在大量数字上计算复杂的数学表达式。在这方面,Python本身就提供了所有必需的功能:

In [21]: import math
         loops = 2500000
         a = range(1, loops)
         def f(x):
             return 3 * math.log(x) + math.cos(x) ** 2
         %timeit r = [f(x) for x in a]
         1.59 s ± 41.2 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

Python解释程序在本例中需要1.6s的时间来完成250万次函数f的计算。使用NumPy可以完成相同的任务,它提供了优化(也就是预先编译)的函数来处理这种基于数组的运算:

In [22]: import numpy as np
         a = np.arange(1, loops)
         %timeit r = 3 * np.log(a) + np.cos(a) ** 2
         87.9 ms ± 1.73 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

NumPy可以将执行时间大幅缩减到约88ms。甚至有一个库是专门用于此类任务的,这个库叫作numexpr,得名于“数值表达式”(Numerical Expressions)。它可以编译表达式来改善NumPy通用功能的性能。例如,在执行期间避免ndarray对象在内存中复制:

In [23]: import numexpr as ne
         ne.set_num_threads(1)
         f = '3 * log(a) + cos(a) ** 2'
         %timeit r = ne.evaluate(f)
         50.6 ms ± 4.2 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

使用这种更特殊的方法可以进一步将执行时间降低至约50ms。而且,numexpr还内建并行执行单独运算的功能。这使我们能够使用一个CPU的多个线程:

In [24]: ne.set_num_threads(4)
         %timeit r = ne.evaluate(f)
         22.8 ms ± 1.76 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)

本例利用了4个线程,执行时间进一步下降到23ms,总体的性能提升了90倍。特别要注意的是,这类改善不需要修改基本问题/算法,也不用了解任何有关编译和并行化问题的知识,即使是非专业人士也可以从较高的层次上去利用这种功能。当然,前提是你必须知道存在这些功能。

这个例子说明,Python提供了一些选项可以更好地利用现有资源,也就是提高生产率。利用并行化方法,可以在同样的时间里完成3倍于串行化方法的计算,这只需要告诉Python使用多个CPU线程(而非仅使用一个线程)即可。

从执行速度的角度看,交互式分析的效率和性能当然是Python值得考虑的两个好处。在金融学中使用Python的另一个好处初看似乎比较不起眼,但是细看之下就会发现它本身是一个重要的战略因素。这就是以端到端(从原型化到生产)的方式使用Python的可能性。

当今全球金融机构的金融开发过程往往是一个分离的两步式过程。一方面,量化分析师(quant,也称宽客)负责模型开发和技术原型化。他们喜欢使用MatLab和R等工具和环境实现快速、交互式的应用程序开发。在开发的这一阶段,性能、稳定性、异常管理、数据访问分离和分析等问题都不重要。人们的主要目标是概念或者原型的验证,原型用于展现某种算法或者整个应用程序必需的主要功能。

一旦原型完成,IT部门中的开发人员接管工作,他们负责将现有原型代码翻译为可靠、易于维护和高性能的生产代码。这一阶段中,通常在用于满足生产性能的C++或者Java语言中有一个范型转换的过程。而且,正规的开发过程还要用到专业工具、版本控制等技术。

这种两步式方法会产生一些意外的结果。

效率低下

原型代码不能重用;算法必须实现两次;多余的工作消耗时间和资源;转译时产生的风险。

多种技能集

不同部门展现不同的技能集合,使用不同的语言实现“相同的工作”。

遗留代码

代码必须以不同的语言存在和维护,并使用不同的实现风格(例如,从架构的观点上看)。

另一方面,使用Python可以实现合理化的端到端过程——从最初的交互式原型化步骤到高可靠性、易于维护的生产代码。不同部门之间的沟通变得更加简单,工作人员的培训也更为合理,只有一种主要语言覆盖金融应用构建的所有领域,还避免了在开发过程不同步骤中使用不同技术造成的低效和冗余性。总而言之,Python可以为金融应用开发和算法实现提供一致性的技术框架。

在2018年8月更新第2版的这一节时,2014年本书第1版中有关科技与金融学之间关系的言论似乎仍然适用且重要。但是,本节将讲述金融业的两个重要趋势,它们将从根本上重塑这个行业。这两个趋势主要是在过去的几年内形成的。

最重要的一些金融理论(如MPT和CAPM)可以追溯到20世纪50年代和60年代。然而,它们仍然是经济、财务、金融工程和商业管理领域教育的基石。这可能令人惊讶,因为大部分此类理论的实证支持相当贫乏,而证据往往完全与理论相反。另一方面,它们的流行性也是可以理解的,因为它们接近于人们对金融市场表现的期望,而且,它们是建立在一些吸引人(通常过于简单)的假设之上的简洁数学理论的。

科学方法(如物理学)始于数据(如来自试验或者观察的数据),然后得出假设和理论,并用数据加以测试。如果测试结果是肯定的,那可以对这些假设和理论进行提炼,并以合适的方法记录下来,例如以研究型论文的方式发表。如果测试结果是否定的,假设和理论将被抛弃,并开始寻找复合数据的新理论。由于物理定律在一段时间里是稳定的,所以一旦发现并对其进行了完备的测试,那么在最佳状况下,通常可以认为是永远成立的。

(计量)金融学的历史大部分与科学方法相悖。在许多情况下,理论和模型是在简化的数学假设下“从头”开发的,目标是发现金融学核心问题的简练回答。金融学的流行假设是,金融工具的回报呈标准正态分布,各种利率之间呈线性关系。由于这些现象在金融市场上很难看到,这些简单理论的实证往往很缺乏,也就不值得惊讶了。许多金融理论和模型都是首先提出公式、证明并发表,然后才进行实证测试的。在某种程度上,这当然是因为20世纪50年代或者70年代甚至更晚的时候,还不存在合适形式的金融数据,而今天就连攻读金融学士学位的学生都能得到这些数据。

20世纪90年代初期到中期,金融机构所能得到的此类数据急剧增加。今天,甚至进行金融研究或者参与算法交易的个人都可以得到大量的历史数据,也可以通过流服务得到实时数据。这使我们可以专注于科学方法,科学方法通常从数据开始,然后得出思路、假设、模型和策略。

用一个简单的例子就可以说明,如今在本地机器上利用Python和Eikon Data APIs订阅大规模专业数据有多么简单。下面的例子是读取的苹果公司股票常规交易日中一个小时的分笔交易数据。读取的报价数据(包括交易量信息)大约有15000条。由于股票代码为AAPL,所以路透金融工具代码(RIC)为AAPL.0:

In [26]: import eikon as ek ❶

In [27]: data = ek.get_timeseries('AAPL.O', fields='*',
                                  start_date='2018-10-18 16:00:00',
                                  end_date='2018-10-18 17:00:00',
                                  interval='tick') ❷

In [28]: data.info() ❷
         <class 'pandas.core.frame.DataFrame'>
         DatetimeIndex: 35350 entries, 2018-10-18 16:00:00.002000 to 
         2018-10-18 16:59:59.888000
         Data columns (total 2 columns):
         VALUE 35285 non-null float64
         VOLUME 35350 non-null float64
         dtypes: float64(2)
         memory usage: 828.5 KB

In [29]: data.tail() ❸
Out[29]: AAPL.O                VALUE VOLUME
         Date
         2018-10-18 16:59:59.433 217.13 10.0
         2018-10-18 16:59:59.433 217.13 12.0
         2018-10-18 16:59:59.439 217.13 231.0
         2018-10-18 16:59:59.754 217.14 100.0
         2018-10-18 16:59:59.888 217.13 100.0

❶ Eikon Data API需要订阅和API连接才能使用。

❷ 读取苹果公司(AAPL.O)股票分笔数据。

❸ 显示最后5行数据。

Eikon Data API不仅可以访问结构化金融数据(如历史报价数据),还可以访问新闻等非结构化数据。下面的例子读取一小部分新闻的元数据,并以全文本方式显示其中一篇文章开头的内容。

In [30]: news = ek.get_news_headlines('R:AAPL.O Language:LEN',
                                  date_from='2018-05-01',
                                  date_to='2018-06-29',
                                  count=7) ❶

In [31]: news ❶
Out[31]:
                                     versionCreated \
    2018-06-28 23:00:00.000 2018-06-28 23:00:00.000
    2018-06-28 21:23:26.526 2018-06-28 21:23:26.526
    2018-06-28 19:48:32.627 2018-06-28 19:48:32.627
    2018-06-28 17:33:10.306 2018-06-28 17:33:10.306
    2018-06-28 17:33:07.033 2018-06-28 17:33:07.033
    2018-06-28 17:31:44.960 2018-06-28 17:31:44.960
    2018-06-28 17:00:00.000 2018-06-28 17:00:00.000

                                                          text \
    2018-06-28 23:00:00.000 RPT-FOCUS-AI ambulances and robot doctors: Chi...
    2018-06-28 21:23:26.526 Why Investors Should Love Apple's (AAPL) TV En...
    2018-06-28 19:48:32.627 Reuters Insider - Trump: We're reclaiming our ...
    2018-06-28 17:33:10.306 Apple v. Samsung ends not with a whimper but a...
    2018-06-28 17:33:07.033 Apple's trade-war discount extended for anothe...
    2018-06-28 17:31:44.960 Other Products: Apple's fast-growing island of...
    2018-06-28 17:00:00.000 Pokemon Go creator plans to sell the tech behi...
                                                            storyId \
    2018-06-28 23:00:00.000 urn:newsml:reuters.com:20180628:nL4N1TU4F8:6
    2018-06-28 21:23:26.526 urn:newsml:reuters.com:20180628:nNRA6e2vft:1
    2018-06-28 19:48:32.627 urn:newsml:reuters.com:20180628:nRTV1vNw1p:1
    2018-06-28 17:33:10.306 urn:newsml:reuters.com:20180628:nNRA6e1oza:1
    2018-06-28 17:33:07.033 urn:newsml:reuters.com:20180628:nNRA6e1pmv:1
    2018-06-28 17:31:44.960 urn:newsml:reuters.com:20180628:nNRA6e1m3n:1
    2018-06-28 17:00:00.000 urn:newsml:reuters.com:20180628:nL1N1TU0PC:3

                           sourceCode
    2018-06-28 23:00:00.000   NS:RTRS
    2018-06-28 21:23:26.526 NS:ZACKSC
    2018-06-28 19:48:32.627   NS:CNBC
    2018-06-28 17:33:10.306 NS:WALLST
    2018-06-28 17:33:07.033 NS:WALLST
    2018-06-28 17:31:44.960 NS:WALLST
    2018-06-28 17:00:00.000   NS:RTRS
In [32]: story_html = ek.get_news_story(news.iloc[1, 2]) ❷

In [33]: from bs4 import BeautifulSoup ❸

In [34]: story = BeautifulSoup(story_html, 'html5lib').get_text() ❹

In [35]: print(story[83:958]) ❺
    Jun 28, 2018 For years, investors and Apple AAPL have been beholden to
    the iPhone, which is hardly a negative since its flagship product is
    largely responsible for turning Apple into one of the world's biggest
    companies. But Apple has slowly pushed into new growth areas, with
    streaming television its newest frontier. So let's take a look at what
    Apple has planned as it readies itself to compete against the likes of
    Netflix NFLX and Amazon AMZN in the battle for the new age of
    entertainment.Apple's second-quarter revenues jumped by 16% to reach
    $61.14 billion, with iPhone revenues up 14%. However, iPhone unit sales
    climbed only 3% and iPhone revenues accounted for over 62% of total Q2
    sales. Apple knows this is not a sustainable business model, because
    rare is the consumer product that can remain in vogue for decades. This
    is why Apple has made a big push into news,

❶ 读取一小部分新闻的元数据。

❷ 读取一篇文章的全部文本,形式为HTML文档。

❸ 导入BeautifulSoup HTML解析库并进行后续操作。

❹ 以纯文本方式(str对象)提取内容。

❺ 打印新闻的开头。

尽管这两个例子很浅显,但它们说明,通过Python包装器库和数据订阅服务,可以以标准化、高效的方式得到结构化和非结构化的金融历史数据。在许多情况下,个人甚至可以使用FXCM集团、LLC等交易平台(在第14章和第16章中会讲到)来免费获得类似的数据集。一旦在Python级别上得到数据(独立于原始来源),就可以利用Python数据分析生态系统的全部功能了。

 

数据驱动金融学

近年来,数据成了金融业的推动力。即使最大、最成功的对冲基金也自称是“数据驱动”的,而非“金融驱动”的。越来越多的服务产品向大小机构及个人提供海量数据。Python通常被选为与这些API交互、处理和分析数据的编程语言。

由于通过编程API能够取得大量金融数据,所以在金融问题(如算法交易)上应用人工智能(AI)方法、特别是机器与深度学习(ML,DL)就变得非常容易,也更有成果了。

Python可以称得上AI界的“宠儿”。它往往被AI研究人员和从业者选为编程语言。从这个意义上说,金融领域从不同领域的发展中得益,这些领域有时甚至与金融没有太大的联系。举个例子,深度学习所用的TensorFlow开源程序库是Google公司开发和维护的,用于其母公司Alphabet自动驾驶汽车的制造和销售上。

TensorFlow当然和股票自动算法交易一点关联都没有,但却可以用于预测金融市场的变动。第15章提供了许多这方面的例子。最广泛使用的Python ML程序库是scikit-learn。下面的代码以高度简化的方式说明:ML 分类算法如何用来预测期货价格变动方向,并以这些预测为基础制定一个算法交易策略。所有细节将在第15章中解释,因此这个例子相当简洁。首先,导入数据,准备期货数据(定向滞后对数收益率数据)。

In [36]: import numpy as np
         import pandas as pd

In [37]: data = pd.read_csv('../../source/tr_eikon_eod_data.csv',
                            index_col=0, parse_dates=True)
         data = pd.DataFrame(data['AAPL.O']) ❶
         data['Returns'] = np.log(data / data.shift()) ❷
         data.dropna(inplace=True)

In [38]: lags = 6

In [39]: cols = []
         for lag in range(1, lags + 1):
             col = 'lag_{}'.format(lag)
             data[col] = np.sign(data['Returns'].shift(lag)) ❸
             cols.append(col)
         data.dropna(inplace=True)

❶ 选择苹果公司(AAPL.0)历史日终数据。

❷ 计算整个历史数据内的对数收益率。

❸ 生成带有定向滞后对数收益率数据(+1或者−1)的DateFrame列。

接下来,为支持向量机(SVM)算法、模型拟合和预测步骤实例化一个模型对象。图1-2说明,根据预测买进和卖出苹果公司股票的基于预测交易策略的表现胜过被动的基准股票投资方法。

图1-2 基于ML的算法交易策略与被动基准投资的对比(苹果公司股票)

In [40]: from sklearn.svm import SVC

In [41]: model = SVC(gamma='auto') ❶

In [42]: model.fit(data[cols], np.sign(data['Returns'])) ❷
Out[42]: SVC(C=1.0, cache_size=200, class_weight=None, coef0=0.0,
           decision_function_shape='ovr', degree=3, gamma='auto', kernel='rbf',
           max_iter=-1, probability=False, random_state=None, shrinking=True,
           tol=0.001, verbose=False)

In [43]: data['Prediction'] = model.predict(data[cols]) ❸

In [44]: data['Strategy'] = data['Prediction'] * data['Returns'] ❹

In [45]: data[['Returns', 'Strategy']].cumsum().apply(np.exp).plot(
                 figsize=(10, 6)); ❺

❶ 实例化模型对象。

❷ 根据期货和标签数据(全部是定向的)拟合模型。

❸ 使用拟合模型创建预测(样本内),这同时是交易策略的头寸(买入或者卖出)。

❹ 根据预测值和基准对数收益率计算交易策略的对数收益率。

❺ 绘制基于ML交易策略表现与被动基准投资表现的对比曲线。

这里采用的简化方法没有考虑交易成本,也没有将数据集分为训练和测试子集。但是,这个例子说明,至少从技术意义上,将ML算法应用到金融数据有多么简单。在实践中,需要考虑一些重要的因素(参见Lopez de Prado(2018))。

 

人工智能优先金融学

AI将像对待其他领域一样,重塑金融行业。通过编程API功能可以取得大量金融数据,这成为了该领域的引擎。第13章中介绍AI、ML和DL基本方法,并在第15章和第16章中将其应用到算法交易中。不过,全面介绍人工智能优先金融学需要一本专门的图书。

作为数据驱动金融学的自然延伸,不管从研究还是从业者的角度,金融学中的人工智能当然也是一个令人痴迷和兴奋的领域。本书在不同背景下使用了多种AI、ML和DL方法,但总体的焦点与本书的副标题相符,仍是数据驱动金融学所需的Python基本技术与方法。不过,这些技术与方法对人工智能优先金融学同样重要。

Python作为一种语言,但更多的是作为生态系统,是金融业理想的技术框架。它的特性中有许多好处,比如简洁的语法、高效的开发方法和原型化及生产的易用性等。利用Python大量的可用库和工具,我们似乎能够应付当今金融业中分析、数据量和频率、依从性及监管所引发的大部分问题。即使在较大型的金融机构中,它也具备提供单一、强大、一致性的框架,简化端到端开发和生产工作的潜力。

此外,Python已经成为人工智能、特别是机器与深度学习工作者选择的编程语言。因此,Python对于数据驱动金融学和人工智能优先金融学来说也是合适的语言,这两种当今的趋势将从根本上重塑金融学和金融行业。

下面的图书更详细地介绍了本章浅释的多个方面(例如Python工具、衍生品研究、机器学习概述以及金融中的机器学习)。

至于算法交易,本书作者的公司提供了一系列在线培训项目,该计划聚焦于Python和其他工具,以及这个迅速成长的领域中所需的技术。

本章引用了如下信息来源。

[1] 例如,Python已经成为纽约城市大学博鲁克学院金融工程研究生课程中使用的主要语言之一。——原注

[2] 维基百科上可以找到许多开发人员和非开发人员学习Python入门知识的宝贵资源。——原注


盖房子的时候,木料的选择是个问题。

木匠的目标本质上就是携带好的切割工具。在他有时间的时候,会将他的设备磨得很锋利。

——宫本武藏(五轮书)

对于Python新手来说,Python的部署似乎很简单。丰富的可选安装库和程序包也很容易安装。首先,Python不止一种,它有许多不同的“风味”,如CPython、Jython、IronPython和PyPy。然后,Python 2.7和3.x也是不同的世界。[1]

即便在你决定了使用哪一版本之后,部署也很困难,原因如下:

幸运的是,我们可以求助于工具和策略。本章将介绍以下有助于Python部署的技术。

包管理器

pip和conda等包管理器用于安装、更新和删除Python软件包;它们还有助于保持不同包的版本一致性。

虚拟环境管理器

virtualenv或 conda等虚拟环境管理器可以并行管理多种Python安装(例如,在单一机器上安装Python 2.7和3.7,以便无风险地测试某个有趣的Python软件包的最新开发版本)。[2]

容器

Docker容器代表着包含运行特定软件所需的全部系统部件(如代码、运行时库或系统工具)的完整文件系统。例如,你可以在运行macOS或者Windows10的一台机器上,在一个Docker容器里运行Ubuntu 18.04操作系统,并在其中安装Python 3.7和单独的Python代码。

云实例

为金融应用部署Python代码通常要求高可用性、安全性和高性能;这些需求一般只能利用专业计算及存储基础设施满足。目前,这种基础设施以情况良好的云实例形式存在,规模从小到大不等。与长期租赁的专用服务器相比,云实例(也就是虚拟服务器)的好处之一是,用户通常只需要按照实际使用的时间付费;另一个好处是,这种云实例在需要时一两分钟内就能投入使用,有助于敏捷开发并提高伸缩性。

本章的结构如下。

作为包管理器使用的conda

本节介绍作为Python包管理器使用的conda。

作为虚拟环境管理器使用的conda

这一节专注于conda作为虚拟环境管理器的功能。

使用Docker容器

这一节简单概述了Docker容器化技术,聚焦于构建带有Python 3.7安装的Ubuntu容器。

使用云实例

本节介绍在云中部署Python和Jupyter Notebook的方法,后者是一个基于浏览器的、功能强大的Python部署工具套件。

本章的目标是在专业基础设施上建立一个合适的Python环境,包含最重要的工具以及数值、数据分析和可视化软件包(库)。此后,这一组合将作为实现和部署后续章节中Python代码的支柱,不管这些代码是交互式的金融分析代码,还是以脚本和模块形式出现的。

conda可以单独安装,但是更有效的方法之一是通过Miniconda安装,这是一个包含conda、并将conda作为包和虚拟环境管理器使用的最小化Python分发版本。

Miniconda可用于Windows、macOS和Linux。你可以从Miniconda网页上下载不同的版本。以下假定安装的是Python 3.7 64位版本。本节的主要例子是基于Ubuntu的Docker容器中的一个会话,通过 wget 下载 Linux 64 位安装程序,然后安装Miniconda。下面的代码应该可以在任何Linux或者macOS机器上正常工作(可能需要做少量修改)。

$ docker run -ti -h py4fi -p 11111:11111 ubuntu:latest /bin/bash

root@py4fi:/# apt-get update; apt-get upgrade -y
...
root@py4fi:/# apt-get install -y bzip2 gcc wget
...
root@py4fi:/# cd root
root@py4fi:~# wget \
> https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_64.sh \
> -O miniconda.sh
...
HTTP request sent, awaiting response... 200 OK
Length: 62574861 (60M) [application/x-sh]
Saving to: 'miniconda.sh'
miniconda.sh        100%[====================>] 59.68M 5.97MB/s in 11s

2018-09-15 09:44:28 (5.42 MB/s) - 'miniconda.sh' saved [62574861/62574861]

root@py4fi:~# bash miniconda.sh

Welcome to Miniconda3 4.5.11

In order to continue the installation process, please review the license
agreement.
Please, press ENTER to continue
>>>

按Enter键开始安装过程。阅读许可协议后,单击“yes”按钮同意条款。

...
Do you accept the license terms? [yes|no]
[no] >>> yes

Miniconda3 will now be installed into this location:
/root/miniconda3

 - Press ENTER to confirm the location
 - Press CTRL-C to abort the installation
 - Or specify a different location below

[/root/miniconda3] >>>
PREFIX=/root/miniconda3
installing: python-3.7. ...
...
installing: requests-2.19.1-py37_0 ...
installing: conda-4.5.11-py37_0 ...
installation finished.

同意许可条款并确认安装位置之后,你应该再次单击“yes”按钮,允许 Miniconda 将新的Miniconda安装位置附加到PATH环境变量中。

Do you wish the installer to prepend the Miniconda3 install location
to PATH in your /root/.bashrc ? [yes|no]
[no] >>> yes

Appending source /root/miniconda3/bin/activate to /root/.bashrc
A backup will be made to: /root/.bashrc-miniconda3.bak

For this change to become active, you have to open a new terminal.

Thank you for installing Miniconda3!
root@py4fi:~#

此后,你可能想要升级conda和Python。[3]

root@py4fi:~# export PATH="/root/miniconda3/bin/:$PATH"
root@py4fi:~# conda update -y conda python
...
root@py4fi:~# echo ". /root/miniconda3/etc/profile.d/conda.sh" >> ~/.bashrc
root@py4fi:~# bash

在这一相当简单的安装过程之后,你就可以使用基本的Python安装和conda了。基本Python安装包含了一些很好的功能,如SQLite3数据库引擎。在对应的环境变量中附加相关路径(正如前面所做的那样)之后,你可以试验能否从新的Shell实例中启动Python:

root@py4fi:~# python
Python 3.7.0 (default, Jun 28 2018, 13:15:42)
[GCC 7.2.0] :: Anaconda, Inc. on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> print('Hello Python for Finance World.')
Hello Python for Finance World.
>>> exit()
root@py4fi:~#

conda可用于高效地处理Python软件包的安装、更新和删除。接下来概述一下主要功能。

安装Python x.x版本
conda install python=x.x
更新Python
conda update python
安装软件包
conda install $PACKAGE_NAME
更新软件包
conda update $PACKAGE_NAME
删除软件包
conda remove $PACKAGE_NAME
更新conda
conda update conda
搜索软件包
conda search $SEARCH_TERM
列出已安装软件包
conda list

考虑到这些功能,安装NumPy——所谓“科学栈”中最重要的库之一——只需要一条命令。在装有Intel处理器的机器上安装时,将自动安装Intel数学核心库(Intel Math Kernel Library,MKL),这个库不仅能加速NumPy的数值运算,而且对其他几个Python科学库也有作用。[4]

root@py4fi:~# conda install numpy
Solving environment: done

## Package Plan ##

  environment location: /root/miniconda3

  added / updated specs:
    numpy

The following packages will be downloaded:

    Package                |            build
---------------------------|-----------------
    mkl-2019.0             |              117       204.4 MB
    intel-openmp-2019.0    |              117         721 KB
    mkl_random-1.0.1       |   py37h4414c95_1         372 KB
    libgfortran-ng-7.3.0   |       hdf63c60_0         1.3 MB
    numpy-1.15.1           |   py37h1d66e8a_0          37 KB
    numpy-base-1.15.1      |   py37h81de0dd_0         4.2 MB
    blas-1.0               |              mkl           6 KB
    mkl_fft-1.0.4          |   py37h4414c95_1         149 KB
------------------------------------------------------------
                                       Total:       211.1 MB

The following NEW packages will be INSTALLED:

blas:           1.0-mkl
intel-openmp:   2019.0-117
libgfortran-ng: 7.3.0-hdf63c60_0
mkl:            2019.0-117
mkl_fft:        1.0.4-py37h4414c95_1
mkl_random:     1.0.1-py37h4414c95_1
numpy:          1.15.1-py37h1d66e8a_0
numpy-base:     1.15.1-py37h81de0dd_0

Proceed ([y]/n)? y
Downloading and Extracting Packages
mkl-2019.0           | 204.4 MB | ###################################### | 100%
...
numpy-1.15.1         | 37 KB    | ###################################### | 100%
numpy-base-1.15.1    | 4.2 MB   | ###################################### | 100%
...
root@py4fi:~#

也可以一次性安装多个软件包。-y标志表示所有(可能的)问题都以yes回答。

root@py4fi:/# conda install -y ipython matplotlib pandas pytables scikit-learn \
> scipy
...
pytables-3.4.4       | 1.5 MB   | ##################################### | 100%
kiwisolver-1.0.1     | 83 KB    | ##################################### | 100%
icu-58.2             | 22.5 MB  | ##################################### | 100%
Preparing transaction: done
Verifying transaction: done
Executing transaction: done
root@py4fi:~#

安装过程结束后,除了标准库之外,一些重要的金融分析库也已经可用,包括:

IPython

改进的交互式Python shell;

Matplotlib

Python标准绘图库;

NumPy

用于高效处理数组;

pandas

用于管理表格数据,例如金融时间序列数据;

PyTables

Python HDF5库封装器;

scikit-learn

机器学习和相关任务所用的软件包;

SciPy

一组科学类和函数(以依赖的形式安装)。

这就为数据分析、特别是金融分析提供了一个基本工具集。下面的例子使用IPython和NumPy提取了一组伪随机数。

root@py4fi:~# ipython
Python 3.7.0 (default, Jun 28 2018, 13:15:42)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.5.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import numpy as np

In [2]: np.random.seed(100)

In [3]: np.random.standard_normal((5, 4))
Out[3]:
array([[-1.74976547, 0.3426804 , 1.1530358 , -0.25243604],
       [ 0.98132079, 0.51421884, 0.22117967, -1.07004333],
       [-0.18949583, 0.25500144, -0.45802699, 0.43516349],
       [-0.58359505, 0.81684707, 0.67272081, -0.10441114],
       [-0.53128038, 1.02973269, -0.43813562, -1.11831825]])

In [4]: exit
root@py4fi:~#

执行conda list命令显示已安装的软件包。

root@py4fi:~# conda list
# packages in environment at /root/miniconda3:
#
# Name                    Version            Build Channel
asn1crypto                0.24.0            py37_0
backcall                  0.1.0             py37_0
blas                      1.0                  mkl
blosc                     1.14.4        hdbcaa40_0
bzip2                     1.0.6         h14c3975_5
...
python                    3.7.0         hc3d631a_0
...
wheel                     0.31.1            py37_0
xz                        5.2.4         h14c3975_4
yaml                      0.1.7         had09818_2
zlib                      1.2.11        ha838bed_2
root@py4fi:~#

如果不再某个包需要,可以用conda remove将其高效删除。

root@py4fi:~# conda remove scikit-learn
Solving environment: done

## Package Plan ##

  environment location: /root/miniconda3
  removed specs:
    - scikit-learn

The following packages will be REMOVED:

    scikit-learn: 0.19.1-py37hedc7406_0

Proceed ([y]/n)? y

Preparing transaction: done
Verifying transaction: done
Executing transaction: done
root@py4fi:~#

conda的包管理器功能相当实用。然而,在加上虚拟环境管理器后,你才能看出它的全部威力。

 

简易包管理

conda作为包管理器,可以使Python软件包的安装、更新和删除变得很简单。没有必要自行构建和编译软件包——考虑到软件包指定的依赖列表和不同操作系统所需考虑的细节,这一步有时可能很棘手。

根据你所选择的安装程序版本,Miniconda提供了默认的Python 2.7或者3.7安装。conda的虚拟环境管理器可以允许不同的组合,例如,在Python 3.7默认安装的基础上增加一个完全独立的Python 2.7.x安装。为此,conda提供了以下功能。

创建虚拟环境
conda create --name $ENVIRONMENT_NAME
激活环境
conda activate $ENVIRONMENT_NAME
停止环境
conda deactivate $ENVIRONMENT_NAME
删除环境
conda env remove --name $ENVIRONMENT_NAME
导出到环境文件
conda env export > $FILE_NAME
从一个文件中创建环境
conda env create -f $FILE_NAME
列出所有环境
conda info --envs

下面的代码是一个简单的示意:创建一个名为py27的环境,在其中安装IPython,并执行一行Python 2.7.x代码。

root@py4fi:~# conda create --name py27 python=2.7
Solving environment: done

## Package Plan ##

  environment location: /root/miniconda3/envs/py27

  added / updated specs:
    - python=2.7

The following NEW packages will be INSTALLED:

    ca-certificates: 2018.03.07-0
...
    python:          2.7.15-h1571d57_0
...
    zlib:            1.2.11-ha838bed_2

Proceed ([y]/n)? y

Preparing transaction: done
Verifying transaction: done
Executing transaction: done
#
# To activate this environment, use:
# > conda activate py27
#
# To deactivate an active environment, use:
# > conda deactivate
#

root@py4fi:~#

注意激活环境之后提示符的变化(py27)。

root@py4fi:~# conda activate py27
(py27) root@py4fi:~# conda install ipython
Solving environment: done
...
Executing transaction: done
(py27) root@py4fi:~#

最后,以下代码允许你以Python 2.7语法使用IPython。

(py27) root@py4fi:~# ipython
Python 2.7.15 |Anaconda, Inc.| (default, May 1 2018, 23:32:55)
Type "copyright", "credits" or "license" for more information.

IPython 5.8.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
Help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: print "Hello Python for Finance World!"
Hello Python for Finance World!

In [2]: exit
(py27) root@py4fi:~#

如上例所示,将conda作为虚拟环境管理器使用,你可以同时安装不同的Python版本,还可以安装某些包的不同版本。默认Python的安装不受这一过程的影响,存在于同一台机器上的其他环境也是如此。conda env list可显示所有可用环境。

(py27) root@py4fi:~# conda env list
# conda environments:
#
base                     /root/miniconda3
py27                   * /root/miniconda3/envs/py27

(py27) root@py4fi:~#

有时候,你需要与其他人共享环境信息,或者在多台机器上使用环境信息。为此,可以用conda env export将已安装程序包列表导出到一个文件中。这只默认适用于使用相同操作系统的机器,因为结果YAML文件中指定构建版本,但可以将其删掉,只指定软件包版本。

(py27) root@py4fi:~# conda env export --no-builds > py27env.yml
(py27) root@py4fi:~# cat py27env.yml
name: py27
channels:
  - defaults
dependencies:
  - backports=1.0
...
  - python=2.7.15
...
  - zlib=1.2.11
prefix: /root/miniconda3/envs/py27

(py27) root@py4fi:~#

从技术上说,虚拟环境不过是一个特定的(子)文件夹结构,创建它们往往是为了进行一些快速测试[5]。在这种情况下,停止后的环境很容易用conda env remove删除。

(py27) root@py4fi:/# conda deactivate
root@py4fi:~# conda env remove -y --name py27

Remove all packages in environment /root/miniconda3/envs/py27:

## Package Plan ##

  environment location: /root/miniconda3/envs/py27

The following packages will be REMOVED:

    backports:                          1.0-py27_1
...
    zlib:                               1.2.11-ha838bed_2

root@py4fi:~#

conda的虚拟环境管理器的功能概述到此结束。

 

简易环境管理

conda不仅有助于包管理,还是Python的虚拟环境管理器。它简化了不同Python环境的创建,允许在同一台机器上使用多个版本的Python和可选包,这些不同版本不会互相影响。conda还可以导入环境信息,因此你可以轻松地在多台机器上复制环境,或者与他人共享。

Docker容器已经征服了IT界。虽然这种技术仍然相对年轻,但已经为几乎所有类型软件应用的高效开发与部署确立了一个标杆。

在本书中,你可以将Docker容器看作一个独立(“容器化”)文件系统,它包含操作系统(例如Ubuntu Server 18.04)、(Python)运行时库、其他系统与开发工具,以及需要的其他(Python)库和软件包。这样的一个Docker容器可以运行在Windows 10本地机器上,或者使用Linux操作系统的云实例上。

本节不打算介绍Docker容器所有激动人心的细节,而是简洁地说明Docker技术在Python开发领域所能发挥的能力。[6]

不过,在说明之前,我们必须区分Docker的两个基本概念。首先是Docker镜像(Image),它可以比作Python的一个类。其次是Docker容器,它可以比作对应Python类的一个实例。[7]

你可以从Docker词汇表上找到镜像更为技术性的定义:

Docker镜像是容器的基础。镜像是根文件系统变化和用于容器运行时库内部的对应执行参数的一个有序集合。镜像通常包含一组相互堆叠的分层文件系统,它没有状态,也永远不会变化。

类似地,你可以在Docker词汇表上找到容器的定义,这使得与Python类和类实例的对比变得很清晰:

容器是Docker镜像的运行时实例。一个Docker实例包括:一个Docker镜像、一个执行环境和一个标准指令集。

根据操作系统的不同,Docker的安装略有不同,这就是本节不做详述的原因。更多的信息和链接可以在About Docker CE页面上找到。

本节举例说明基于Ubuntu最新版本的Docker镜像的构建方法,镜像中还包括Miniconda和几个重要的Python软件包。此外,通过更新Linux软件包索引、在必要时升级软件包并安装某些附加的系统工具,我们可以进行一些Linux的“内务整理”工作。这方面的工作需要两个脚本,一个是完成所有Linux层面工作的bash脚本[8]。另一个是所谓的Dockerfile,即控制镜像本身的构建过程。

例2-1中的bash安装脚本包括3个主要部分。第一部分处理Linux“内务”。第二部分安装Miniconda,第3部分安装Python可选程序包。更详细的注释请见脚本。

例2-1 安装Python和可选包的脚本

#!/bin/bash
#
# Script to Install
# Linux System Tools and
# Basic Python Components
#
# Python for Finance, 2nd ed.
# (c) Dr. Yves J. Hilpisch
#
# GENERAL LINUX
apt-get update # updates the package index cache
apt-get upgrade -y # updates packages
# installs system tools
apt-get install -y bzip2 gcc git htop screen vim wget
apt-get upgrade -y bash # upgrades bash if necessary
apt-get clean # cleans up the package index cache

# INSTALL MINICONDA
# downloads Miniconda
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_  
64.sh -O \ Miniconda.sh
bash Miniconda.sh -b # installs it
rm -rf Miniconda.sh # removes the installer
export PATH="/root/miniconda3/bin:$PATH" # prepends the new path

# INSTALL PYTHON LIBRARIES
conda update -y conda python # updates conda & Python (if required)
conda install -y pandas # installs pandas
conda install -y ipython # installs IPython shell

例2-2中的Dockerfile使用例2-1中的bash脚本,从而构建了一个新的Docker镜像。它的主要部分也有内嵌注释。

例2-2 构建镜像的Dockerfile

#
# Building a Docker Image with
# the Latest Ubuntu Version and
# Basic Python Install
#
# Python for Finance, 2nd ed.
# (c) Dr. Yves J. Hilpisch
#

# latest Ubuntu version
FROM ubuntu:latest

# information about maintainer
MAINTAINER yves

# add the bash script
ADD install.sh /

# change rights for the script
RUN chmod u+x /install.sh

# run the bash script
RUN /install.sh

# prepend the new path
ENV PATH /root/miniconda3/bin:$PATH

# execute IPython when container is run
CMD ["ipython"]

如果这两个文件在一个文件夹里且安装了Docker,那么构建新镜像就很简单了。这里为镜像使用了ubuntupython标签,这个标签是引用镜像时必需的,例如在根据它运行容器时。

~/Docker$ docker build -t py4fi:basic .

...

Removing intermediate container 5fec0c9b2239
 ---> accee128d9e9
Step 6/7 : ENV PATH /root/miniconda3/bin:$PATH
 ---> Running in a2bb97686255
Removing intermediate container a2bb97686255
 ---> 73b00c215351
Step 7/7 : CMD ["ipython"]
 ---> Running in ec7acd90c991
Removing intermediate container ec7acd90c991
 ---> 6c36b9117cd2
Successfully built 6c36b9117cd2
Successfully tagged py4fi:basic
~/Docker$

现有Docker镜像可以用docker images列出。新镜像出现在列表的开头:

(py4fi) ~/Docker$ docker images
REPOSITORY       TAG            IMAGE ID      CREATED             SIZE
py4fi            basic          f789dd230d6f  About a minute ago  1.79GB
ubuntu           latest         cd6d8154f1e1  9 days ago          84.1MB
(py4fi) ~/Docker$

成功地构建py4fi:basic之后,你就可以用docker run运行对应的Docker容器。参数组合-ti是在Docker容器内部运行交互过程(如Shell过程)时所需的(参见docker run参考页面):

~/Docker$ docker run -ti py4fi:basic
Python 3.7.0 (default, Jun 28 2018, 13:15:42)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.5.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: import numpy as np

In [2]: a = np.random.standard_normal((5, 3))

In [3]: import pandas as pd

In [4]: df = pd.DataFrame(a, columns=['a', 'b', 'c'])

In [5]: df
Out[5]:
          a         b        c
0 -1.412661 -0.881592 1.704623
1 -1.294977  0.546676 1.027046
2 1.156361   1.979057 0.989772
3 0.546736  -0.479821 0.693907
4 -1.972943 -0.193964 0.769500

In [6]:

退出IPython也将退出该容器,因为IPython是容器中运行的唯一应用程序。不过,你可以输入Ctrl-P、Ctrl-Q来卸下容器。

卸下容器之后,docker ps命令仍会显示运行中的容器(以及当前运行的其他任何容器):

~/Docker$ docker ps
CONTAINER ID  IMAGE         COMMAND     CREATED            STATUS
e815df8f0f4d  py4fi:basic   "ipython"   About a minute ago Up About a minute
4518917de7dc  ubuntu:latest "/bin/bash" About an hour ago  Up About an hour
d081b5c7add0  ubuntu:latest "/bin/bash" 21 hours ago       Up 21 hours
~/Docker$

Docker容器的连接可用docker attach $CONTAINER_ID命令完成(注意,$CONTAINER_ID只需要几个字符就够了):

~/Docker$ docker attach e815d

In [6]: df.info()
<class 'pandas.core.frame.DataFrame'>
RangeIndex: 5 entries, 0 to 4
Data columns (total 3 columns):
a    5 non-null float64
b    5 non-null float64
c    5 non-null float64
dtypes: float64(3)
memory usage: 200.0 bytes

In [7]: exit
~/Docker$

exit命令会终止IPython并停止Docker容器。容器可用docker rm删除:

~/Docker$ docker rm e815d
e815d
~/Docker$

类似地,如果不再需要Docker容器py4fi:basic,可以通过docker rmi删除。虽然容器相对轻量,但单独容器仍可能消耗相当一部分存储容量。以py4fi:basic为例,其大小接近2GB。这也就是你可能想要定期清理Docker镜像列表的原因:

~/Docker$ docker rmi 6c36b9117cd2

当然,关于Docker容器及其在某些应用场景中的好处,还有许多好的讲解。但对于本书,你只需要知道,容器为部署Python、在完全独立(容器化)的环境中完成Python开发和为交付算法交易代码提供了一种现代化方法,就足够了。

 

Docker容器的好处

如果你还没有使用Docker容器,应该考虑试试它。它们为Python部署与开发工作提供了许多好处,不仅在本地工作时如此,在使用远程云实例与服务器部署算法交易代码时更具优势。

本节介绍在DigitalOcean云实例上建立全套Python基础架构的方法。其他的云提供商还有很多,如业界领先的Amazon Web Services。但是Digital Ocean以简易而闻名,对于小型云实例(称作水滴(Droplet))来说,价格也相对低。研究和开发通常使用最小的Droplet就足够了,其费用只有每月5美元(或者每小时0.007美元)。收费按小时计算,因此人们可以轻松地使用一个Droplet两个小时,然后将其删除,这只需要支付0.014美元。[9]

本节的目标是在DigitalOcean上建立一个Droplet,它包含Python 3.7安装包和典型的软件包(例如NumPy、pandas),并与一个密码保护、用安全套接字层(SSL)加密的Jupyter Notebook服务器安装相结合。这个服务器安装将提供3个可通过常规浏览器使用的重要工具。

Jupyter Notebook

流行的交互开发环境,其特点是可以选择不同语言内核(例如,Python、R和Julia)。

终端

可通过浏览器访问的系统Shell实现,能完成所有典型系统管理任务、对Vim和git等实用工具的使用。

编辑器

基于浏览器的文件编辑器,可以对许多不同编程语言及文件类型的语法高亮显示,还具有典型的文本/代码编辑功能。

在Droplet上安装Jupyter Notebook之后,你可以通过浏览器进行Python开发和部署,而不需要通过安全外壳(SSH)访问、登录云实例。

要实现本节的目标,需要几个文件。

服务器设置脚本

这个脚本协调所有必要步骤,例如将其他文件复制到Droplet中,并在其上运行。

Python和Jupyter安装脚本

这个脚本用于安装Python、附加软件包和Jupyter Notebook,并启动Jupyter Notebook服务器。

Jupyter Notebook配置文件

这个文件用于配置Jupyter Notebook服务器,例如有关密码保护的细节。

RSA公钥与私钥文件

这两个文件是Jupyter Notebook服务器SSL加密时所需的。

下面的小节以相反的次序来处理上述文件。

为了通过任意浏览器建立与Jupyter Notebook服务器的安全连接,我们需要一个包含RSA公钥和私钥的SSL证书。一般来说,这样的证书来自所谓的证书颁发机构(CA)。但是,在本书中,自生成的证书就“足够好”了。[10]生成RSA密钥对的流行工具之一是OpenSSL。下面简短的交互会话说明如何生成用于Jupyter Notebook服务器的证书(在提示符后面插入你自己的国家名称和其他字段):

~/cloud$ openssl req -x509 -nodes -days 365 -newkey \
> rsa:1024 -out cert.pem -keyout cert.key
Generating a 1024 bit RSA private key
..++++++
.......++++++
writing new private key to 'cert.key'

系统将要求你输入加进证书请求中的信息。你将输入所谓的可识别名称(DN)。需要输入的字段有多个,但你可以将某些留空,其他一些则用默认值。如果输入“.”,字段将留空:

Country Name (2 letter code) [AU]:DE
State or Province Name (full name) [Some-State]:Saarland
Locality Name (eg, city) []:Voelklingen
Organization Name (eg, company) [Internet Widgits Pty Ltd]:TPQ GmbH
Organizational Unit Name (eg, section) []:Python for Finance
Common Name (e.g. server FQDN or YOUR name) []:Jupyter
Email Address []:team@tpq.io
~/cloud$ ls
cert.key cert.pem
~/cloud$

cert.key和cert.pem这两个文件必须复制到Droplet中,由Jupyter Notebook配置文件引用。下面介绍配置文件。

你可以按照Jupyter Notebook文档中的解释来部署一个公共Jupyter Notebook服务器。除了其他特性之外,Jupyter Notebook还可以加上密码保护。为此,notebook.auth子软件包提供了一个密码散列代码生成函数passwd()。以下代码生成密码为jupyter的散列代码:

~/cloud$ ipython
Python 3.7.0 (default, Jun 28 2018, 13:15:42)
Type 'copyright', 'credits' or 'license' for more information
IPython 6.5.0 -- An enhanced Interactive Python. Type '?' for help.

In [1]: from notebook.auth import passwd

In [2]: passwd('jupyter')
Out[2]: 'sha1:d4d34232ac3a:55ea0ffd78cc3299e3e5e6ecc0d36be0935d424b'

In [3]: exit

这个散列代码必须放在例2-3提供的Jupyter Notebook配置文件中。该配置文件假定RSA公钥文件已经复制到Droplet上的/root/.jupyter/文件夹中。

例2-3 Jupyter Notebook配置文件

#
# Jupyter Notebook Configuration File
#
# Python for Finance, 2nd ed.
# (c) Dr. Yves J. Hilpisch
#
# SSL ENCRYPTION
# replace the following filenames (and files used) with your choice/files
c.NotebookApp.certfile = u'/root/.jupyter/cert.pem'
c.NotebookApp.keyfile = u'/root/.jupyter/cert.key'

# IP ADDRESS AND PORT
# set ip to '*' to bind on all IP addresses of the cloud instance
c.NotebookApp.ip = '*'
# it is a good idea to set a known, fixed default port for server access
c.NotebookApp.port = 8888

# PASSWORD PROTECTION
# here: 'jupyter' as password
# replace the hash code with the one for your strong password

c.NotebookApp.password = 'sha1:d4d34232ac3a:55ea0ffd78cc3299e3e5e6ecc0d36be0935d424b'
# NO BROWSER OPTION
# prevent Jupyter from trying to open a browser
c.NotebookApp.open_browser = False

 

Jupyter与安全性

在云端部署Jupyter Notebook会引起一些安全问题,因为这是一个通过浏览器访问的完整开发环境。因此,最重要的是使用Jupyter Notebook服务器提供的安全措施,例如密码保护和SSL加密。但这只是开始:建议根据在云实例上完成的工作采取进一步的安全措施。

下一步是确保将Python和Jupyter Notebook安装在Droplet上。

安装 Python 和 Jupyter Notebook 的 bash 脚本与 2.3 节中通过 Docker 容器里的Miniconda安装Python的脚本类似。但是,例2-4中的脚本还需要启动Jupyter Notebook服务器。所有的重要部分和代码行都有内嵌注释。

例2-4 安装Python和运行Jupyter Notebook服务器的bash脚本

#!/bin/bash
#
# Script to Install
# Linux System Tools,
# Basic Python Packages and
# Jupyter Notebook Server
#
# Python for Finance, 2nd ed.
# (c) Dr. Yves J. Hilpisch
#
# GENERAL LINUX
apt-get update # updates the package index cache
apt-get upgrade -y # updates packages
apt-get install -y bzip2 gcc git htop screen vim wget # installs system tools
apt-get upgrade -y bash # upgrades bash if necessary
apt-get clean # cleans up the package index cache

# INSTALLING MINICONDA
wget https://repo.continuum.io/miniconda/Miniconda3-latest-Linux-x86_  
64.sh -O \ Miniconda.sh
bash Miniconda.sh -b # installs Miniconda
rm Miniconda.sh # removes the installer
# prepends the new path for current session
export PATH="/root/miniconda3/bin:$PATH"
# prepends the new path in the shell configuration
echo ". /root/miniconda3/etc/profile.d/conda.sh" >> ~/.bashrc
echo "conda activate" >> ~/.bashrc

# INSTALLING PYTHON LIBRARIES
# More packages can/must be added
# depending on the use case.
conda update -y conda # updates conda if required
conda create -y -n py4fi python=3.7 # creates an environment
source activate py4fi # activates the new environment
conda install -y jupyter # interactive data analytics in the browser
conda install -y pytables # wrapper for HDF5 binary storage
conda install -y pandas # data analysis package
conda install -y matplotlib # standard plotting library
conda install -y scikit-learn # machine learning library
conda install -y openpyxl # library for Excel interaction
conda install -y pyyaml # library to manage YAML files

pip install --upgrade pip # upgrades the package manager
pip install cufflinks # combining plotly with pandas

# COPYING FILES AND CREATING DIRECTORIES
mkdir /root/.jupyter
mv /root/jupyter_notebook_config.py /root/.jupyter/
mv /root/cert.* /root/.jupyter
mkdir /root/notebook
cd /root/notebook

# STARTING JUPYTER NOTEBOOK
jupyter notebook --allow-root

# STARTING JUPYTER NOTEBOOK
# as background process:
# jupyter notebook --allow-root &

这个脚本必须复制到Droplet,并由下一小节介绍的编配脚本启动。

设置Droplet的第二个bash脚本最短(例2-5)。它主要的作用是将所有其他文件复制到Droplet中,Droplet的IP地址是脚本的一个参数。脚本的最后一行用于启动install.sh脚本,后者安装完成后启动Jupyter Notebook服务器。

例2-5 设置Droplet的bash脚本

#!/bin/bash
#
# Setting up a DigitalOcean Droplet
# with Basic Python Stack
# and Jupyter Notebook
#
# Python for Finance, 2nd ed.
# (c) Dr Yves J Hilpisch
#

# IP ADDRESS FROM PARAMETER
MASTER_IP=$1

# COPYING THE FILES
scp install.sh root@${MASTER_IP}:
scp cert.* jupyter_notebook_config.py root@${MASTER_IP}:

# EXECUTING THE INSTALLATION SCRIPT
ssh root@${MASTER_IP} bash /root/install.sh

现在,设置代码的所有条件都已经具备。在DigitalOcean上,用如下选项创建一个新的Droplet。

操作系统

Ubuntu 18.10 x64(本书写作时最新的版本)。

大小

1个内核、1GB内存、25GB SSD(最小的Droplet)。

数据中心所在地区

法兰克福(因为作者住在德国)。

SSH密钥

添加一个(新)SSH密钥,用于无密码登录。[11]

Droplet名称

你可以使用预先指定的名称,或者选择py4fi等名称。

单击Create(创建)按钮启动Droplet创建过程,该过程通常需要花费一分钟。设置过程的主要结果是一个IP地址,如果你选择法兰克福作为数据中心位置,这个地址可能是46.101.156.199。现在,设置Droplet只需要以下简单命令:

(py3) ~/cloud$ bash setup.sh 46.101.156.199

后续的过程可能需要几分钟。结束时,Jupyter Notebook服务器将显示以下信息:

The Jupyter Notebook is running at: https://[all ip addresses on your 
system]:8888/

在任何现代浏览器中,访问以下地址都可以访问运行中的Jupyter Notebook服务器(注意https协议):

https://46.101.156.199:8888

服务器可能要求你添加一个安全例外,添加后应该会出现Jupyter Notebook登录屏幕,提示输入密码(我们的例子中是jupyter)。现在,你已经做好准备,在浏览器中通过Jupyter Notebook、通过终端窗口中的IPython或者文本文件编辑器开始Python开发。其他文件管理功能(如文件上传、删除和文件夹创建)也已经具备。

 

云的好处

DigitalOcean等公司提供的云实例和Jupyter Notebook组合起来很强大,使Python开发人员和“宽客”可以使用专业的计算和存储基础设施。专业的云和数据中心提供商确保你的(虚拟)机器的物理安全和高可用性。使用云实例还可以将研究和开发阶段的成本保持在较低的水平,因为收费通常按照使用的小时数计算,不需要签订长期的协议。

Python是本书选用的编程语言和技术平台,并且它被几乎所有领先的金融机构采用。不过,Python开发可能很难,有时候甚至是乏味且令人头疼的。幸运的是,近年来已经出现了许多协助解决部署问题的技术。开源项目conda可以帮助管理Python软件包和虚拟环境。Docker容器更进一步,可以轻松地在技术上隔离的“沙箱”(容器)中创建完整的文件系统和运行时环境。DigitalOcean等云提供商更能在几分钟之内,提供专业管理的安全数据中心内的计算及存储能力,按照小时收费。这些技术与Python 3.7安装和安全的Jupyter Notebook服务器安装相结合,为Python金融项目的开发和部署提供了专业化的环境。

Python软件包管理可以参考如下资源:

虚拟环境管理可以参考如下资源:

下面的资源提供关于Docker容器的信息:

bash脚本语言的简介与概述参见:

Jupyter Notebook文档解释了安全运行公共Jupyter Notebook服务器的方法。JupyterHub是管理Jupyter Notebook服务器的多个用户的一个中心。

通过推荐人的链接注册DigitalOcean,并在新账户中得到10美元的起始余额。这可以支付最小Droplet两个月的使用费。

[1] 本版基于CPython 3.7(写作时最新的主版本),这是Python编程语言最受欢迎的原创版本。——原注

[2] 最新的pipenv项目结合了包管理器pip和虚拟环境管理器virtualenv的功能。——原注

[3] Miniconda安装程序通常不像conda和Python那样经常更新。——原注

[4] 安装元软件包nomkl(例如使用命令conda install numpy nomkl),可以避免自动安装和使用mkl及其他相关软件包。——原注

[5] 在Python的官方文档中,可以找到如下解释:“Python‘虚拟环境’允许Python软件包安装于特定应用的独立位置中,而不是全局安装。”——原注

[6] Docker技术的全面介绍参见Matthias and Kane(2015)。——原注

[7] 如果对这个术语的理解还不够清晰,不用担心,第6章将做进一步介绍。——原注

[8] Consult Robbins (2016)对bash脚本做了简洁的介绍和概述。——原注

[9] 通过推荐链接注册的新用户可以得到Digital Ocean的10美元信用额度。——原注

[10] 如果使用自生成证书,你可能需要在浏览器提示时添加一个安全例外。——原注

[11] 如果需要帮助,访问“How to Add SSH Keys to Droplets”或者“How to Create SSH Keys with PuTTY on Windows”网页。——原注


相关图书

Python极客项目编程(第2版)
Python极客项目编程(第2版)
动手学自然语言处理
动手学自然语言处理
Python财务应用编程
Python财务应用编程
深度学习的数学——使用Python语言
深度学习的数学——使用Python语言
Web应用安全
Web应用安全
Python+ChatGPT办公自动化实战
Python+ChatGPT办公自动化实战

相关文章

相关课程