火幣網(wǎng)(https://www.huobi.io/zh-cn/)是國(guó)內(nèi)比較有名的數(shù)據(jù)貨幣交易所,它提供了API接口,可以用來(lái)作量化交易。
申請(qǐng)火幣API接口
如下圖所示,登陸火幣官網(wǎng)后用戶頭像下面有一個(gè)API管理。

點(diǎn)開(kāi)后創(chuàng)建API key

這里需要輸入三個(gè)安全驗(yàn)證碼,分別是安全郵箱的驗(yàn)證碼、手機(jī)驗(yàn)證碼和google驗(yàn)證碼。

上圖顯示的兩個(gè)參數(shù)的含義是,Access Key API 訪問(wèn)密鑰, Secret Key 簽名認(rèn)證加密所使用的密鑰(僅申請(qǐng)時(shí)可見(jiàn)),是用戶接入火幣網(wǎng)API的憑證,因?yàn)樯婕暗侥愕馁Y產(chǎn)安全,必須牢記。
如何使用火幣網(wǎng)API 接口
我把官網(wǎng)的API介紹搬過(guò)來(lái)了,說(shuō)的很明白,詳細(xì)的看官網(wǎng)文檔,見(jiàn)文末參考資料。
接口類型
火幣為用戶提供兩種接口,您可根據(jù)自己的使用場(chǎng)景和偏好來(lái)選擇適合的方式進(jìn)行查詢行情、交易或提現(xiàn)。
- REST API
REST,即Representational State Transfer的縮寫,是目前較為流行的基于HTTP的一種通信機(jī)制,每一個(gè)URL代表一種資源。
交易或資產(chǎn)提現(xiàn)等一次性操作,建議開(kāi)發(fā)者使用REST API進(jìn)行操作。
- WebSocket API
WebSocket是HTML5一種新的協(xié)議(Protocol)。它實(shí)現(xiàn)了客戶端與服務(wù)器全雙工通信,通過(guò)一次簡(jiǎn)單的握手就可以建立客戶端和服務(wù)器連接,服務(wù)器可以根據(jù)業(yè)務(wù)規(guī)則主動(dòng)推送信息給客戶端。
市場(chǎng)行情和買賣深度等信息,建議開(kāi)發(fā)者使用WebSocket API進(jìn)行獲取。
接口鑒權(quán)
以上兩種接口均包含公共接口和私有接口兩種類型。
公共接口可用于獲取基礎(chǔ)信息和行情數(shù)據(jù)。公共接口無(wú)需認(rèn)證即可調(diào)用。
私有接口可用于交易管理和賬戶管理。每個(gè)私有請(qǐng)求必須使用您的API Key進(jìn)行簽名驗(yàn)證。
接入U(xiǎn)RLs
您可以自行比較使用api.huobi.pro和api-aws.huobi.pro兩個(gè)域名的延遲情況,選擇延遲低的進(jìn)行使用。
其中,api-aws.huobi.pro域名對(duì)使用aws云服務(wù)的用戶做了一定的鏈路延遲優(yōu)化。
SDK與代碼示例
SDK(推薦)
Java
Python3
C++
其它代碼示例
https://github.com/huobiapi?tab=repositories
簡(jiǎn)單應(yīng)用
我想通過(guò)python來(lái)訪問(wèn)火幣API接口,獲得近期的k線數(shù)據(jù),然后根據(jù)歷史信息計(jì)算出的相應(yīng)的指標(biāo)(主要是rsi指標(biāo)),來(lái)找到買賣的時(shí)間點(diǎn),并進(jìn)行自動(dòng)化交易。如何實(shí)現(xiàn)這樣的功能?
在 https://github.com/huobiapi?tab=repositories上有一個(gè) REST-Python3-demo
的例子,基于這個(gè)修改是最快速方便的。
使用git clone到本地
git clone https://github.com/huobiapi/REST-Python3-demo.git

我們需要修改Utils.py和HuobiServices.py這兩個(gè)文件

將剛才審請(qǐng)的acess_key和secret_key填入20和21行。

