Python 实战之量化交易
阅读本文大概需要 6 分钟。所谓的量化交易这个概念, 它是指什么呢?百科上是这样介绍的量化交易指的是用先进的数学模型来替代人为的主观判断, 它是利用计算机技术从非常庞大的历史数据中筛选出能够带来超额收益的各种“大概率”事件, 从而制定投资策略, 它极大地减少了投资者情绪波动带来的影响, 避免在市场极度狂热或者出现悲观情绪的情况下, 作出非理性的投资决策。关于量化交易的涵盖范围是非常广阔的。像程序化交易。像算法交易。像高频交易。还有比如自动化交易平台等等这些。其实全部都可以被算作是量化交易这一类的东西。它最突出的长处在于能够把因为个人心理素质问题而引发的交易风险给躲过去, 再说一说, 计算机是不用睡觉的, 也不需要人工进行实时的操作, 这就实现了让大家躺着就能赚钱的那个想法, 尽管在现实的状况里还是需要有人员在不太频繁的时候去插手处理一下, 这么做的原因是为了要避免因为算法突然间出现了失效而导致产生非常严重的交易资金损失情况发生。利用程序执行量化交易, 在底层逻辑上, 其实就是把买进和卖出的指令发送给交易所, 以此来完成交易这件事。通常情况之下, 券商或者是交易所那边, 也会给投资者提供一些 API 接口作为服务。拿一个具体的例子来说吧, 如果我们想要获取最近这一段时间里, 比特币对美元的价格信息, 还有最近的成交量数据, 那么就可以通过下面介绍的这种比较简单的 HTTP GET 请求方式, 去调用那个交易所的公开行情 API 来达到目的。########## GEMINI 行情接口 ############import jsonimport requestsgemini_ticker symbol btcusdbtc_data requests.get(gemini_ticker.format(symbol)).json()print(json.dumps(btc_data, indent4))########## 输出 ##########{bid: 8825.88,ask: 8827.52,volume: {BTC: 910.0838782726,USD: 7972904.560901317851,timestamp: 1560643800000},last: 8838.45}对于算法交易系统这一点来说是如此, API接口它仅仅是构成了最底层的结构基础部分, 从通常性的视角角度来看, 一个属于基本类型的交易系统中理应包含有这几个核心内容, 第一是负责接收市场数据的行情模块, 第二是实现交易逻辑的策略模块, 第三是将订单送达交易所的执行模块, 另外为了能够进一步地帮助完善和开发相关的策略方案, 一般还会配套引入一套用于验证历史表现的量化回测系统进行辅助支持作业, 至于上述这些不同功能板块之间具体是如何划分职责以及进行协作配合的详细示意图内容展现形式如下所述:交易系统各模块分工量化交易算法交易存在一个基本的现实需求, 那就是必须高效地处理各种数据, 而数据处理正是该系统的核心优势范畴, 尤其是将Numpy与相关工具组合起来使用的这一种搭配方式, 直接导致了算法交易领域的开发人员在工作效率方面出现大幅度的显著增长。这里给出了一段代码, 这段代码的功能是抓取数据、处理数据的格式、画出图形, 这个图形展示的是比特币在过去一个小时内价格是如何变化的。import matplotlib.pyplot as pltimport pandas as pdimport requests# 选择要获取的数据时间段periods 3600# 通过 Http 抓取 btc 历史价格数据resp requests.get(https://api.cryptowat.ch/markets/gemini/btcusd/ohlc,params{periods: periods})data resp.json()# 转换成 pandas data framedf pd.DataFrame(data[result][periods],columns[CloseTime,OpenPrice,HighPrice,LowPrice,ClosePrice,Volume,NA])# 输出 DataFrame 的头部几行print(df.head())# 绘制 btc 价格曲线df[ClosePrice].plot(figsize(14, 7))########### 输出 ###############CloseTime OpenPrice HighPrice ... ClosePrice Volume NA0 1558843200 8030.55 8046.30 ... 8011.20 11.642968 93432.4599641 1558846800 8002.76 8050.33 ... 8034.48 8.575682 68870.1458952 1558850400 8031.61 8036.14 ... 8000.00 15.659680 125384.5190633 1558854000 8000.00 8016.29 ... 8001.46 38.171420 304342.0488924 1558857600 8002.69 8023.11 ... 8009.24 3.582830 28716.385009咱们通过执行相关的代码操作, 就很有希望能够获得那副图表里面所呈现出的那样的一条曲线的画面。可以借助一些专有的库另外, 有一些现存的方便的交易处理平台能够执行用户自定义的策略方案, 这种情况下使用者不需要自己去搭建量化的交易架构。有些平台就提供了基于某种标准的回测运行环境, 在国内也存在诸如某某、果仁网等等这些具有同样功能特点的平台。另外, 它是众多行业里普遍在用的计算机程序编写工具, 越来越多的基金公司或者投资公司的业务部门, 也开始采用它进行处理, 所以市场需要更多技术比较好的编写人员, 这样看来, 去学这项技能就变成了一个值得花钱和时间投入的选择。量化交易必须了解什么是 REST什么是 REST API? 要理解这种架构, 最好的方法就是去仔细弄明白 State 这个词组到底是什么意思, 以及它的每一个单词到底代表了什么涵义。从它的英文名字的全称来看, 它的意思是表征状态转移。这种方式是通过 URL 来定位资源的, 然后用 GET、POST、PUT, 这些动词来描述各种操作。满足这种要求的 API , 就叫做 REST API。给你举几个具体的例子: 第一点, 就是提供那种交易所里面关于BTC和USD之间交易的接口。GET https://api.gemini.com/v1/pubticker/btcusd在这里, GET 这个字样代表的是动词的含义, 而在其后面的位置存在着的 url 则是指代了这个资源的具体地址内容, 因此就可以认定这是一个属于 REST API 这样的接口类型。2、以下这种情况的话, 就并不是那种严格意义上的所谓的 REST API 类型的接口。POST https://api.restful.cn/accounts/delete/:username因为那个网址里面带着一个表示清除动作的动词, 也就是删除这两个字, 所以这个网址并不能被看作是指向某个具体资源的东西。如果我们想把这里修改成一个更加规范的接口形式, 我们可以将其调整为下面所述的内容。DELETE https://api.rest.cn/accounts/:username手把手教你使用 API 下单手动进行挂单操作, 其速度显然太慢, 这一点并不符合量化交易的初始目标和核心理念。接下来, 我们将一起探讨如何通过代码的方式来, 从而实现自动化的下单流程。第一步, 你需要做的事儿是去注册一个小号的账号。你可千万别担心需要往里头充钱, 这个测试用的东西是不用钱买的, 只要是你把那个注册的流程走完了, 就会白白送给你一大堆虚拟的现金在里面让你随便花着用。这么说起来是不是特别像那些网络游戏里打出来的宣传广告词?比如说下一句是不是该说什么快来贪玩蓝月来找老兄我一起玩儿啊之类的玩笑话? 反正不管怎么开玩笑说都是好玩的哈。但是, 人家那个官方原本就是这么设定的一个规则制度, 所以你不用犹豫了, 赶紧动手先把这个小号的账号给注册下来再说。在注册完成之后, 为了满足心中的那种好奇心理, 你是可以先去试一下, 用那个 web 界面自己去下单看看。但是呢, 从真正的事实情况来看, 当这个功能没有解锁的时候, 是无法进行正常下单操作的, 所以这样的话去做尝试, 其实并没什么太大的实际意义。所以第二步, 我们需要来配置 API Key , 把 User , 还有 API , 然后点 A NEW API KEY 按钮, 记下 Key 和 这两串字符, 因为窗口一旦消失, 这两个信息就再也找不到了, 可能需要你重新生成, 配置到此结束, 接下来, 我们来看具体实现。首先必须要强调一个前提条件就是在着手进行量化系统的代码编写工作的时候, 你的大脑里一定要绘制清楚、明确的数据流向流程图。下单这一部分的逻辑其实是非常简单直接的执行过程。它和你平常在网页界面上手工操作交易的方式是完全一样的。你需要做的是按照规范构造好你的申请订单数据, 然后对这份数据进行加密处理。最后一步是通过 post 方法把刚才准备好的请求发送给交易所的服务器来完成提交。不过, 因为所涉及的知识点有很多, 带你一步一步从零点开始编写代码, 这显然是不太现实的状况, 所以呢, 我们就采用先来读得懂然后再记忆以及最后去使用这样的这样一个办法来进行学习, 接下来要呈现出来的就是属于这段代码的具体内容了。import requestsimport jsonimport base64import hmacimport hashlibimport datetimeimport timebase_url endpoint /v1/order/newurl base_url endpointgemini_api_key account-zmidXEwP72yLSSybXVvngemini_api_secret 375b97HfE7E4tL8YaP3SJ239Pky9.encode()t datetime.datetime.now()payload_nonce str(int(time.mktime(t.timetuple())*1000))payload {request: /v1/order/new,nonce: payload_nonce,symbol: btcusd,amount: 5,price: 3633.00,side: buy,type: exchange limit,options: [maker-or-cancel]}encoded_payload json.dumps(payload).encode()b64 base64.b64encode(encoded_payload)signature hmac.new(gemini_api_secret, b64, hashlib.sha384).hexdigest()request_headers {Content-Type: text/plain,Content-Length: 0,X-GEMINI-APIKEY: gemini_api_key,X-GEMINI-PAYLOAD: b64,X-GEMINI-SIGNATURE: signature,Cache-Control: no-cache}response requests.post(url,dataNone,headersrequest_headers)new_order response.json()print(new_order)########## 输出 ##########{order_id: 239088767, id: 239088767, symbol: btcusd, exchange: gemini, avg_execution_price: 0.00, side: buy, type: exchange limit, timestamp: 1561956976, timestampms: 1561956976535, is_live: True, is_cancelled: False, is_hidden: False, was_forced: False, executed_amount: 0, remaining_amount: 5, options: [maker-or-cancel], price: 3633.00, original_amount: 5}进行 POST 请求, 是通过 post 这个方法来实现的。post 方法接收三个参数, 分别是 url、data 和一个其他的参数。这里的 url 在功能上等价于那个被截断的部分, 但是在代码编写时, 它被分成了两部分来处理。第一部分是交易所 API 的地址第二部分是带有斜杠开头的部分, 这部分是用来表示统一的 API 接口的。我们同样能够在其他交易所的应用程序接口中看见相似的代码模式, 当这两部分相互拼接在一起之后, 最终的结果就是一个完整的统一资源定位符。至于后面那一大段代码所执行的操作它们真正想要达到的具体目标, 则是为了完成结构上的某种构建操作。此外, 必须关注 nonce, 它是一个在网络的交流互动之中, 特别常见且极为重要的一块内容。原因在于, 当前这种沟通方式是不牢靠的, 一个数据包也许会被丢掉, 说不定也会再次被发出去, 一旦涉及到金融方面的处理操作, 上述两种情况都有可能带来十分糟糕的结果。若是发生了数据丢失的状况, 直接再次发送就好可要是出现了重复发送的情况, 就必须对它进行排除过滤。尽管TCP协议在某些方面能够提供保障, 但是为了让应用层面上的出错概率进一步往下降低, 交易所那边提出了一个明确的要求, 就是所有参与通信的数据包都得配备上一个nonce。nonce 是一个单调递增的整数。当某个后续的请求所使用的 nonce, 相比于上一次成功接收到的请求所携带的 nonce, 如果数值更小或者是相等的话, 就会导致这个请求遭到拒绝。这么做, 能够确保重复提交的报文不会被执行两次。另外, 从另一方面来说, 这种做法也能够在有限的程度上起到防止中间人攻击的作用:接下来的代码就已经很清楚了, 咱们要对具体的内容进行非对称加密操作, 算法的选择也是非对称的那种, 在加密的时候用到的是私钥, 这个私钥由你自己持有, 而交易所那边呢存储着对应的公钥, 所以交易所可以用这个公钥对你发过去的请求进行解密工作, 最后一步就是代码把经过加密处理了的请求给它封装到一个特定的数据格式或者是容器里面去, 当然这里用空格代替了具体的名词, 然后把这份封装好的东西发送给交易所, 接着你这边收到了交易所返回回来的响应信息叫做 , 这样关于这笔订单的处理流程就算大功告成了。请参考所提供的文章内容。核心技术与实战: 量化交易实战篇, 这是我学习的过程中能够最为受益的环节所在, 因此特意推荐给您, 如果您想要进行购买的话, 请扫描下方的二维码。完