Python 實戰之量化交易

 

 

 

 

閱讀本文大概須要 6 分鐘。html

 

 

什麼是量化交易?

百科上是這樣介紹的web

量化交易是指以先進的數學模型替代人爲的主觀判斷,利用計算機技術從龐大的歷史數據中海選能帶來超額收益的多種「大機率」事件以制定策略,極大地減小了投資者情緒波動的影響,避免在市場極度狂熱或悲觀的狀況下做出非理性的投資決策。算法

量化交易的涵蓋範圍很大,程序化交易,算法交易,高頻交易,自動化交易平臺等等均可以算做量化交易。編程

它最大的優勢能夠規避心理素質緣由帶來的交易風險,另外,計算機不睡覺,不須要人工實時操盤,知足人們躺着賺錢的願景。固然實際狀況下仍是須要人適時干預,防止算法忽然失效形成鉅額交易虧損。json

使用程序來作量化交易,底層就是將買賣請求發送至交易所實現交易,券商或者交易所,一般也會提供 API 接口給投資者。舉個例子,Gemini 交易所的公開行情 API 就能夠經過下面這種簡單的 HTTP GET 請求,來獲取最近的比特幣對美圓的價格和最近的成交量。api

 

########## GEMINI 行情接口 ##########
## https://api.gemini.com/v1/pubticker/:symbol

import json
import requests

gemini_ticker = 'https://api.gemini.com/v1/pubticker/{}'
symbol = 'btcusd'
btc_data = requests.get(gemini_ticker.format(symbol)).json()
print(json.dumps(btc_data, indent=4))

########## 輸出 ##########

{
   "bid""8825.88",
   "ask""8827.52",
   "volume": {
       "BTC""910.0838782726",
       "USD""7972904.560901317851",
       "timestamp"1560643800000
   },
   "last""8838.45"
}restful

對算法交易系統來講,API 只是最下層的結構,一般而言,一個基本的交易系統應該包括:行情模塊、策略模塊、執行模塊,爲了輔助策略的開發,一般還有回測系統輔助,它們的分工示意圖以下:網絡

640?wx_fmt=png

交易系統各模塊分工架構

  • 行情模塊主要獲取市場行情數據,一般也負責獲取交易帳戶的狀態。app

  • 策略模塊主要訂閱市場數據,根據設定的算法發出買、賣指令給執行模塊。

  • 執行模塊的主要功能是接受並把策略模塊發過來的買、賣指令封閉並轉發到交易所,並監督策略買賣的完整執行。

Python 量化交易

算法交易一個基本需求,就是高效處理數據,數據處理是 Python 的強項,特別是 Numpy+Pandas 的組合,讓算法交易開發者的效率直線上升。

這裏提供一個爬取、格式化、繪製比特幣在過去一個小時的價格曲線的 Python 代碼。

 

import matplotlib.pyplot as plt
import pandas as pd
import requests

# 選擇要獲取的數據時間段
periods = '3600'

# 經過 Http 抓取 btc 歷史價格數據
resp = requests.get('https://api.cryptowat.ch/markets/gemini/btcusd/ohlc'
  params={
    'periods': periods
  })
data = resp.json()

# 轉換成 pandas data frame
df = pd.DataFrame(
  data['result'][periods], 
  columns=[
    'CloseTime',
    'OpenPrice',
    'HighPrice',
    'LowPrice',
    'ClosePrice',
    'Volume',
    'NA'])

# 輸出 DataFrame 的頭部幾行
print(df.head())

# 繪製 btc 價格曲線
df['ClosePrice'].plot(figsize=(147))


########### 輸出 ###############
CloseTime  OpenPrice  HighPrice  ...  ClosePrice     Volume             NA
0  1558843200    8030.55    8046.30  ...     8011.20  11.642968   93432.459964
1  1558846800    8002.76    8050.33  ...     8034.48   8.575682   68870.145895
2  1558850400    8031.61    8036.14  ...     8000.00  15.659680  125384.519063
3  1558854000    8000.00    8016.29  ...     8001.46  38.171420  304342.048892
4  1558857600    8002.69    8023.11  ...     8009.24   3.582830   28716.385009

經過執行代碼,咱們即可能獲得下圖所示的曲線:

640?wx_fmt=png

能夠藉助一些專有的庫:

  • Zipline 策略回測

  • Pyfolio 投資組合分析

另外,有一些現有的便利交易平臺能夠執行自定義的 Python 策略,無需搭建量化交易框架。好比,Quantopian,就提供了基於 Zipline 的標準回測環境,國內也有諸如 BigQuant,果仁網等相似平臺。

此外, Python 是各行各業普遍使用的編程語言,愈來愈多投資機構的交易部門,都開始使用 Python,所以對優秀的 Python 開發者產生了更多的需求,天然也讓學習 Python 成了更有意義的投資。

量化交易必須瞭解什麼是 REST

