火幣量化API的簡(jiǎn)單使用

火幣網(wǎng)(https://www.huobi.io/zh-cn/)是國(guó)內(nèi)比較有名的數(shù)據(jù)貨幣交易所,它提供了API接口,可以用來(lái)作量化交易。

申請(qǐng)火幣API接口

如下圖所示,登陸火幣官網(wǎng)后用戶頭像下面有一個(gè)API管理。


API管理

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


創(chuàng)建API key

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

上圖顯示的兩個(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行。


image.png

第一次執(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í)盤上操作。

參考資料

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。
禁止轉(zhuǎn)載,如需轉(zhuǎn)載請(qǐng)通過(guò)簡(jiǎn)信或評(píng)論聯(lián)系作者。

相關(guān)閱讀更多精彩內(nèi)容

  • 【日文】朝に紅顔あって夕べに白骨となる (あさにこうがんあって、ゆうべにはっこつとなる) 【中文】朝有紅顏夕白骨 ...
    行禪者閱讀 1,200評(píng)論 0 0
  • 「今年“雙十一”交易額再創(chuàng)紀(jì)錄。天貓交易額10秒鐘沖破16億元,3分01秒突破100億元大關(guān)?!?去年雙十一也是“...
    素懷閱讀 1,059評(píng)論 4 16
  • 最近兩三年,我的體重年年上漲,從130竟然飆漲到160了。 每次減肥,我都會(huì)先做一大堆的心理預(yù)設(shè)。假設(shè)我這次減肥,...
    天才玉米腸閱讀 340評(píng)論 0 1
  • 今天呢 有點(diǎn)狀態(tài)不好 早上還是滿血的狀態(tài) 到了三四點(diǎn)的時(shí)候有點(diǎn)腿軟 干不下去的感覺(jué) 也多虧了君如的理解...
    洋氵羊閱讀 323評(píng)論 0 2

友情鏈接更多精彩內(nèi)容