Python 金融编程第二版(GPT 重译)(一)(4)https://developer.aliyun.com/article/1559389
零基编号
与其他一些编程语言(如Matlab
)相比,Python
使用零基编号方案。例如,tuple
对象的第一个元素的索引值为 0。
这种对象类型提供的特殊方法仅有两个:count
和index
。第一个方法统计某个对象的出现次数,第二个方法给出其第一次出现的索引值:
In [100]: t.count('data') Out[100]: 1 In [101]: t.index(1) Out[101]: 0
tuple
对象是不可变对象。这意味着一旦定义,它们就不容易更改。
列表
类型为list
的对象比tuple
对象更加灵活和强大。从财务角度来看,你可以仅使用list
对象就能实现很多,比如存储股价报价和添加新数据。list
对象通过括号定义,其基本功能和行为与tuple
对象相似:
In [102]: l = [1, 2.5, 'data'] l[2] Out[102]: 'data'
也可以通过使用函数list
来定义或转换list
对象。以下代码通过转换前面示例中的tuple
对象生成一个新的list
对象:
In [103]: l = list(t) l Out[103]: [1, 2.5, 'data'] In [104]: type(l) Out[104]: list
除了tuple
对象的特性外,list
对象还可以通过不同的方法进行扩展和缩减。换句话说,虽然string
和tuple
对象是不可变序列对象(具有索引),一旦创建就无法更改,但list
对象是可变的,并且可以通过不同的操作进行更改。你可以将list
对象附加到现有的list
对象上,等等:
In [105]: l.append([4, 3]) ![1](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/1.png) l Out[105]: [1, 2.5, 'data', [4, 3]] In [106]: l.extend([1.0, 1.5, 2.0]) ![2](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/2.png) l Out[106]: [1, 2.5, 'data', [4, 3], 1.0, 1.5, 2.0] In [107]: l.insert(1, 'insert') ![3](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/3.png) l Out[107]: [1, 'insert', 2.5, 'data', [4, 3], 1.0, 1.5, 2.0] In [108]: l.remove('data') ![4](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/4.png) l Out[108]: [1, 'insert', 2.5, [4, 3], 1.0, 1.5, 2.0] In [109]: p = l.pop(3) ![5](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/5.png) print(l, p) [1, 'insert', 2.5, 1.0, 1.5, 2.0] [4, 3]
在末尾附加list
对象。
添加list
对象的元素。
在索引位置之前插入对象。
删除对象的第一次出现。
删除并返回索引位置的对象。
切片也很容易实现。在这里,切片指的是将数据集分解为较小部分(感兴趣的部分)的操作:
In [110]: l[2:5] ![1](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/1.png) Out[110]: [2.5, 1.0, 1.5]
第三到第五个元素。
Table 3-2 提供了list
对象的选定操作和方法的摘要。
表 3-2. list
对象的选定操作和方法
方法 | 参数 | 返回/结果 |
l[i] = x |
[i] |
将第i 个元素替换为x |
l[i:j:k] = s |
[i:j:k] |
用s 替换从i 到j-1 的每个第k 个元素 |
append |
(x) |
将x 附加到对象 |
count |
(x) |
对象x 的出现次数 |
del l[i:j:k] |
[i:j:k] |
删除索引值为i 到j-1 的元素 |
extend |
(s) |
将s 的所有元素附加到对象 |
index |
(x[, i[, j]]) |
元素i 和j-1 之间x 的第一个索引 |
insert |
(i, x) |
在索引i 之前/后插入x |
remove |
(i) |
删除索引为i 的元素 |
pop |
(i) |
删除索引为i 的元素并返回它 |
reverse |
() |
将所有项目原地颠倒 |
sort |
([cmp[, key[, reverse]]]) |
原地对所有项目排序 |
专题:控制结构
虽然控制结构本身是一个专题,像for
循环这样的控制结构可能最好是基于Python
中的list
对象介绍的。这是因为一般情况下循环是在list
对象上进行的,这与其他语言中通常的标准相当不同。看下面的例子。for
循环遍历list
对象l
的元素,索引值为 2 到 4,并打印出相应元素的平方。注意第二行缩进(空格)的重要性:
In [111]: for element in l[2:5]: print(element ** 2) 6.25 1.0 2.25
这相比于典型的基于计数器的循环提供了非常高的灵活性。基于(标准的)list
对象range
也可以使用计数器进行循环:
In [112]: r = range(0, 8, 1) ![1](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/1.png) r Out[112]: range(0, 8) In [113]: type(r) Out[113]: range
参数是start
、end
、step size
。
为了比较,相同的循环使用range
实现如下:
In [114]: for i in range(2, 5): print(l[i] ** 2) 6.25 1.0 2.25
遍历列表
在Python
中,你可以遍历任意的list
对象,不管对象的内容是什么。这通常避免了引入计数器。
Python
还提供了典型的(条件)控制元素if
、elif
和else
。它们在其他语言中的使用方式类似:
In [115]: for i in range(1, 10): if i % 2 == 0: ![1](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/1.png) print("%d is even" % i) elif i % 3 == 0: print("%d is multiple of 3" % i) else: print("%d is odd" % i) 1 is odd 2 is even 3 is multiple of 3 4 is even 5 is odd 6 is even 7 is odd 8 is even 9 is multiple of 3
%
代表取模。
同样,while
提供了另一种控制流的手段:
In [116]: total = 0 while total < 100: total += 1 print(total) 100
Python
的一个特点是所谓的list
推导式。与遍历现有list
对象不同,这种方法以一种相当紧凑的方式通过循环生成list
对象:
In [117]: m = [i ** 2 for i in range(5)] m Out[117]: [0, 1, 4, 9, 16]
从某种意义上说,这已经提供了一种生成“类似”的向量化代码的第一手段,因为循环相对来说更加隐式而不是显式的(代码的向量化将在本章后面更详细地讨论)。
专题:功能编程
Python
还提供了一些功能编程支持工具,即将函数应用于整套输入(在我们的情况下是list
对象)。其中包括filter
、map
和reduce
。然而,我们首先需要一个函数定义。首先从一个非常简单的函数开始,考虑一个返回输入x
的平方的函数f
:
In [118]: def f(x): return x ** 2 f(2) Out[118]: 4
当然,函数可以是任意复杂的,具有多个输入/参数对象,甚至多个输出(返回对象)。但是,考虑以下函数:
In [119]: def even(x): return x % 2 == 0 even(3) Out[119]: False
返回对象是一个布尔值。这样的函数可以通过使用 map
应用于整个 list
对象:
In [120]: list(map(even, range(10))) Out[120]: [True, False, True, False, True, False, True, False, True, False]
为此,我们还可以直接将函数定义作为 map
的参数提供,通过使用 lambda
或匿名函数:
In [121]: list(map(lambda x: x ** 2, range(10))) Out[121]: [0, 1, 4, 9, 16, 25, 36, 49, 64, 81]
函数也可以用于过滤 list
对象。在下面的示例中,过滤器返回符合由 even
函数定义的布尔条件的 list
对象元素:
In [122]: list(filter(even, range(15))) Out[122]: [0, 2, 4, 6, 8, 10, 12, 14]
列表推导、函数式编程、匿名函数
在 Python
级别尽可能避免使用循环被认为是良好的实践。list
推导和函数式编程工具如 map
、filter
和 reduce
提供了编写没有(显式)循环的代码的方法,这种代码既紧凑又通常更可读。在这种情况下,lambda
或匿名函数也是强大的工具。
字典
dict
对象是字典,也是可变序列,允许通过可以是 string
对象的键来检索数据。它们被称为键值存储。虽然 list
对象是有序且可排序的,但 dict
对象是无序且不可排序的。通过示例可以更好地说明与 list
对象的进一步差异。花括号是定义 dict
对象的标志:
In [123]: d = { 'Name' : 'Angela Merkel', 'Country' : 'Germany', 'Profession' : 'Chancelor', 'Age' : 63 } type(d) Out[123]: dict In [124]: print(d['Name'], d['Age']) Angela Merkel 63
同样,这类对象具有许多内置方法:
In [125]: d.keys() Out[125]: dict_keys(['Name', 'Country', 'Profession', 'Age']) In [126]: d.values() Out[126]: dict_values(['Angela Merkel', 'Germany', 'Chancelor', 63]) In [127]: d.items() Out[127]: dict_items([('Name', 'Angela Merkel'), ('Country', 'Germany'), ('Profession', 'Chancelor'), ('Age', 63)]) In [128]: birthday = True if birthday is True: d['Age'] += 1 print(d['Age']) 64
有几种方法可以从 dict
对象获取 iterator
对象。当进行迭代时,这些对象的行为类似于 list
对象:
In [129]: for item in d.items(): print(item) ('Name', 'Angela Merkel') ('Country', 'Germany') ('Profession', 'Chancelor') ('Age', 64) In [130]: for value in d.values(): print(type(value)) <class 'str'> <class 'str'> <class 'str'> <class 'int'>
表 3-3 提供了 dict
对象的选定操作和方法的摘要。
表 3-3. dict
对象的选定操作和方法
方法 | 参数 | 返回/结果 |
d[k] |
[k] |
d 中具有键 k 的项目 |
d[k] = x |
[k] |
将项目键 k 设置为 x |
del d[k] |
[k] |
删除具有键 k 的项目 |
clear |
() |
删除所有项目 |
copy |
() |
复制一个副本 |
has_key |
(k) |
如果 k 是键,则为 True |
items |
() |
迭代器遍历所有项目 |
keys |
() |
迭代器遍历所有键 |
values |
() |
迭代器遍历所有值 |
popitem |
(k) |
返回并删除具有键 k 的项目 |
update |
([e]) |
用 e 中的项目更新项目 |
集合
我们将考虑的最后一个数据结构是 set
对象。尽管集合论是数学和金融理论的基石,但对于 set
对象的实际应用并不太多。这些对象是其他对象的无序集合,每个元素只包含一次:
In [131]: s = set(['u', 'd', 'ud', 'du', 'd', 'du']) s Out[131]: {'d', 'du', 'u', 'ud'} In [132]: t = set(['d', 'dd', 'uu', 'u'])
使用 set
对象,您可以像在数学集合论中一样实现操作。例如,您可以生成并集、交集和差异:
In [133]: s.union(t) ![1](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/1.png) Out[133]: {'d', 'dd', 'du', 'u', 'ud', 'uu'} In [134]: s.intersection(t) ![2](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/2.png) Out[134]: {'d', 'u'} In [135]: s.difference(t) ![3](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/3.png) Out[135]: {'du', 'ud'} In [136]: t.difference(s) ![4](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/4.png) Out[136]: {'dd', 'uu'} In [137]: s.symmetric_difference(t) ![5](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/5.png) Out[137]: {'dd', 'du', 'ud', 'uu'}
s
和 t
的全部。
在 s
和 t
中都有。
在 s
中但不在 t
中。
在 t
中但不在 s
中。
在其中一个但不是两者都。
set
对象的一个应用是从list
对象中消除重复项。例如:
In [138]: from random import randint l = [randint(0, 10) for i in range(1000)] ![1](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/1.png) len(l) ![2](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/2.png) Out[138]: 1000 In [139]: l[:20] Out[139]: [10, 9, 2, 4, 5, 1, 7, 4, 6, 10, 9, 5, 4, 6, 10, 3, 4, 7, 0, 5] In [140]: s = set(l) s Out[140]: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
1,000 个 0 到 10 之间的随机整数。
l
中的元素数量。
结论
基本的Python
解释器已经提供了丰富灵活的数据结构。从金融的角度来看,以下可以被认为是最重要的:
基本数据类型
在金融中,int
、float
和string
类提供了原子数据类型。
标准数据结构
tuple
、list
、dict
和set
类在金融领域有许多应用领域,其中list
通常是最灵活的通用工作马。
进一步资源
本章重点讨论可能对金融算法和应用特别重要的问题。但是,它只能代表探索Python
中数据结构和数据建模的起点。有许多宝贵的资源可供进一步深入了解。
书籍形式的良好参考资料包括:
- Goodrich, Michael 等(2013):Python 数据结构与算法. John Wiley & Sons, Hoboken, NJ.
- Harrison, Matt (2017): Python 3 图解指南. Treading on Python Series.
- Ramalho, Luciano (2016): 流畅的 Python. O’Reilly, Beijing et al.
¹ Cython
库将静态类型和编译功能引入Python
,与C
中的相似。实际上,Cython
是Python
和C
的混合语言。
² 在这里和后续讨论中,诸如float、float 对象等术语可互换使用,承认每个float也是一个对象。对于其他对象类型也是如此。
³ 参考http://en.wikipedia.org/wiki/Double-precision_floating-point_format。
⁴ 在这里不可能详细介绍,但互联网上有大量关于正则表达式的信息,特别是针对Python
。关于这个主题的介绍,请参阅 Fitzgerald, Michael (2012): 正则表达式入门. O’Reilly, Sebastopol, CA.
石,但对于 set
对象的实际应用并不太多。这些对象是其他对象的无序集合,每个元素只包含一次:
In [131]: s = set(['u', 'd', 'ud', 'du', 'd', 'du']) s Out[131]: {'d', 'du', 'u', 'ud'} In [132]: t = set(['d', 'dd', 'uu', 'u'])
使用 set
对象,您可以像在数学集合论中一样实现操作。例如,您可以生成并集、交集和差异:
In [133]: s.union(t) ![1](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/1.png) Out[133]: {'d', 'dd', 'du', 'u', 'ud', 'uu'} In [134]: s.intersection(t) ![2](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/2.png) Out[134]: {'d', 'u'} In [135]: s.difference(t) ![3](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/3.png) Out[135]: {'du', 'ud'} In [136]: t.difference(s) ![4](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/4.png) Out[136]: {'dd', 'uu'} In [137]: s.symmetric_difference(t) ![5](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/5.png) Out[137]: {'dd', 'du', 'ud', 'uu'}
[外链图片转存中…(img-jRWfaNE1-1717935840758)]
s
和 t
的全部。
[外链图片转存中…(img-PwcZYTDE-1717935840758)]
在 s
和 t
中都有。
[外链图片转存中…(img-SoZkO8vS-1717935840758)]
在 s
中但不在 t
中。
[外链图片转存中…(img-3xnwT7OQ-1717935840759)]
在 t
中但不在 s
中。
[外链图片转存中…(img-rNDbfeFX-1717935840759)]
在其中一个但不是两者都。
set
对象的一个应用是从list
对象中消除重复项。例如:
In [138]: from random import randint l = [randint(0, 10) for i in range(1000)] ![1](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/1.png) len(l) ![2](https://gitee.com/OpenDocCN/ibooker-quant-zh/raw/master/docs/py-fin-2e/img/2.png) Out[138]: 1000 In [139]: l[:20] Out[139]: [10, 9, 2, 4, 5, 1, 7, 4, 6, 10, 9, 5, 4, 6, 10, 3, 4, 7, 0, 5] In [140]: s = set(l) s Out[140]: {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10}
[外链图片转存中…(img-kYDec8em-1717935840759)]
1,000 个 0 到 10 之间的随机整数。
[外链图片转存中…(img-WiF4IKCk-1717935840759)]
l
中的元素数量。
结论
基本的Python
解释器已经提供了丰富灵活的数据结构。从金融的角度来看,以下可以被认为是最重要的:
基本数据类型
在金融中,int
、float
和string
类提供了原子数据类型。
标准数据结构
tuple
、list
、dict
和set
类在金融领域有许多应用领域,其中list
通常是最灵活的通用工作马。
进一步资源
本章重点讨论可能对金融算法和应用特别重要的问题。但是,它只能代表探索Python
中数据结构和数据建模的起点。有许多宝贵的资源可供进一步深入了解。
书籍形式的良好参考资料包括:
- Goodrich, Michael 等(2013):Python 数据结构与算法. John Wiley & Sons, Hoboken, NJ.
- Harrison, Matt (2017): Python 3 图解指南. Treading on Python Series.
- Ramalho, Luciano (2016): 流畅的 Python. O’Reilly, Beijing et al.
¹ Cython
库将静态类型和编译功能引入Python
,与C
中的相似。实际上,Cython
是Python
和C
的混合语言。
² 在这里和后续讨论中,诸如float、float 对象等术语可互换使用,承认每个float也是一个对象。对于其他对象类型也是如此。
³ 参考http://en.wikipedia.org/wiki/Double-precision_floating-point_format。
⁴ 在这里不可能详细介绍,但互联网上有大量关于正则表达式的信息,特别是针对Python
。关于这个主题的介绍,请参阅 Fitzgerald, Michael (2012): 正则表达式入门. O’Reilly, Sebastopol, CA.