01|Python 安装那些事
1.1 Python 安装
https://www.python.org
选择您对应的文件下载。
(图片来源于网络)
特别注意:图中箭头指向处一定要记得勾选上。否则得手动配置环境变量了哦。
Q:如何配置环境变量呢?
A:控制面板—系统与安全—系统—高级系统设置—环境变量—系统变量—双击 path—进入编辑环境变量窗口后在空白处填入 Python 所在路径—一路确定。
检查
1.2 Python 编译器 Sublime
http://www.sublimetext.com/
常见问题
02|Python 语言快速入门
本节虽是零基础友好文,但也有对一些知识点的深度拓展,有编程基础的看官也可以选择性观看哦!
2.1 Python 交互式模式与命令行模式
2.1.1 命令行模式
1.进入方式:
2. 提示符
2.1.2 交互式模式
1. 进入方式
2. 提示符
区别
py 文件只能在命令行中运行; Python 交互模式的代码是输入一行、执行一行;而命令行模式下直接运行 .py 文件是一次性执行该文件内的所有代码。
2.2 数据类型和变量
2.2.1 整数
2.2.2 浮点数
2.2.3 布尔值
var1==var2
==
2.2.4 字符串
'
"
'aaa'
"abc"
''
""
'aaa'
aaa
'
"
\
you’re
'
\
\
2.2.5 列表
2.2.6 元组
列表与元组的区别
元组使用小括号,列表使用方括号。 列表是动态的,长度大小不固定,可以随意地增加、删减或者改变元素(可变)。 元组是静态的,长度大小固定,无法增加删减或者改变(不可变)。
偷偷告诉你哦:
2.2.7 字典
2.2.8 集合
注意: set()
{}
{ }
拓展
Python 不可变对象:int、float、tuple、string Python 可变对象:list、dict、set
添加:append、insert。
删除:remove()、pop(索引)、pop()
修改:list [索引] = 元素
查找:list [索引]
2.2.9 变量
拓展
b=a
假设开发商 = 内存,变量 = 房子,变量存储的值 = 住户,在 b=a 前,a=1 的大趋势使得开发商把 a 房子建造好了,当 b=a 复制时,开发商又马不停蹄的画了块内存建了 b 房子,且 b 房子和 a 房子里都住着数值 1,因此当 a=4,使得 a 房子换了新住户,但这不能影响到 b 房子住户——数值 1 的居住。
2.3 条件、循环和其他语句
2.3.1 函数
2.3.2 文件
open()
read()
03|带你初探量化世界
3.1 交易是什么?
3.2 量化交易
当你不确定用哪个词的时候,用量化交易就行了。
2019 年 6 月比特币在全球头部交易所的价格
公开行情 API
行情模块的主要功能是,尝试获取市场的行情数据,通常也负责获取交易账户的状态。 策略模块的主要功能是,订阅市场的数据,根据设定的算法发出买、卖指令给执行模块。 执行模块的主要功能是,接受并把策略模块发过来的买、卖指令封装并转发到交易所;同时,监督并确保策略买卖的完整执行。
3.3 Python 算法交易
3.4 数据分析能力
3.5 大量专有库
3.6 便利的交易平台
3.7 广泛的行业应用
4 | RESTful & Socket: 搭建交易执行层核心
知道包是怎样在网络间传递的; 知道每一个节点是如何处理不同的输入包,然后输出并分发给下一级的。
4.1 REST 简介
厨房的茶 泡
指向一个资源
https://docs.gemini.com/rest-api/#private-api-invocation
动词设计不准确,接口使用“POST”而不是重用 HTTP 动词“DELETE”; URI 里包含动词 cancel; ID 代表的订单是资源,但订单 ID 是放在参数列表而不是 URI 里的,因此 URI 并没有指向资源。
无状态 一个 HTTP 请求完成一次完整操作
4.2 交易所 API 简介
买(buy):用美元买入比特币的行为。 卖(sell):用比特币换取美元的行为。 市价单(market order):给交易所一个方向(买或者卖)和一个数量,交易所把给定数量的美元(或者比特币)换成比特币(或者美元)的单子。 限价单(limit order):给交易所一个价格、一个方向(买或者卖)和一个数量,交易所在价格达到给定价格的时候,把给定数量的美元(或者比特币)换成比特币(或者美元)的单子。
4.3 手把手教你使用 API 下单
一则是因为 nonce 的加入,使得加密后的同样订单的加密文本完全混乱; 二则是因为,这会使得中间人无法通过“发送同样的包来构造重复订单“进行攻击。
5 | RESTful & Socket: 行情数据对接和抓取
5.1 行情数据
上半部分里,第一列红色数字代表 BTC 的卖出价格,中间一列数字是这个价格区间的订单 BTC 总量,最右边一栏是从最低卖出价格到当前价格区间的积累订单量。 中间的大字部分,9994.10 USD 是当前的市场价格,也就是上一次成交交易的价格。 下面绿色部分的含义与上半部分类似,不过指的是买入委托和对应的数量。
Gemini 的委托账本,来自
https://cryptowat.ch
5.2 Websocket 介绍
我们在请求的同时也在接受消息
REST(HTTP)单工请求响应的示意图
Websocket 全双工请求响应的示意图
import ssl
import websocket
import json
count = 5
def on_message ( ws, message) :
global count
print ( message)
count -= 1
if count == 0 :
ws. close( )
if __name__ == "__main__" :
ws = websocket. WebSocketApp(
"wss://api.gemini.com/v1/marketdata/btcusd?top_of_book=true&offers=true" ,
on_message= on_message)
ws. run_forever( sslopt= { "cert_reqs" : ssl. CERT_NONE} )
{ "type" : "update" , "eventId" : 7275473603 , "socket_sequence" : 0 , "events" : [ { "type" : "change" , "reason" : "initial" , "price" : "11386.12" , "delta" : "1.307" , "remaining" : "1.307" , "side" : "ask" } ] }
{ "type" : "update" , "eventId" : 7275475120 , "timestamp" : 1562380981 , "timestampms" : 1562380981991 , "socket_sequence" : 1 , "events" : [ { "type" : "change" , "side" : "ask" , "price" : "11386.62" , "remaining" : "1" , "reason" : "top-of-book" } ] }
{ "type" : "update" , "eventId" : 7275475271 , "timestamp" : 1562380982 , "timestampms" : 1562380982387 , "socket_sequence" : 2 , "events" : [ { "type" : "change" , "side" : "ask" , "price" : "11386.12" , "remaining" : "1.3148" , "reason" : "top-of-book" } ] }
{ "type" : "update" , "eventId" : 7275475838 , "timestamp" : 1562380986 , "timestampms" : 1562380986270 , "socket_sequence" : 3 , "events" : [ { "type" : "change" , "side" : "ask" , "price" : "11387.16" , "remaining" : "0.072949" , "reason" : "top-of-book" } ] }
{ "type" : "update" , "eventId" : 7275475935 , "timestamp" : 1562380986 , "timestampms" : 1562380986767 , "socket_sequence" : 4 , "events" : [ { "type" : "change" , "side" : "ask" , "price" : "11389.22" , "remaining" : "0.06204196" , "reason" : "top-of-book" } ] }
5.3 行情抓取模块
import copy
import json
import ssl
import time
import websocket
class OrderBook ( object ) :
BIDS = 'bid'
ASKS = 'ask'
def __init__ ( self, limit= 20 ) :
self. limit = limit
self. bids = { }
self. asks = { }
self. bids_sorted = [ ]
self. asks_sorted = [ ]
def insert ( self, price, amount, direction) :
if direction == self. BIDS:
if amount == 0 :
if price in self. bids:
del self. bids[ price]
else :
self. bids[ price] = amount
elif direction == self. ASKS:
if amount == 0 :
if price in self. asks:
del self. asks[ price]
else :
self. asks[ price] = amount
else :
print ( 'WARNING: unknown direction {}' . format ( direction) )
def sort_and_truncate ( self) :
self. bids_sorted = sorted ( [ ( price, amount) for price, amount in self. bids. items( ) ] , reverse= True )
self. asks_sorted = sorted ( [ ( price, amount) for price, amount in self. asks. items( ) ] )
self. bids_sorted = self. bids_sorted[ : self. limit]
self. asks_sorted = self. asks_sorted[ : self. limit]
self. bids = dict ( self. bids_sorted)
self. asks = dict ( self. asks_sorted)
def get_copy_of_bids_and_asks ( self) :
return copy. deepcopy( self. bids_sorted) , copy. deepcopy( self. asks_sorted)
class Crawler :
def __init__ ( self, symbol, output_file) :
self. orderbook = OrderBook( limit= 10 )
self. output_file = output_file
self. ws = websocket. WebSocketApp( 'wss://api.gemini.com/v1/marketdata/{}' . format ( symbol) ,
on_message = lambda ws, message: self. on_message( message) )
self. ws. run_forever( sslopt= { 'cert_reqs' : ssl. CERT_NONE} )
def on_message ( self, message) :
data = json. loads( message)
for event in data[ 'events' ] :
price, amount, direction = float ( event[ 'price' ] ) , float ( event[ 'remaining' ] ) , event[ 'side' ]
self. orderbook. insert( price, amount, direction)
self. orderbook. sort_and_truncate( )
with open ( self. output_file, 'a+' ) as f:
bids, asks = self. orderbook. get_copy_of_bids_and_asks( )
output = {
'bids' : bids,
'asks' : asks,
'ts' : int ( time. time( ) * 1000 )
}
f. write( json. dumps( output) + '\n' )
if __name__ == '__main__' :
crawler = Crawler( symbol= 'BTCUSD' , output_file= 'BTCUSD.txt' )
{ "bids" : [ [ 11398.73 , 0.96304843 ] , [ 11398.72 , 0.98914437 ] , [ 11397.32 , 1.0 ] , [ 11396.13 , 2.0 ] , [ 11395.95 , 2.0 ] , [ 11395.87 , 1.0 ] , [ 11394.09 , 0.11803397 ] , [ 11394.08 , 1.0 ] , [ 11393.59 , 0.1612581 ] , [ 11392.96 , 1.0 ] ] , "asks" : [ [ 11407.42 , 1.30814001 ] , [ 11407.92 , 1.0 ] , [ 11409.48 , 2.0 ] , [ 11409.66 , 2.0 ] , [ 11412.15 , 0.525 ] , [ 11412.42 , 1.0 ] , [ 11413.77 , 0.11803397 ] , [ 11413.99 , 0.5 ] , [ 11414.28 , 1.0 ] , [ 11414.72 , 1.0 ] ] , "ts" : 1562558996535 }
{ "bids" : [ [ 11398.73 , 0.96304843 ] , [ 11398.72 , 0.98914437 ] , [ 11397.32 , 1.0 ] , [ 11396.13 , 2.0 ] , [ 11395.95 , 2.0 ] , [ 11395.87 , 1.0 ] , [ 11394.09 , 0.11803397 ] , [ 11394.08 , 1.0 ] , [ 11393.59 , 0.1612581 ] , [ 11392.96 , 1.0 ] ] , "asks" : [ [ 11407.42 , 1.30814001 ] , [ 11407.92 , 1.0 ] , [ 11409.48 , 2.0 ] , [ 11409.66 , 2.0 ] , [ 11412.15 , 0.525 ] , [ 11412.42 , 1.0 ] , [ 11413.77 , 0.11803397 ] , [ 11413.99 , 0.5 ] , [ 11414.28 , 1.0 ] , [ 11414.72 , 1.0 ] ] , "ts" : 1562558997377 }
{ "bids" : [ [ 11398.73 , 0.96304843 ] , [ 11398.72 , 0.98914437 ] , [ 11397.32 , 1.0 ] , [ 11396.13 , 2.0 ] , [ 11395.95 , 2.0 ] , [ 11395.87 , 1.0 ] , [ 11394.09 , 0.11803397 ] , [ 11394.08 , 1.0 ] , [ 11393.59 , 0.1612581 ] , [ 11392.96 , 1.0 ] ] , "asks" : [ [ 11407.42 , 1.30814001 ] , [ 11409.48 , 2.0 ] , [ 11409.66 , 2.0 ] , [ 11412.15 , 0.525 ] , [ 11412.42 , 1.0 ] , [ 11413.77 , 0.11803397 ] , [ 11413.99 , 0.5 ] , [ 11414.28 , 1.0 ] , [ 11414.72 , 1.0 ] ] , "ts" : 1562558997765 }
{ "bids" : [ [ 11398.73 , 0.96304843 ] , [ 11398.72 , 0.98914437 ] , [ 11397.32 , 1.0 ] , [ 11396.13 , 2.0 ] , [ 11395.95 , 2.0 ] , [ 11395.87 , 1.0 ] , [ 11394.09 , 0.11803397 ] , [ 11394.08 , 1.0 ] , [ 11393.59 , 0.1612581 ] , [ 11392.96 , 1.0 ] ] , "asks" : [ [ 11407.42 , 1.30814001 ] , [ 11409.48 , 2.0 ] , [ 11409.66 , 2.0 ] , [ 11412.15 , 0.525 ] , [ 11413.77 , 0.11803397 ] , [ 11413.99 , 0.5 ] , [ 11414.28 , 1.0 ] , [ 11414.72 , 1.0 ] ] , "ts" : 1562558998638 }
{ "bids" : [ [ 11398.73 , 0.97131753 ] , [ 11398.72 , 0.98914437 ] , [ 11397.32 , 1.0 ] , [ 11396.13 , 2.0 ] , [ 11395.95 , 2.0 ] , [ 11395.87 , 1.0 ] , [ 11394.09 , 0.11803397 ] , [ 11394.08 , 1.0 ] , [ 11393.59 , 0.1612581 ] , [ 11392.96 , 1.0 ] ] , "asks" : [ [ 11407.42 , 1.30814001 ] , [ 11409.48 , 2.0 ] , [ 11409.66 , 2.0 ] , [ 11412.15 , 0.525 ] , [ 11413.77 , 0.11803397 ] , [ 11413.99 , 0.5 ] , [ 11414.28 , 1.0 ] , [ 11414.72 , 1.0 ] ] , "ts" : 1562558998645 }
{ "bids" : [ [ 11398.73 , 0.97131753 ] , [ 11398.72 , 0.98914437 ] , [ 11397.32 , 1.0 ] , [ 11396.13 , 2.0 ] , [ 11395.87 , 1.0 ] , [ 11394.09 , 0.11803397 ] , [ 11394.08 , 1.0 ] , [ 11393.59 , 0.1612581 ] , [ 11392.96 , 1.0 ] ] , "asks" : [ [ 11407.42 , 1.30814001 ] , [ 11409.48 , 2.0 ] , [ 11409.66 , 2.0 ] , [ 11412.15 , 0.525 ] , [ 11413.77 , 0.11803397 ] , [ 11413.99 , 0.5 ] , [ 11414.28 , 1.0 ] , [ 11414.72 , 1.0 ] ] , "ts" : 1562558998748 }
6 | Pandas & Numpy: 策略与回测系统
6.1 OHLCV 数据
K 线示意图
K 线的“小蜡烛” -- OHLC
这里
一个是 read_file,它的作用是,用 pandas 读取 csv 文件。 另一个是 assert_msg,它的作用类似于 assert,如果传入的条件(contidtion)为否,就会抛出异常。不过,你需要提供一个参数,用于指定要抛出的异常信息。
6.2 回测框架
比如 Zipline,就是一个热门的事件驱动型回测框架,背后有大型社区和文档的支持。 PyAlgoTrade 也是事件驱动的回测框架,文档相对完整,整合了知名的技术分析(Techique Analysis)库 TA-Lib。在速度和灵活方面,它比 Zipline 强。不过,它的一大硬伤是不支持 Pandas 的模块和对象。
读取 OHLC 数据; 对 OHLC 进行指标运算; 策略根据指标向量决定买卖; 发给模拟的”交易所“进行交易; 最后,统计结果。
交易所类( ExchangeAPI):负责维护账户的资金和仓位,以及进行模拟的买卖; 策略类(Strategy):负责根据市场信息生成指标,根据指标决定买卖; 回测类框架(Backtest):包含一个策略类和一个交易所类,负责迭代地对每个数据点调用策略执行。
OHLC 数据; 初始资金; 手续费率; 交易所类; 策略类。
初始化函数(init):传入必要参数,对 OHLC 数据进行简单清洗、排序和验证。我们从不同地方下载的数据,可能格式不一样;而排序的方式也可能是从前往后。所以,这里我们把数据统一设置为按照时间从之前往现在的排序。 执行函数(run):这是回测框架的主要循环部分,核心是更新市场还有更新策略的时间。迭代完成所有的历史数据后,它会计算收益并返回。
初始化函数 init(),根据历史数据进行指标(Indicator)计算。 步进函数 next(),根据当前时间和指标,决定买卖操作,并发给交易所类执行。
步进函数 next(),根据当前时间,更新最新的价格; 买入操作 buy(),买入资产; 卖出操作 sell(),卖出资产。
6.3 交易策略
某个投资品价格的 SMA,窗口大小为 50
如果小窗口的 SMA 曲线从下面刺破或者穿过大窗口 SMA,那么说明,这个投资品的价格在短期内快速上涨,同时这个趋势很强烈,可能是一个买入的信号; 反之,如果大窗口的 SMA 从下方突破小窗口 SMA,那么说明,投资品的价格在短期内快速下跌,我们应该考虑卖出。
6.4 模拟交易
7 | Kafka & ZMQ:自动化交易流水线
7.1 中间件
7.2 消息队列
消息发布者将消息发送到分布式消息队列后,就结束了对消息的处理; 消息接受者从分布式消息队列获取该消息后,即可进行后续处理,并不需要探寻这个消息从何而来。
7.3 ZMQ
作者 Pieter Hintjens 是一位大牛,他本人的经历也很传奇,2010 年诊断出胆管癌,并成功做了手术切除。但 2016 年 4 月,却发现癌症大面积扩散到了肺部,已经无法治疗。他写的最后一篇通信模式是关于死亡协议的,之后在比利时选择接受安乐死。
Request - Reply 模式; Publish - Subscribe 模式; Parallel Pipeline 模式。
7.4 Kafka
7.5 基于消息队列的 Orderbook 数据流
8 | MySQL:日志和数据存储系统
8.1 快速理解 MySQL
数据是以表格的形式出现的; 每一行是各种记录名称; 每一列是记录名称所对应的数据域; 许多的行和列,组成一张表单; 若干的表单,组成数据库(database)这个整体。
数据库,是一些关联表的集合;而数据表则是数据的矩阵。在一个数据库中,数据表看起来就像是一个简单的电子表格。 在数据表中,每一列包含的是相同类型的数据;每一行则是一组相关的数据。 主键也是数据表中的一个列,只不过,这一列的每行元素都是唯一的,且一个数据表中只能包含一个主键;而外键则用于关联两个表。
Python 之站在高层框架下的 SQLAIchemy 操作 MySQL(关系型数据库)
8.2 mysqlclient
8.3 peewee
8.4 量化数据分析系统
8.5 分布式日志系统
8.6 日志分析
比如,数据系统异常停止,被监视的表没有更新; 或者,交易系统的连接出了故障,委托订单的某些状态超过了一定的阈值; 再或者,仓位信息出现了较大的、预计之外的变动。
9 | Django:搭建监控平台
9.1 Django 简介和安装
TradingMonitor/TradingMonitor,表示项目最初的 Python 包; TradingMonitor/init.py,表示一个空文件,声明所在目录的包为一个 Python 包; TradingMonitor/settings.py,管理项目的配置信息; TradingMonitor/urls.py,声明请求 URL 的映射关系; TradingMonitor/wsgi.py,表示 Python 程序和 Web 服务器的通信协议; manage.py,表示一个命令行工具,用来和 Django 项目进行交互; Db.sqlite3,表示默认的数据库,可以在设置中替换成其他数据库。
9.2 MVC 架构
9.3 设计模型 Model
asset 表示当前持有资产的代码,例如 btc; timestamp 表示时间戳; amount 则表示时间戳时刻的持仓信息。
9.4 设计视图 Views
9.5 设计模板 Templates
9.6 设计链接 Urls
9.7 测试
Graphite 是一款存储时间序列数据,并通过 Django Web 应用程序在图形中显示的插件; Vimeo 则是一个基于 Graphite 的仪表板,具有附加功能和平滑的设计; Scout 监控 Django 和 Flask 应用程序的性能,提供自动检测视图、SQL 查询、模板等。
10 | 总结:Python中的数据结构与算法全景
总结
作为 Python 语言,我确实不可能给你把每一种数据结构和算法都详细讲解一遍,但是,还是那句话,基础的数据结构和算法,一定是每个程序员的基本功。
在数据爆炸的互联网的今天,学习资料触手可及,时间就显得更加宝贵。我在这里列出这些纲要的目的,也是希望能够帮你节省时间,为你整理出适合入门学习、掌握的基础知识点,让你可以带着全局观更有针对性地去学习。
当然,一切可以取得成果的学习,都离不开我们自己付出的努力。也只有这样,掌握了数据结构和算法的你,才能在数学基础上对 Python 的理解更进一步。同时,在未来的项目设计中,这些思维亦会在无形之中,帮你设计出更高质量的系统和架构,可以说是终生受益的学习投资了。
希望你可以学会并且切实有所收获,我的公众号是:AI悦创(微信号:AI-YueChuang)