├── README.md
└── huobi
├── const.go
├── huobi_test.go
├── market.go
└── trading.go
/README.md:
--------------------------------------------------------------------------------
1 | # coin 数字货币交易平台API
2 | digiccy trading platform API collection, such as Bitcoin, Litecoin. current complete huobi api v3.
3 |
4 | 数字货币交易平台API,目前包含了火币网的API V3的大部分接口,包含交易和行情接口,剩余的接口会陆续完善。其他平台的API接口后续补充。
5 | ##火币网API V3
6 |
7 | ## 安装
8 | ```go
9 | go get -u github.com/lemtree/coin
10 | ```
11 |
12 |
13 | ## 实例
14 | #### 实例一:获取当前市场行情
15 | ```go
16 | package main
17 |
18 | import (
19 | "fmt"
20 | "github.com/lemtree/coin/huobi"
21 | )
22 |
23 | func main() {
24 | c := huobi.NewHuobiClient()
25 |
26 | //获取BTC-CNY行情,返回解析好的struct
27 | QuoData, err := c.Quotation(huobi.COIN_BTC, huobi.CURRENCY_CNY)
28 | checkError(err)
29 | fmt.Printf("当前BTC-CNY报价(golang struct):%+v \r\n", QuoData)
30 |
31 | //获取BTC-CNY行情,返回火币api的原始JSON
32 | jsonBlob, err := c.QuotationJson(huobi.COIN_BTC, huobi.CURRENCY_CNY)
33 | checkError(err)
34 | fmt.Print("当前BTC-CNY报价(火币API原始json):", string(jsonBlob))
35 |
36 | }
37 |
38 | func checkError(err error) {
39 | if err != nil {
40 | fmt.Println(err.Error())
41 | }
42 | }
43 |
44 | ```
45 | 对应火币API接口,我们可以获取火币api原始json信息或者解析后的struct结构信息,调用其中一种即可。
46 |
47 | #### 实例二:获取我的账户信息
48 | ```go
49 | package main
50 |
51 | import (
52 | "fmt"
53 | "github.com/lemtree/coin/huobi"
54 | )
55 |
56 | func main() {
57 | c := huobi.NewHuobiClient()
58 |
59 | // 获取我的账户信息,需要在火币网获取访问秘钥,然后设置你的API key
60 | c.SetApiKey("your-access-key", "your-secret-key")
61 |
62 | accountInfo, err := c.GetAccountInfo()
63 | if err != nil {
64 | fmt.Println(err.Error())
65 | } else {
66 | fmt.Printf("我的资产:%+v", accountInfo)
67 | }
68 | }
69 | ```
70 | #### 注意:个人账户、买卖下单等操作的默认交易市场是人民币市场。若要操作美元市场,设置 c.SetMarket("usd") 即可。
71 |
72 |
73 | ## API接口其他补充说明
74 | 本接口尽量保持和火币的API接口一致
75 | 每个对应火币网的API接口函数都有2种,一种是直接返回火币api的原始json,另一种是解析后的struct,更方便操作。详细请看实例一。
76 | 例如获取实时行情: func Quotation() 返回的是解析后的struct, func QuotationJson()返回的是huobi api的原始json。其他接口也类似。
77 | 基于火币的API返回的原始Json,对于数字和字符串没有严格的区分,有的接口返回的json中价格是字符串,有的接口中是浮点型。如果客户端是弱类型语言则不需额外处理,但是强类型语言则可能直接导致异常。如果你想保持和火币网一致,可以使用 funcname+Json的函数返回api的原始json,如果想规范点,则使用返回struct的接口,然后把返回的struct format成json,这样输出的json数字和字符串就统一了,不会出现价格可能是字符串也可能是浮点型的问题了。
78 |
79 |
80 | ## 更多
81 | 利用放年假的前几天的空暇时间完成,虽然已经对API借口做了测试,但是仍难免有疏漏之处,如果发现bug,请联系QQ:290924805。
82 | 也欢迎讨论各种交易策略。
83 |
--------------------------------------------------------------------------------
/huobi/const.go:
--------------------------------------------------------------------------------
1 | package huobi
2 |
3 | const (
4 | HOST = "https://api.huobi.com/"
5 | API_V3_URI = HOST + "apiv3/"
6 | )
7 |
8 | type PeriodT int
9 | type CoinT int
10 | type CurrencyT int
11 |
12 | // K线周期
13 | const (
14 | PERIOD_1_MINS PeriodT = 1
15 | PERIOD_5_MINS = 5
16 | PERIOD_15_MINS = 15
17 | PERIOD_30_MINS = 30
18 | PERIOD_60_MINS = 60
19 | PERIOD_1_DAY = 100
20 | PERIOD_1_WEEK = 200
21 | PERIOD_1_MONTH = 300
22 | PERIOD_1_YEAR = 400
23 | )
24 |
25 | // 数字货币
26 | const (
27 | COIN_BTC CoinT = 1 + iota
28 | COIN_LTC
29 | )
30 |
31 | //法币
32 | const (
33 | CURRENCY_CNY CurrencyT = 1 + iota
34 | CURRENCY_USD
35 | )
36 |
37 | // 根据coin获得coin name,获取url时用
38 | var coinNames map[CoinT]string = map[CoinT]string{COIN_BTC: "btc", COIN_LTC: "ltc"}
39 |
40 | // 根据currency获得currency name,获取url时用
41 | var marketNames map[CurrencyT]string = map[CurrencyT]string{CURRENCY_CNY: "staticmarket", CURRENCY_USD: "usdmarket"}
42 |
43 | // 账号下的资产信息
44 | type AccountInfo struct {
45 | Total float64 `json:"total,string"`
46 | NetAsset float64 `json:"net_asset,string"`
47 | AvailableCnyDisplay float64 `json:"available_cny_display,string"`
48 | AvailableBtcDisplay float64 `json:"available_btc_display,string"`
49 | AvailableLtcDisplay float64 `json:"available_ltc_display,string"`
50 | FrozenCnyDisplay float64 `json:"frozen_cny_display,string"`
51 | FrozenBtcDisplay float64 `json:"frozen_btc_display,string"`
52 | FrozenLtcDisplay float64 `json:"frozen_ltc_display,string"`
53 | LoanCnyDisplay float64 `json:"loan_cny_display,string"`
54 | LoanBtcDisplay float64 `json:"loan_btc_display,string"`
55 | LoanLtcDisplay float64 `json:"loan_ltc_display,string"`
56 | }
57 |
58 | // 批量返回的订单的单条信息
59 | type Order struct {
60 | Id int `json:"id"`
61 | Type int `json:type`
62 | OrderPrice float64 `json:"order_price,string"`
63 | OrderAmount float64 `json:"order_amount,string"`
64 | ProcessedAmount float64 `json:"processed_amount,string"`
65 | OrderTime int `json:"order_time"`
66 | }
67 |
68 | // 返回某一条订单的详细信息
69 | type OrderInfo struct {
70 | Id int `json:"id"`
71 | Type int `json:type`
72 | OrderPrice float64 `json:"order_price,string"`
73 | OrderAmount float64 `json:"order_amount,string"`
74 | ProcessedPrice float64 `json:"processed_price,string"`
75 | ProcessedAmount float64 `json:"processed_amount,string"`
76 | Vot float64 `json:"vot,string"`
77 | Fee float64 `json:"fee,string"`
78 | Total float64 `json:"total,string"`
79 | Status int `json:"status"`
80 | }
81 |
82 | // 已经成交的订单的信息
83 | type OrderTraded struct {
84 | Order
85 | LastProcessedTime int `json:"last_processed_time"`
86 | Status int `json:"status"`
87 | }
88 |
89 | // 通用返回信息
90 | type Result struct {
91 | Result string `json:"result"`
92 | Id int `json:"id"`
93 | }
94 |
95 | // k线图
96 | type Kline struct {
97 | DateTime int
98 | Open float64
99 | High float64
100 | Low float64
101 | Close float64
102 | Volue float64
103 | }
104 |
105 | // 返回的实时行情
106 | type RealTimeQuotation struct {
107 | DateTime int `json:"time,string"`
108 | Ticker RealTimeQuotationTicker
109 | }
110 |
111 | // 返回的实时行情 ticker
112 | type RealTimeQuotationTicker struct {
113 | High float64
114 | Low float64
115 | Symbol string
116 | Last float64
117 | Volue float64 `json:"vol"`
118 | Buy float64
119 | Sell float64
120 | Open float64
121 | }
122 |
123 | type Depth struct {
124 | Asks [][]float64
125 | Bids [][]float64
126 | Symbol string
127 | }
128 |
129 | // 实时行情
130 | type RealTimeTransactionData struct {
131 | Amount float64
132 | Level float64
133 | Buys []RealTimeTransactionDataSubBuy
134 | Phigh float64 `json:"p_high"`
135 | Plast float64 `json:"p_last"`
136 | Plow float64 `json:"p_low"`
137 | Pnew float64 `json:"p_new"`
138 | Popen float64 `json:"p_open"`
139 | Sells []RealTimeTransactionDataSubBuy
140 | TopBuy []RealTimeTransactionDataSubTopBuy `json:"top_buy"`
141 | TopSell []RealTimeTransactionDataSubTopBuy `json:"top_sell"`
142 | Total float64
143 | Trades []RealTimeTransactionDataSubTrade
144 | Symbol string
145 | }
146 |
147 | //实时行情下的trade结构
148 | type RealTimeTransactionDataSubTrade struct {
149 | Amount float64
150 | Price float64
151 | Time string
152 | EnType string `json:"en_type"`
153 | Type string
154 | }
155 |
156 | //实时行情下的buy或sell结构
157 | type RealTimeTransactionDataSubBuy struct {
158 | Amount float64
159 | Level int
160 | Price float64
161 | }
162 |
163 | //实时行情下的top_buy或top_sell结构
164 | type RealTimeTransactionDataSubTopBuy struct {
165 | RealTimeTransactionDataSubBuy
166 | Accu float64
167 | }
168 |
--------------------------------------------------------------------------------
/huobi/huobi_test.go:
--------------------------------------------------------------------------------
1 | package huobi
2 |
3 | import (
4 | "test"
5 | )
6 |
--------------------------------------------------------------------------------
/huobi/market.go:
--------------------------------------------------------------------------------
1 | /**
2 | * 火币 www.huobi.com API 行情接口
3 | * Auth HuHeKun
4 | * Date 2017-01-17
5 | */
6 | package huobi
7 |
8 | import (
9 | "encoding/json"
10 | "fmt"
11 | "net/url"
12 | "strconv"
13 | )
14 |
15 | var KlineUrl = HOST + "%s" + "/" + "%s" + "_kline_" + "%03d" + "_json.js"
16 | var QuotationUrl = HOST + "%s" + "/" + "ticker_%s_json.js"
17 | var DepthUrl = HOST + "%s/depth_%s_%d.js"
18 | var RealTimeTransactionUrl = HOST + "%s/detail_%s_json.js"
19 |
20 | /**
21 | * 获取K线图
22 | * coinType 数字货币 BTC\LTC
23 | * currency 法币类型 CNY\USD
24 | * period 周期
25 | * length 数据条数
26 | */
27 | func (hb *HuobiClient) Kline(coinType CoinT, currencyType CurrencyT, period PeriodT, length int) ([]Kline, error) {
28 | klines := []Kline{}
29 | dataMap := [][]interface{}{}
30 | jsonBlob, err := hb.KlineJson(coinType, currencyType, period, length)
31 | if err != nil {
32 | return klines, err
33 | }
34 | err = json.Unmarshal(jsonBlob, &dataMap)
35 | if err != nil {
36 | return klines, err
37 | }
38 |
39 | for _, row := range dataMap {
40 | kline := Kline{}
41 | kline.DateTime, _ = strconv.Atoi(row[0].(string))
42 | kline.Open = row[1].(float64)
43 | kline.High = row[2].(float64)
44 | kline.Low = row[3].(float64)
45 | kline.Close = row[4].(float64)
46 | kline.Volue = row[5].(float64)
47 | klines = append(klines, kline)
48 | }
49 |
50 | return klines, nil
51 | }
52 |
53 | /**
54 | * 获取K线图
55 | * coinType 数字货币 BTC\LTC
56 | * currency 法币类型 CNY\USD
57 | * period 周期
58 | * length 数据条数
59 | */
60 | func (hb *HuobiClient) KlineJson(coinType CoinT, currencyType CurrencyT, period PeriodT, length int) ([]byte, error) {
61 | uri := hb.generateKlineApiUrl(coinType, currencyType, period)
62 | v := url.Values{}
63 | v.Set("length", strconv.Itoa(length))
64 | parameter := v.Encode()
65 | return hb.SendRequest(uri, parameter)
66 | }
67 |
68 | // 根据cointype返回coin的小写名称 btc/ltc
69 | func (hb *HuobiClient) getCoinName(coinType CoinT) string {
70 | if coinName, ok := coinNames[coinType]; ok {
71 | return coinName
72 | }
73 | return ""
74 | }
75 |
76 | // 根据currency返回market cny:staticmarket usd:usdmarket
77 | func (hb *HuobiClient) getMarketName(currencyType CurrencyT) string {
78 | if marketName, ok := marketNames[currencyType]; ok {
79 | return marketName
80 | }
81 | return ""
82 | }
83 |
84 | func (hb *HuobiClient) generateKlineApiUrl(coinType CoinT, currencyType CurrencyT, period PeriodT) string {
85 | coinName := hb.getCoinName(coinType)
86 | marketName := hb.getMarketName(currencyType)
87 | return fmt.Sprintf(KlineUrl, marketName, coinName, period)
88 | }
89 |
90 | /**
91 | * BTC-CNY K线图
92 | */
93 | func (hb *HuobiClient) KlineBtcCny(period PeriodT, length int) ([]Kline, error) {
94 | return hb.Kline(COIN_BTC, CURRENCY_CNY, period, length)
95 | }
96 |
97 | /**
98 | * BTC-USD K线图
99 | */
100 | func (hb *HuobiClient) KlineBtcUsd(period PeriodT, length int) ([]Kline, error) {
101 | return hb.Kline(COIN_BTC, CURRENCY_USD, period, length)
102 | }
103 |
104 | /**
105 | * LTC-USD K线图
106 | */
107 | func (hb *HuobiClient) KlineLtcCny(period PeriodT, length int) ([]Kline, error) {
108 | return hb.Kline(COIN_LTC, CURRENCY_CNY, period, length)
109 | }
110 |
111 | /**
112 | * 实时行情
113 | * coinType 数字货币 BTC\LTC
114 | * currency 法币类型 CNY\USD
115 | */
116 | func (hb *HuobiClient) Quotation(coinType CoinT, currencyType CurrencyT) (*RealTimeQuotation, error) {
117 | realTimeQuotation := &RealTimeQuotation{}
118 | jsonBlob, err := hb.QuotationJson(coinType, currencyType)
119 | if err != nil {
120 | return realTimeQuotation, err
121 | }
122 | err = json.Unmarshal(jsonBlob, realTimeQuotation)
123 | if err != nil {
124 | return realTimeQuotation, err
125 | }
126 | return realTimeQuotation, nil
127 | }
128 |
129 | /**
130 | * 实时行情(返回API的json字符串)
131 | * coinType 数字货币 BTC\LTC
132 | * currency 法币类型 CNY\USD
133 | */
134 | func (hb *HuobiClient) QuotationJson(coinType CoinT, currencyType CurrencyT) ([]byte, error) {
135 | coinName := hb.getCoinName(coinType)
136 | marketName := hb.getMarketName(currencyType)
137 | uri := fmt.Sprintf(QuotationUrl, marketName, coinName)
138 | return hb.SendRequest(uri, "")
139 | }
140 |
141 | /**
142 | * 交易深度
143 | * coinType 数字货币 BTC\LTC
144 | * currency 法币类型 CNY\USD
145 | * length 返回的数据条数
146 | */
147 | func (hb *HuobiClient) Depth(coinType CoinT, currencyType CurrencyT, length int) (*Depth, error) {
148 | depths := &Depth{}
149 | jsonBlob, err := hb.DepthJson(coinType, currencyType, length)
150 | if err != nil {
151 | return depths, err
152 | }
153 | err = json.Unmarshal(jsonBlob, depths)
154 | if err != nil {
155 | return depths, err
156 | }
157 | return depths, nil
158 | }
159 |
160 | /**
161 | * 交易深度(返回API的json字符串)
162 | * coinType 数字货币 BTC\LTC
163 | * currency 法币类型 CNY\USD
164 | * length 返回的数据条数
165 | */
166 | func (hb *HuobiClient) DepthJson(coinType CoinT, currencyType CurrencyT, length int) ([]byte, error) {
167 | coinName := hb.getCoinName(coinType)
168 | marketName := hb.getMarketName(currencyType)
169 | uri := fmt.Sprintf(DepthUrl, marketName, coinName, length)
170 | return hb.SendRequest(uri, "")
171 | }
172 |
173 | /**
174 | * 买卖盘实时成交数据
175 | * coinType 数字货币 BTC\LTC
176 | * currency 法币类型 CNY\USD
177 | */
178 | func (hb *HuobiClient) RealTimeTransaction(coinType CoinT, currencyType CurrencyT) (*RealTimeTransactionData, error) {
179 | transactionData := &RealTimeTransactionData{}
180 | jsonBlob, err := hb.RealTimeTransactionJson(coinType, currencyType)
181 | if err != nil {
182 | return transactionData, err
183 | }
184 | err = json.Unmarshal(jsonBlob, transactionData)
185 | if err != nil {
186 | return transactionData, err
187 | }
188 | return transactionData, nil
189 | }
190 |
191 | /**
192 | * 买卖盘实时成交数据
193 | * coinType 数字货币 BTC\LTC
194 | * currency 法币类型 CNY\USD
195 | */
196 | func (hb *HuobiClient) RealTimeTransactionJson(coinType CoinT, currencyType CurrencyT) ([]byte, error) {
197 | coinName := hb.getCoinName(coinType)
198 | marketName := hb.getMarketName(currencyType)
199 | uri := fmt.Sprintf(RealTimeTransactionUrl, marketName, coinName)
200 | return hb.SendRequest(uri, "")
201 | }
202 |
--------------------------------------------------------------------------------
/huobi/trading.go:
--------------------------------------------------------------------------------
1 | /**
2 | * 火币 www.huobi.com API 交易接口
3 | * Auth HuHeKun
4 | * Date 2017-01-17
5 | * 目前 trade_password trade_id 还未实现,以及BTC\LTC提现等暂时未用到,如有需求后续完成
6 | */
7 | package huobi
8 |
9 | import (
10 | "encoding/json"
11 | "errors"
12 | "fmt"
13 | "io/ioutil"
14 |
15 | "net/http"
16 | "net/url"
17 | "strconv"
18 | "strings"
19 | "time"
20 |
21 | "github.com/lemtree/funcs"
22 | )
23 |
24 | var huobiDebug bool
25 |
26 | type HuobiClient struct {
27 | httpClient *http.Client
28 | accessKey string
29 | secretKey string
30 | market string
31 | // trade_password
32 | userAgent string
33 | }
34 |
35 | // huobi client
36 | func NewHuobiClient() *HuobiClient {
37 | client := &http.Client{}
38 | return &HuobiClient{httpClient: client, accessKey: "", secretKey: "", market: "cny", userAgent: "HHK Client"}
39 | }
40 |
41 | /**
42 | * 设置api访问秘钥
43 | * accessKey huobi api AccessKey
44 | * secretKey huobi api SecretKey
45 | */
46 | func (hb *HuobiClient) SetApiKey(accessKey, secretKey string) {
47 | hb.accessKey = accessKey
48 | hb.secretKey = secretKey
49 | }
50 |
51 | /**
52 | * 设置http header的User-Agent
53 | * userAgent User-Agent信息
54 | */
55 | func (hb *HuobiClient) SetUserAgent(userAgent string) {
56 | hb.userAgent = userAgent
57 | }
58 |
59 | /**
60 | * 设置交易市场,人民币市场还是美元市场
61 | * market 交易市场(cny:人民币交易市场,usd:美元交易市场)
62 | */
63 | func (hb *HuobiClient) SetMarket(market string) {
64 | hb.market = market
65 | }
66 |
67 | /**
68 | * 生成请求的参数
69 | */
70 | func (hb *HuobiClient) generateParameter(parameter map[string]string) string {
71 | v := url.Values{}
72 | for key, val := range parameter {
73 | v.Set(key, val)
74 | }
75 | v.Set("access_key", hb.accessKey)
76 | v.Set("created", strconv.Itoa(int(time.Now().Unix())))
77 | v.Set("secret_key", hb.secretKey)
78 | v.Set("sign", tools.MD5([]byte(v.Encode())))
79 | v.Del("secret_key")
80 | v.Set("market", hb.market)
81 | return v.Encode()
82 | }
83 |
84 | /**
85 | * 获取个人账户信息
86 | */
87 | func (hb *HuobiClient) GetAccountInfo() (*AccountInfo, error) {
88 | account := &AccountInfo{}
89 | jsonBlob, err := hb.GetAccountInfoJson()
90 | //jsonBlob = []byte(`{"total":"2163.32","net_asset":"2163.32","available_cny_display":"2163.32","available_btc_display":"1.23000","available_ltc_display":"2.2300","frozen_cny_display":"3.23","frozen_btc_display":"4.23","frozen_ltc_display":"5.23","loan_cny_display":"6.23","loan_btc_display":"7.23","loan_ltc_display":"8.23"}`)
91 | if err != nil {
92 | return account, err
93 | }
94 | err = json.Unmarshal(jsonBlob, &account)
95 | if err != nil {
96 | return account, err
97 | }
98 | return account, nil
99 |
100 | }
101 |
102 | /**
103 | * 获取个人账户信息(返回API的json字符串)
104 | */
105 | func (hb *HuobiClient) GetAccountInfoJson() ([]byte, error) {
106 | p := map[string]string{"method": "get_account_info"}
107 | parameter := hb.generateParameter(p)
108 | return hb.SendTradingRequest(parameter)
109 | }
110 |
111 | /**
112 | * 获取当前所有正在进行的委托
113 | * coinType 数字货币 BTC\LTC
114 | */
115 | func (hb *HuobiClient) GetOrders(coinType CoinT) ([]Order, error) {
116 | orders := []Order{}
117 | jsonBlob, err := hb.GetOrdersJson(coinType)
118 | if err != nil {
119 | return orders, err
120 | }
121 | err = json.Unmarshal(jsonBlob, &orders)
122 | if err != nil {
123 | return orders, err
124 | }
125 | return orders, nil
126 | }
127 |
128 | /**
129 | * 获取当前所有正在进行的委托(返回API的json字符串)
130 | * coinType 数字货币 BTC\LTC
131 | */
132 | func (hb *HuobiClient) GetOrdersJson(coinType CoinT) ([]byte, error) {
133 | p := map[string]string{"method": "get_orders", "coin_type": formatCoinType(coinType)}
134 | parameter := hb.generateParameter(p)
135 | return hb.SendTradingRequest(parameter)
136 | }
137 |
138 | /**
139 | * 获取委托订单详情
140 | * coinType 数字货币 BTC\LTC
141 | * id 订单id
142 | */
143 | func (hb *HuobiClient) OrderInfo(coinType CoinT, id int) (*OrderInfo, error) {
144 | orderInfo := &OrderInfo{}
145 | jsonBlob, err := hb.OrderInfoJson(coinType, id)
146 | // jsonBlob = []byte(`{"id":3748640502,"type":1,"order_price":"3000.00","order_amount":"0.0100","processed_price":"1.11","processed_amount":"2.22","vot":"3.33","fee":"4.44","total":"5.55","status":8}`)
147 | if err != nil {
148 | return orderInfo, err
149 | }
150 | err = json.Unmarshal(jsonBlob, orderInfo)
151 | if err != nil {
152 | return orderInfo, err
153 | }
154 | return orderInfo, nil
155 | }
156 |
157 | /**
158 | * 获取委托订单详情(返回API的json字符串)
159 | * coinType 数字货币 BTC\LTC
160 | * id 订单id
161 | */
162 | func (hb *HuobiClient) OrderInfoJson(coinType CoinT, id int) ([]byte, error) {
163 | p := map[string]string{"method": "order_info", "coin_type": formatCoinType(coinType), "id": strconv.Itoa(id)}
164 | parameter := hb.generateParameter(p)
165 | return hb.SendTradingRequest(parameter)
166 | }
167 |
168 | /**
169 | * 限价买入
170 | * coinType 买入的数字货币 BTC\LTC
171 | * price 买价,期望购买的价位
172 | * amount 数字货币数量,要购买数字货币的数量
173 | */
174 | func (hb *HuobiClient) Buy(coinType CoinT, price, amount float64) (*Result, error) {
175 | result := &Result{}
176 | jsonBlob, err := hb.BuyJson(coinType, price, amount)
177 | if err != nil {
178 | return result, err
179 | }
180 | err = json.Unmarshal(jsonBlob, result)
181 | if err != nil {
182 | return result, err
183 | }
184 | return result, nil
185 | }
186 |
187 | /**
188 | * 限价买入(返回API的json字符串)
189 | * coinType 买入的数字货币 BTC\LTC
190 | * price 买价,期望购买的价位
191 | * amount 数字货币数量,要购买数字货币的数量
192 | */
193 | func (hb *HuobiClient) BuyJson(coinType CoinT, price, amount float64) ([]byte, error) {
194 | p := map[string]string{"method": "buy", "coin_type": formatCoinType(coinType), "price": formatPrice(price), "amount": formatCoinAmout(amount)}
195 | parameter := hb.generateParameter(p)
196 | return hb.SendTradingRequest(parameter)
197 | }
198 |
199 | /**
200 | * 限价卖出
201 | * coinType 卖出的数字货币 BTC\LTC
202 | * price 卖价,期望卖出的价位
203 | * amount 数字货币数量,卖出的coinType的数量
204 | */
205 | func (hb *HuobiClient) Sell(coinType CoinT, price, amount float64) (*Result, error) {
206 | result := &Result{}
207 | jsonBlob, err := hb.SellJson(coinType, price, amount)
208 | if err != nil {
209 | return result, err
210 | }
211 | err = json.Unmarshal(jsonBlob, result)
212 | if err != nil {
213 | return result, err
214 | }
215 | return result, nil
216 | }
217 |
218 | /**
219 | * 限价卖出(返回API的json字符串)
220 | * coinType 卖出的数字货币 BTC\LTC
221 | * price 卖价,期望卖出的价位
222 | * amount 数字货币数量,卖出的coinType的数量
223 | */
224 | func (hb *HuobiClient) SellJson(coinType CoinT, price, amount float64) ([]byte, error) {
225 | p := map[string]string{"method": "sell", "coin_type": formatCoinType(coinType), "price": formatPrice(price), "amount": formatCoinAmout(amount)}
226 | parameter := hb.generateParameter(p)
227 | return hb.SendTradingRequest(parameter)
228 | }
229 |
230 | /**
231 | * 市价买入
232 | * coinType 买入的数字货币 BTC\LTC
233 | * amount 法币金额。要买入多少钱的数字货币,单位CNY/USD,金额精确到0.01元,最少为1元
234 | */
235 | func (hb *HuobiClient) BuyMarket(coinType CoinT, amount float64) (*Result, error) {
236 | result := &Result{}
237 | jsonBlob, err := hb.BuyMarketJson(coinType, amount)
238 | if err != nil {
239 | return result, err
240 | }
241 | err = json.Unmarshal(jsonBlob, result)
242 | if err != nil {
243 | return result, err
244 | }
245 | return result, nil
246 | }
247 |
248 | /**
249 | * 市价买入(返回API的json字符串)
250 | * coinType 买入的数字货币 BTC\LTC
251 | * amount 法币金额。要买入多少钱的数字货币,单位CNY/USD,金额精确到0.01元,最少为1元
252 | */
253 | func (hb *HuobiClient) BuyMarketJson(coinType CoinT, amount float64) ([]byte, error) {
254 | p := map[string]string{"method": "buy_market", "coin_type": formatCoinType(coinType), "amount": formatPrice(amount)}
255 | parameter := hb.generateParameter(p)
256 | return hb.SendTradingRequest(parameter)
257 | }
258 |
259 | /**
260 | * 市价卖出
261 | * coinType 卖出的数字货币 BTC\LTC
262 | * amount 要卖出的btc/ltc数量,精确到0.0001个币, 但是最小卖出为0.001币(比如卖出3.1024个币)
263 | */
264 | func (hb *HuobiClient) SellMarket(coinType CoinT, amount float64) (*Result, error) {
265 | result := &Result{}
266 | jsonBlob, err := hb.SellMarketJson(coinType, amount)
267 | if err != nil {
268 | return result, err
269 | }
270 | err = json.Unmarshal(jsonBlob, result)
271 | if err != nil {
272 | return result, err
273 | }
274 | return result, nil
275 | }
276 |
277 | /**
278 | * 市价卖出(返回API的json字符串)
279 | * coinType 卖出的数字货币 BTC\LTC
280 | * amount 要卖出的btc/ltc数量,精确到0.0001个币
281 | */
282 | func (hb *HuobiClient) SellMarketJson(coinType CoinT, amount float64) ([]byte, error) {
283 | p := map[string]string{"method": "sell_market", "coin_type": formatCoinType(coinType), "amount": formatCoinAmout(amount)}
284 | parameter := hb.generateParameter(p)
285 | return hb.SendTradingRequest(parameter)
286 | }
287 |
288 | /**
289 | * 取消委托单
290 | * coinType 数字货币 BTC\LTC
291 | * id 要取消的委托id
292 | */
293 | func (hb *HuobiClient) CancelOrder(coinType CoinT, id int) (*Result, error) {
294 | result := &Result{}
295 | jsonBlob, err := hb.CancelOrderJson(coinType, id)
296 | if err != nil {
297 | return result, err
298 | }
299 | err = json.Unmarshal(jsonBlob, result)
300 | if err != nil {
301 | return result, err
302 | }
303 | return result, nil
304 | }
305 |
306 | /**
307 | * 取消委托单(返回API的json字符串)
308 | * coinType 数字货币 BTC\LTC
309 | * id 要取消的委托id
310 | */
311 | func (hb *HuobiClient) CancelOrderJson(coinType CoinT, id int) ([]byte, error) {
312 | p := map[string]string{"method": "cancel_order", "coin_type": formatCoinType(coinType), "id": strconv.Itoa(id)}
313 | parameter := hb.generateParameter(p)
314 | return hb.SendTradingRequest(parameter)
315 | }
316 |
317 | /**
318 | * 查询个人最新10条成交订单
319 | * coinType 数字货币 BTC\LTC
320 | */
321 | func (hb *HuobiClient) GetNewDealOrders(coinType CoinT) ([]OrderTraded, error) {
322 | orders := []OrderTraded{}
323 | jsonBlob, err := hb.GetNewDealOrdersJson(coinType)
324 | if err != nil {
325 | return orders, err
326 | }
327 | err = json.Unmarshal(jsonBlob, &orders)
328 | if err != nil {
329 | return orders, err
330 | }
331 | return orders, nil
332 | }
333 |
334 | /**
335 | * 查询个人最新10条成交订单(返回API的json字符串)
336 | * coinType 数字货币 BTC\LTC
337 | */
338 | func (hb *HuobiClient) GetNewDealOrdersJson(coinType CoinT) ([]byte, error) {
339 | p := map[string]string{"method": "get_new_deal_orders", "coin_type": formatCoinType(coinType)}
340 | parameter := hb.generateParameter(p)
341 | return hb.SendTradingRequest(parameter)
342 | }
343 |
344 | /**
345 | * 发送交易请求到api接口获取数据,用于发起需要用户交易秘钥的请求
346 | */
347 | func (hb *HuobiClient) SendTradingRequest(parameter string) ([]byte, error) {
348 | if len(hb.accessKey) < 20 || len(hb.secretKey) < 20 {
349 | return []byte{}, errors.New("error!the huobi AccessKey and SecretKey is incorrect.")
350 | }
351 |
352 | url := API_V3_URI
353 | return hb.SendRequest(url, parameter)
354 | }
355 |
356 | /**
357 | * 发送请求到api接口获取数据
358 | * uri 请求的uri
359 | * parameter 请求的数据
360 | */
361 | func (hb *HuobiClient) SendRequest(uri, parameter string) ([]byte, error) {
362 | body := ioutil.NopCloser(strings.NewReader(parameter)) //把form数据编码
363 | req, _ := http.NewRequest("POST", uri, body)
364 | req.Header.Set("Content-Type", "application/x-www-form-urlencoded; param=value") //post方式需要
365 | req.Header.Add("User-Agent", hb.userAgent)
366 | resp, err := hb.httpClient.Do(req) //发送请求
367 | data := []byte{}
368 | if err != nil {
369 | return data, err
370 | }
371 | defer resp.Body.Close() //一定要关闭resp.Body
372 | return ioutil.ReadAll(resp.Body)
373 | }
374 |
375 | func checkErr(err error) {
376 | if err != nil {
377 | fmt.Println(err.Error())
378 | }
379 | }
380 |
381 | /**
382 | * 格式价格为string,最大2位小数。hubi的金额精确到2位小数
383 | * 所有提交post的参数均为string类型
384 | */
385 | func formatPrice(price float64) string {
386 | return strconv.FormatFloat(price, 'f', 2, 64)
387 | }
388 |
389 | /**
390 | * 格式化比特币数量为string,最大4位小数。huobi所有币种精确到4位小数
391 | * 所有提交post的参数均为string类型
392 | */
393 | func formatCoinAmout(amount float64) string {
394 | return strconv.FormatFloat(amount, 'f', 4, 64)
395 | }
396 |
397 | /**
398 | * 格式化数字货币类型为string。
399 | * 所有提交post的参数均为string类型
400 | */
401 | func formatCoinType(coinType CoinT) string {
402 | return strconv.Itoa(int(coinType))
403 | }
404 |
--------------------------------------------------------------------------------