第一次執(zhí)行g(shù)et_account()函數(shù)后,會(huì)返回一個(gè)account_id,將其賦值給全局變量ACCOUNT_ID,這個(gè)值與帳戶有關(guān),在交易請(qǐng)求時(shí)作為參數(shù),在代碼中硬編碼寫入,就不用重復(fù)向后臺(tái)請(qǐng)求了。如果只讀取行情數(shù)據(jù),不進(jìn)行實(shí)盤交易的情況下,就不需要它,也用不到這個(gè)函數(shù)。我審請(qǐng)的api接口權(quán)限為讀取,因此不需要改這兒。
demo代碼實(shí)現(xiàn)
下面我們寫一個(gè)使用火幣api進(jìn)行量化交易的demo,代碼的功能很簡(jiǎn)單,就是獲取k線數(shù)據(jù),計(jì)算rsi指標(biāo),根據(jù)rsi指標(biāo)來(lái)判斷交易時(shí)機(jī),這是一個(gè)非常粗糙的策略,幾乎沒(méi)有實(shí)用價(jià)值。
開(kāi)發(fā)運(yùn)行環(huán)境
- ubuntu19.04 server
- python3.7 (Anaconda 3)
python需要的庫(kù)
- talib
這是一個(gè)python中一個(gè)非常有名的金融庫(kù),里面提供了大量的方法,可以幫助我們快速計(jì)算各個(gè)指標(biāo),詳細(xì)用法參考官網(wǎng),這個(gè)庫(kù)基于numpy,建議在anaconda環(huán)境下用pip安裝。
#-*- coding:utf-8 -*-
from HuobiServices import *
import time
import numpy as np
import os,json
from talib import RSI
import requests
from utils import send_mail
#保存配置信息
config = {}
#日志文件
log_file = 'log/log.txt'
#配置文件
config_file = 'conf.json'
#日志函數(shù)
def log(msg):
global log_file
cur_time = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(int(time.time())))
if not os.path.isfile(log_file):
open(log_file,'w')
open(log_file,'a').write('%s: %s\n'%(cur_time,msg))
#獲取我的帳戶
def get_my_balance(currency):
data = list(filter(lambda x: x['currency'] == currency and x['type'] == 'trade',get_balance()['data']['list']))[0]['balance']
return float(data[:data.find('.')+7])
#獲取當(dāng)前的usdt/btc價(jià)格
def get_current_price():
url = 'https://www.huobi.co/-/x/pro/market/overview5?r=ny2seo'
response = requests.get(url)
if response.status_code == 200:
data = response.json()
price_usdt= data['data'][2]['close']
return price_usdt
else:
return 0
#根據(jù)k線計(jì)算rsi,周期為14
def get_rsi(data):
#調(diào)用talib庫(kù)計(jì)算rsi指標(biāo)
close = np.array([x['close'] for x in data])
real = RSI(close,14)
return real
#買操作
def buy(cur_price):
global config
#獲取當(dāng)前我?guī)糁械膗sdt
my_usdt = get_my_balance('usdt')
#取小數(shù)點(diǎn)后6位
my_usdt = float('%0.6f' % my_usdt)
#若my_usdt不為0的話
if int(my_usdt) > 0:
#下單,以cur_price價(jià)錢全部買btc
ret = send_order(amount=my_usdt,source='api',symbol='btcusdt',_type='buy-market')
#config['BUY_PRICE']記下當(dāng)前買的價(jià)格
config['BUY_PRICE'] = cur_price
#log(str(ret))
#在日志文件中記下這個(gè)買操作
log('buy at %f usdt/btc,current balance: %f btc,%f usdt' % (
cur_price,
get_my_balance('btc')
,get_my_balance('usdt')
))
#賣操作
def sell(cur_price):
global config
#獲取我的帳戶中的btc數(shù)量
my_btc = get_my_balance('btc')
#取小數(shù)點(diǎn)后6位
my_btc = float('%0.6f' % my_btc)
#若大于0.0001,因?yàn)閎tc是最小交易單位為萬(wàn)分之一比特幣
if my_btc > 0.0001:
#下單賣
ret = send_order(amount=my_btc,source='api',symbol='btcusdt',_type='sell-market')
#config['SELL_PRICE']記下當(dāng)前的賣的價(jià)格
config['SELL_PRICE'] = cur_price
#log(str(ret))
#將這次賣操作寫入日志文件
log('sell at %f usdt/btc,current balance: %f btc,%f usdt' % (
cur_price,
get_my_balance('btc'),
get_my_balance('usdt')
))
#買時(shí)機(jī)監(jiān)控開(kāi)關(guān)
buy_monitor_switch = False
#賣時(shí)機(jī)監(jiān)控開(kāi)關(guān)
sell_monitor_switch = False
#量化主函數(shù)
def trade():
#聲明全局變量
global config
global buy_monitor_switch,sell_monitor_switch
#獲取k線數(shù)據(jù),獲取從當(dāng)前向前200個(gè)k線數(shù)據(jù),每個(gè)k線時(shí)長(zhǎng)為config['period']
data = get_kline('btcusdt',"%dmin" % config['period'],200)['data']
#數(shù)據(jù)反轉(zhuǎn)
data.reverse()
#計(jì)算rsi,取最后三個(gè)rsi值
rsi1,rsi2,rsi3 = get_rsi(data)[-3:]
#根據(jù)時(shí)間戳獲取最后一個(gè)k線的時(shí)間
cur_time_ = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime(data[-1]['id']))
#獲取當(dāng)前的btc/usdt的價(jià)格
cur_price = get_current_price()
log('%s rsi:%f, price:%f usdt/btc' % (cur_time_,rsi3,cur_price))
#如果rsi3小于30,開(kāi)啟買監(jiān)控
if rsi3 < 30:
buy_monitor_switch = True
#如果rsi大于70,開(kāi)啟賣監(jiān)控
if rsi3 > 70:
sell_monitor_switch = True
if buy_monitor_switch:
#若rsi曲線出線 觸底反彈 或者 直接向上突破30 時(shí),發(fā)出買的信息
if (rsi2 < rsi1 and rsi2 < rsi3) or (rsi3 > 30):
log('It is time to buy')
try:
#向用戶發(fā)出買的信息
send_mail(title='Buy Signal rsi=%f price= %f' % (rsi3,cur_price),msg='%s rsi:%f, price:%f usdt/btc' % (cur_time_,rsi3,cur_price))
except:
pass
#若rsi向上已經(jīng)突破30,關(guān)閉買操作監(jiān)控
if rsi3 > 30 :
buy_monitor_switch = False
if sell_monitor_switch:
#若rsi出現(xiàn) 觸頂下降 時(shí) 或者 向下突破70,發(fā)出賣的信息
if (rsi2 > rsi1 and rsi2 > rsi3) or (rsi3 < 70):
log('It is time to sell')
try:
#向用戶發(fā)出賣的信號(hào)
send_mail(title='Sell Signal rsi=%f price= %f' % (rsi3,cur_price),msg='%s rsi:%f, price:%f usdt/btc' % (cur_time_,rsi3,cur_price))
except:
pass
#若rsi向下突破70,關(guān)閉賣操作監(jiān)控
if rsi3 < 70:
sell_monitor_switch = False
#主函數(shù)
def main():
#聲明全局變量
global config
#k線的時(shí)間區(qū)間為15min
config['period'] = 15
while True:
#獲取當(dāng)前的分和秒
cur_miniute,cur_second = time.strftime("%M:%S", time.localtime(int(time.time()))).split(':')
cur_miniute = int(cur_miniute)
cur_second = int(cur_second)
#如果當(dāng)前時(shí)間為整刻鐘
if cur_miniute % config['period'] == 0 and cur_second == 0:
try:
#加載配置文件
config = json.load(open(config_file,'r'))
#監(jiān)控操作
trade()
except:
#出錯(cuò)的話繼續(xù)
continue
finally:
#配置信息寫入文本文件
json.dump(config,open(config_file,'w'))
time.sleep(1)
main()
配置文件是一個(gè)json文件
{"period": 15, "BUY_PRICE": 11403.96, "SELL_PRICE": 11430.09}
上面代碼中使用了一個(gè)可以發(fā)郵件的功能
#-*- coding:utf-8 -*-
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
def send_mail(title,msg):
mail_content = msg
#發(fā)送方的郵箱和密碼
sender_address = 'xxxx@gmail.com'
sender_pass = 'xxxxx'
#接收方的郵箱,多個(gè)郵箱的可以用分號(hào)隔開(kāi)
receiver_address = 'xxxx@qq.com'
#Setup the MIME
message = MIMEMultipart()
message['From'] = sender_address
message['To'] = receiver_address
message['Subject'] = title #郵件的title
#The body and the attachments for the mail
message.attach(MIMEText(mail_content, 'plain'))
#Create SMTP session for sending the mail
session = smtplib.SMTP('smtp.gmail.com', 587) #use gmail with port
session.starttls() #enable security
session.login(sender_address, sender_pass) #login with mail_id and password
text = message.as_string()
session.sendmail(sender_address, receiver_address, text)
session.quit()
#print('Mail Sent')
使用微信開(kāi)啟qq郵件提醒的話,就可以在第1時(shí)間得到交易行情信息。
這個(gè)demo沒(méi)有進(jìn)行實(shí)際交易,因?yàn)檫@個(gè)交易策略實(shí)在是太簡(jiǎn)單粗暴,沒(méi)有應(yīng)用價(jià)值,在實(shí)際的量化模型中往往要考慮多個(gè)指標(biāo),還要考慮交易手續(xù)費(fèi)的問(wèn)題。一個(gè)實(shí)用的量化模型可以給你帶來(lái)豐厚的收益,當(dāng)然一個(gè)失敗的模型也能讓你賠的很慘,千萬(wàn)不要用實(shí)盤去測(cè)試你的代碼,用歷史數(shù)據(jù)進(jìn)行回測(cè)是正確的方法,如果你的模型在歷史數(shù)據(jù)上運(yùn)行的很好,收益率不錯(cuò),再考慮在實(shí)盤上操作。
參考資料
- 火幣API官方文檔
https://huobiapi.github.io/docs/spot/v1/cn/#5ea2e0cde2 - 火幣API示例代碼
https://github.com/huobiapi?tab=repositories - talib文檔(英文)
https://mrjbq7.github.io/ta-lib/ - talib文檔(中文)
https://www.ricequant.com/community/topic/2393//4