什麼是 REST API,要理解 RESTful 架構,最好的方法就是去理解Representational State Transfer 這個詞組究竟是什麼意思,它的每個詞表明瞭什麼涵義。從其英文全稱來看是表徵狀態轉移,經過 url 定位資源,用 GET,POST,PUT,DELETE 等動詞來描述操做。知足這種要求的 API ,就叫 REST API。

舉幾個例子吧:
一、Gemini 交易所 BTC 對 USD 的 ticker 接口:

 

GET https://api.gemini.com/v1/pubticker/btcusd

這裏的 GET 是動詞,後邊的 url 是 ticker 這個資源的地址,因此這是一個 REST API 接口。

二、下面這樣的,就不是嚴格的 REST API 接口。

 

POST https://api.restful.cn/accounts/delete/:username

由於 URI 中包含動詞「delete」(刪除),因此這個 URI 並非指向一個資源。若是要修改爲嚴格的 RESTful 接口,咱們能夠把它改爲下面這樣:

 

DELETE https://api.rest.cn/accounts/:username

手把手教你使用 API 下單

手動掛單顯然太慢,也不符合量化交易的初衷。咱們就來看看如何用代碼實現自動化下單吧。

第一步,你須要作的是,註冊一個 Gemini Sandbox 帳號。請放心,這個測試帳號不須要你充值任何金額,註冊後即送大量虛擬現金。這口吻是否是聽着特像網遊宣傳語,接下來就是「快來貪玩藍月裏找我吧」?哈哈,不過這個設定確實如此,因此趕忙來註冊一個吧。

註冊後,爲了知足好奇,你能夠先嚐試着使用 web 界面自行下單。不過,事實上,未解鎖的狀況下是沒法正常下單的,所以這樣嘗試並沒啥太大意義。

因此第二步,咱們須要來配置 API Key。User Settings,API Settings,而後點 GENERATE A NEW ACCOUNT API KEY.,記下 Key 和 Secret 這兩串字符。由於窗口一旦消失,這兩個信息就再也找不到了,須要你從新生成。配置到此結束。接下來,咱們來看具體實現。

先強調一點,在量化系統開發的時候,你的心中必定要有清晰的數據流圖。下單邏輯是一個很簡單的 RESTful 的過程,和你在網頁操做的同樣,構造你的請求訂單、加密請求,而後 post 給 gemini 交易所便可。

不過,由於涉及到的知識點較多,帶你一步一步從零來寫代碼顯然不太現實。因此,咱們採用「先讀懂後記憶並使用」的方法來學,下面即爲這段代碼:

 

import requests
import json
import base64
import hmac
import hashlib
import datetime
import time

base_url = "https://api.sandbox.gemini.com"
endpoint = "/v1/order/new"
url = base_url + endpoint

gemini_api_key = "account-zmidXEwP72yLSSybXVvn"
gemini_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,
                         data=None,
                         headers=request_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'}

RESTful 的 POST 請求,經過 requests.post 來實現。post 接受三個參數,url、data 和 headers。這裏的 url 等價於 https://api.sandbox.gemini.com/v1/order/new . ,可是在代碼中分兩部分寫。第一部分是交易所 API 地址;第二部分,以斜槓開頭,用來表示統一的 API endpoint。咱們也能夠在其餘交易所的 API 中看到相似的寫法,二者鏈接在一塊兒,就構成了最終的 url。

而接下來大段命令的目的,是爲了構造 request_headers。

另外,請注意 nonce,這是個很關鍵而且在網絡通訊中很常見的字段。由於網絡通訊是不可靠的,一個信息包有可能會丟失,也有可能重複發送,在金融操做中,這二者都會形成很嚴重的後果。丟包的話,咱們從新發送就好了;可是重複的包,咱們須要去重。雖然 TCP 在某種程度上能夠保證,但爲了在應用層面進一步減小錯誤發生的機會,Gemini 交易所要求全部的通訊 payload 必須帶有 nonce。

nonce 是個單調遞增的整數。當某個後來的請求的 nonce,比上一個成功收到的請求的 nouce 小或者相等的時候,Gemini 便會拒絕此次請求。這樣一來,重複的包就不會被執行兩次了。另外一方面,這樣也能夠在必定程度上防止中間人***:

  • 一則是由於 nonce 的加入,使得加密後的一樣訂單的加密文本徹底混亂;

  • 二則是由於,這會使得中間人沒法經過「發送一樣的包來構造重複訂單「進行***。

接下來的代碼就很清晰了。咱們要對 payload 進行 base64 和 sha384 算法非對稱加密,其中 gemini_api_secret  爲私鑰;而交易所存儲着公鑰,能夠對你發送的請求進行解密。最後,代碼再將加密後的請求封裝到 request_headers 中,發送給交易所,並收到 response,這個訂單就完成了。

 

 

(完)

 

640?wx_fmt=jpeg

相關文章
相關標籤/搜索