《Python核心技术与实战》学习笔记
动机
最近在极客时间上买了一个课程名字叫《Python核心技术与实战》。链接戳这里:https://time.geekbang.org/column/intro/176
我挺喜欢这种课程形式:一个业内比较资深的老师整理内容,然后找一个专业的声优再朗读一遍;文章中还有一些代码。我比较习惯上下班的时候听,这种碎片时间巩固下编程语言还是可以的。
不过后面感觉这个课程讲的不错,有些内容值得复习和深度阅读,因此开这篇笔记。
基础篇
01 | 如何逐步突破,成为Python高手?
02 | Jupyter Notebook为什么是现代Python的必学技术?
Jupyter Notebook的优点:
- 整合所有的资源
- 交互性编程体验
- 零成本重现结果
03 | 列表和元组,到底用哪一个?
基础区别:
- 列表是动态的,长度大小不固定,可以随意地增加、删减或者改变元素(mutable)。
- 而元组是静态的,长度大小固定,无法增加删减或者改变(immutable).
04 | 字典、集合,你真的了解吗?
集合并不支持索引操作,因为集合本质上是一个哈希表,和列表不一样。
新版哈希表结构:
1 | Indices |
进阶篇
15 | Python对象的比较、拷贝
==
VS is
:
==
判断两个对象的值是否相等,执行a == b
相当于是去执行a.__eq__(b)
。is
比较两个对象的身份标识符是否相等。执行a is b
等价于id(a) == id(b)
17 | 强大的装饰器
函数装饰器
1 | def my_decorator(func): |
@
是语法糖@my_decorator
就相当于前面的greet=my_decorator(greet)
- 一般使用装饰器后,原函数的元信息会丢失。使用
@functools.wrap
帮助保留原函数的元信息。
类装饰器
1 |
|
@Count
等价于example=Count(example)
- 后面继续调用
example()
等于调用Count
的__call__
18 | metaclass,是潘多拉魔盒还是阿拉丁神灯?
Meta
的两种意思:
- “Beyond”,例如技术词汇
metadata
,意思是描述数据的超越数据; - “Change”,例如技术词汇
metamorphosis
,意思是改变的形态。
即,metaclass
具有超越变形特性。
YAMLObject源代码:
1 | class YAMLObjectMetaclass(type): |
在你定义任何YAMLObject
子类时,Python会强行插入运行下面这段代码:
1 | cls.yaml_loader.add_constructor(cls.yaml_tag, cls.from_yaml) |
原理
- 所有Python的用户定义类都是
type
这个类的实例。class MyClass: ...
等价于MyClass = type(classname, superclasses, attributedict)
type
的__call__
又会进一步调用:type.__new__(typeclass, classname, superclasses, attributedict)
和type.__init__(class, classname, superclasses, attributedict)
metaclass
是type
的子类,通过重载type
的__call__
运算符,“超越变形”正常的类。
建议:metaclass
用于框架层开发,不用在应用层开发。
19 | 深入理解迭代器和生成器
对象的抽象就是类,而对象的集合就是容器。所有的容器都是可迭代的(iterable)。
- 可迭代对象(Iterable):实现了
__iter__
,通过iter()
函数可以返回一个迭代器。 - 迭代器(Iterator):实现了
__next__
,通过next()
方法,要么获取容器的下一个对象,要么得到一个StopIteration
错误。 - 生成器(Generator):生成器是懒人版的迭代器。外部程序在调用
next(gen)
时,进入生成器,直到yield
处返回,生成器暂停;下次再调用next(gen)
时,回到生成器继续执行直到下一处yield
。
21 | Python并发编程之Futures
并发 vs 并行
- 并发(Concurrency):多个任务同时进行,但在具体的同一时刻只有一个任务在进行。应用于
I/O 操作频繁的场景,比如你要从网站上下载多个文件,I/O 操作的时间可能会比 CPU
运行处理的时间长得多。python中一般用threading
和asyncio
。 - 并行(Parallelism):多个任务是同一时刻、同时发生。更多应用于 CPU heavy
的场景,比如 MapReduce
中的并行计算,为了加快运行速度,一般会用多台机器、多个处理器来完成。python中一般用multi-processing。
Futures
Python 中的 Futures
模块,位于 concurrent.futures
和 asyncio
中,它们都表示带有延迟的操作。
future = xxx.submit(func)
:future一般通过某个类的submit
方法生成。
future的重要方法:
done()
:表示相对应的操作是否完成,会立即返回结果。add_done_callback(fn)
:表示future完成后,回调函数fn
会被执行。result()
:表示当future完成后,返回其对应的结果或异常。as_completed(fs)
:给定的future迭代器fs
,在其完成后,返回完成后的迭代器。
22 | 并发编程之Asyncio
多线程的缺点
- 多线程运行过程容易被打断,出现资源竞争的现象;
- 线程切换本身存在一定的损耗,线程数不能无限增加。
sync vs. async
- 同步是指操作一个接一个执行(按顺序,等待上一个操作完成)。
- 异步是指不同的操作间可以互相交替执行。(交替,上一个操作如果被block,可以不等待,先执行)
asyncio工作原理
- 单线程,即主线程。
- 可以进行任务(对应特殊的future对象)切换。
- 不同的任务,被一个
event loop
对象控制,控制逻辑:- 维护两个任务状态列表:1.预备状态任务列表,该列表的任务目前随时准备开始运行;2.等待状态任务列表,该列表的任务已经运行但正在等待外部操作完成(比如IO)。
- 控制权:
event loop
选择task开始运行。- task运行直到结束或者等待。
event loop
根据task是结束还是等待,更新维护的两个状态列表,结束则放入预备状态列表,等待则放入等待状态列表。然后再次选择下一个要运行的task。
ayncio用法
async
和await
关键字是asyncio最新写法,表示这个语句 / 函数是 non-block
的。async
关键字定义一个协程(函数或者对象),await
关键字用于挂起阻塞的异步调用接口。如果一个对象可以在await
语句中使用,那么它就是awaitables
对象,有三种主要类型: coroutines
, Task
和 Future
.
asyncio.run()
是python3.7才引入的,老版本等价代码:
1 | loop = asyncio.get_event_loop() |
24 | 带你解析 Python 垃圾回收机制
sys.getrefcount()
函数可以查看一个对象的引用次数,该函数本身也会引入一次计数。
可以显式调用gc.collect()
,来启动垃圾回收。Python
使用标记清除(mark-sweep)算法和分代收集(generational),来启用针对循环引用的自动垃圾回收。
规范篇
29 | 巧用上下文管理器和With语句精简代码
基于类的上下文管理器
1 |
|
基于生成器的上下文管理器:
1 |
|
- 基于类的上下文管理器更加 flexible,适用于大型的系统开发;
- 而基于生成器的上下文管理器更加方便、简洁,适用于中小型程序。
量化交易实战篇
33 | 带你初探量化世界
程序化交易:它通常用计算机程序代替交易员,来具体执行金融产品的买卖。比如,一个基金经理需要卖出大量股票。如果直接挂一个大的卖单,可能会影响市场,那就用计算机程序拆分成小单慢慢执行。量化交易的下层通常是程序交易。
算法交易:通常用于高频交易中。它指的是,通过算法快速判定买卖的时间点,快速买卖多个产品。
量化交易:通常是指使用数学、统计甚至机器学习的方法,去找寻合适的买卖时机。所以,在这个维度的定义之下,算法交易、高频交易还有统计套利都可以算作量化交易。
盈透证券:提供支持股票、期权的行情数据获取和交易的接口。
Gemini、OKCoin(交易所):提供进行数字货币行情获取和交易的接口。
一个基本的交易系统包括:
- 行情模块:获取市场的行情数据,负责获取交易账户的状态。
- 策略模块:订阅市场的数据,根据设定的算法发出买、卖指令给执行模块。
- 执行模块:接受并把策略模块发过来的买、卖指令封装并转发到交易所;同时,监督并确保策略买卖的完整执行。
- 回测系统:模拟检测当前的策略。
34 | RESTful & Socket: 搭建交易执行层核心
REST 的全称是表征层状态转移(REpresentational State Transfer)。实质可以理解为:通过 URL 定位资源,用 GET、POST、PUT、DELETE 等动词来描述操作。每个 REST 请求都是独立的,不需要服务器在会话(Session)中缓存中间状态来完成这个请求,即无状态。
- maker:挂单者。
- taker:吃单者。
- 买(buy):用美元买入比特币的行为。
- 卖(sell):用比特币换取美元的行为。
- 市价单(market order):给交易所一个方向(买或者卖)和一个数量,交易所把给定数量的美元(或者比特币)换成比特币(或者美元)的单子。
- 限价单(limit order):给交易所一个价格、一个方向(买或者卖)和一个数量,交易所在价格达到给定价格的时候,把给定数量的美元(或者比特币)换成比特币(或者美元)的单子。
35 | RESTful & Socket: 行情数据对接和抓取
交易所主要有两种行情数据:委托账本(Order Book)和活动行情(Tick data)。
WebSocket 是一种在单个 TCP/TSL 连接上,进行全双工、双向通信的协议。WebSocket 可以让客户端与服务器之间的数据交换变得更加简单高效,服务端也可以主动向客户端推送数据。在 WebSocket API 中,浏览器和服务器只需要完成一次握手,两者之间就可以直接创建持久性的连接,并进行双向数据传输。
行情模块可以使用Gemini提供的两种Websocket接口:
- public:公开orderbook,每个人都能看到的当前挂单价和深度。
- private:个人订单被执行等变动的通知。
36 | Pandas & Numpy: 策略与回测系统
OHLCV 数据:开盘价(Open)、最高价(High)、最低价(Low)和收盘价(Close),还有一个成交量(Volume)。
常见的两类回测框架:
- 向量化回测框架:通常基于 Pandas+Numpy 来自己搭建计算核心;后端则是用 MySQL 或者 MongoDB 作为源。这种框架通过 Pandas+Numpy 对 OHLC 数组进行向量运算,可以在较长的历史数据上进行回测。不过,因为这类框架一般只用 OHLC,所以模拟会比较粗糙。
- 事件驱动型回测框架:本质上是针对每一个 tick 的变动或者 orderbook 的变动生成事件;然后,再把一个个事件交给策略进行执行。因此,虽然它的拓展性很强,可以允许更加灵活的策略,但回测速度是很慢的。
成熟的回测框架:
- Zipline,就是一个热门的事件驱动型回测框架,背后有大型社区和文档的支持。
- PyAlgoTrade 也是事件驱动的回测框架,文档相对完整,整合了知名的技术分析(Techique Analysis)库 TA-Lib。在速度和灵活方面,它比 Zipline 强。不过,它的一大硬伤是不支持 Pandas 的模块和对象。
37 | Kafka & ZMQ:自动化交易流水线
中间件,是将技术底层工具和应用层进行连接的组件。
简而言之,消息队列就是一个临时存放消息的容器,有人向消息队列中推送消息;有人则监听消息队列,发现新消息就会取走。根据我们刚刚对中间件的解释,清晰可见,消息队列也是一种中间件。
市面上使用较多的消息队列有 RabbitMQ、Kafka、RocketMQ、ZMQ 等。