1 Star 1 Fork 1

378077287/exchanges

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
binancefutures.go 17.13 KB
一键复制 编辑 原始数据 按行查看 历史
378077287 提交于 2020-09-30 14:27 . 注释打印私人订阅收到的信息
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642
package binancefutures
import (
"context"
"encoding/json"
"fmt"
"net/http"
"net/url"
"strconv"
"time"
. "gitee.com/378077287/exchanges"
"gitee.com/378077287/exchanges/utils"
"github.com/adshao/go-binance/futures"
"github.com/golang/glog"
)
// BinanceFutures the Binance futures exchange
type BinanceFutures struct {
client *futures.Client
symbol string
listenKey string //币安交易所websocket订阅用户信息的key
userStream bool // 是否已经订阅用户信息
orderCallBack func(orders []*Order)
positionCallBack func(positions []*Position)
}
func (b *BinanceFutures) GetName() (name string) {
return "binancefutures"
}
func (b *BinanceFutures) GetTime() (tm int64, err error) {
tm, err = b.client.NewServerTimeService().
Do(context.Background())
return
}
// SetProxy ...
// proxyURL: http://127.0.0.1:1080
func (b *BinanceFutures) SetProxy(proxyURL string) error {
proxyURL_, err := url.Parse(proxyURL)
if err != nil {
return err
}
//adding the proxy settings to the Transport object
transport := &http.Transport{
Proxy: http.ProxyURL(proxyURL_),
}
//adding the Transport object to the http Client
b.client.HTTPClient.Transport = transport
return nil
}
// currency: USDT
func (b *BinanceFutures) GetBalance(currency string) (result *Balance, err error) {
var res []*futures.Balance
res, err = b.client.NewGetBalanceService().
Do(context.Background())
if err != nil {
return
}
result = &Balance{}
for _, v := range res {
if v.Asset == currency { // USDT
value := utils.ParseFloat64(v.Balance)
result.Equity = value
result.Available = value
break
}
}
return
}
func (b *BinanceFutures) GetOrderBook(symbol string, depth int) (result *OrderBook, err error) {
result = &OrderBook{}
if depth <= 5 {
depth = 5
} else if depth <= 10 {
depth = 10
} else if depth <= 20 {
depth = 20
} else if depth <= 50 {
depth = 50
} else if depth <= 100 {
depth = 100
} else if depth <= 500 {
depth = 500
} else {
depth = 1000
}
var res *futures.DepthResponse
res, err = b.client.NewDepthService().
Symbol(symbol).
Limit(depth).
Do(context.Background())
if err != nil {
return
}
for _, v := range res.Asks {
result.Asks = append(result.Asks, Item{
Price: utils.ParseFloat64(v.Price),
Amount: utils.ParseFloat64(v.Quantity),
})
}
for _, v := range res.Bids {
result.Bids = append(result.Bids, Item{
Price: utils.ParseFloat64(v.Price),
Amount: utils.ParseFloat64(v.Quantity),
})
}
result.Time = time.Now()
return
}
func (b *BinanceFutures) GetRecords(symbol string, period string, from int64, end int64, limit int) (records []*Record, err error) {
var res []*futures.Kline
service := b.client.NewKlinesService().
Symbol(symbol).
Interval(b.IntervalKlinePeriod(period)).
Limit(limit)
if from > 0 {
service = service.StartTime(from * 1000)
}
if end > 0 {
service = service.EndTime(end * 1000)
}
res, err = service.Do(context.Background())
if err != nil {
return
}
for _, v := range res {
records = append(records, &Record{
Symbol: symbol,
Timestamp: time.Unix(0, v.OpenTime*int64(time.Millisecond)),
Open: utils.ParseFloat64(v.Open),
High: utils.ParseFloat64(v.High),
Low: utils.ParseFloat64(v.Low),
Close: utils.ParseFloat64(v.Close),
Volume: utils.ParseFloat64(v.Volume),
})
}
return
}
func (b *BinanceFutures) IntervalKlinePeriod(period string) string {
m := map[string]string{
PERIOD_1WEEK: "7d",
}
if v, ok := m[period]; ok {
return v
}
return period
}
func (b *BinanceFutures) SetContractType(currencyPair string, contractType string) (err error) {
b.symbol = currencyPair
return
}
func (b *BinanceFutures) GetContractID() (symbol string, err error) {
return b.symbol, nil
}
func (b *BinanceFutures) SetLeverRate(value float64) (err error) {
return
}
func (b *BinanceFutures) OpenLong(symbol string, orderType OrderType, price float64, size float64) (result *Order, err error) {
return b.PlaceOrder(symbol, Buy, orderType, price, size)
}
func (b *BinanceFutures) OpenShort(symbol string, orderType OrderType, price float64, size float64) (result *Order, err error) {
return b.PlaceOrder(symbol, Sell, orderType, price, size)
}
func (b *BinanceFutures) CloseLong(symbol string, orderType OrderType, price float64, size float64) (result *Order, err error) {
return b.PlaceOrder(symbol, Sell, orderType, price, size, OrderReduceOnlyOption(true))
}
func (b *BinanceFutures) CloseShort(symbol string, orderType OrderType, price float64, size float64) (result *Order, err error) {
return b.PlaceOrder(symbol, Buy, orderType, price, size, OrderReduceOnlyOption(true))
}
func (b *BinanceFutures) PlaceOrder(symbol string, direction Direction, orderType OrderType, price float64,
size float64, opts ...PlaceOrderOption) (result *Order, err error) {
params := ParsePlaceOrderParameter(opts...)
service := b.client.NewCreateOrderService().
Symbol(symbol).
Quantity(fmt.Sprint(size)).
ReduceOnly(params.ReduceOnly)
var side futures.SideType
if direction == Buy {
side = futures.SideTypeBuy
} else if direction == Sell {
side = futures.SideTypeSell
}
var _orderType futures.OrderType
switch orderType {
case OrderTypeLimit:
_orderType = futures.OrderTypeLimit
case OrderTypeMarket:
_orderType = futures.OrderTypeMarket
case OrderTypeStopMarket:
_orderType = futures.OrderTypeStopMarket
service = service.StopPrice(fmt.Sprint(params.StopPx))
case OrderTypeStopLimit:
_orderType = futures.OrderTypeStop
service = service.StopPrice(fmt.Sprint(params.StopPx))
}
if price > 0 {
service = service.Price(fmt.Sprint(price))
}
if params.PostOnly {
service = service.TimeInForce(futures.TimeInForceTypeGTX)
}
service = service.Side(side).Type(_orderType)
var res *futures.CreateOrderResponse
res, err = service.Do(context.Background())
if err != nil {
return
}
result = b.convertOrder1(res)
return
}
func (b *BinanceFutures) GetOpenOrders(symbol string, opts ...OrderOption) (result []*Order, err error) {
service := b.client.NewListOpenOrdersService().
Symbol(symbol)
var res []*futures.Order
res, err = service.Do(context.Background())
if err != nil {
return
}
for _, v := range res {
result = append(result, b.convertOrder(v))
}
return
}
func (b *BinanceFutures) GetOrder(symbol string, id string, opts ...OrderOption) (result *Order, err error) {
var orderID int64
orderID, err = strconv.ParseInt(id, 10, 64)
if err != nil {
return
}
var res *futures.Order
res, err = b.client.NewGetOrderService().
Symbol(symbol).
OrderID(orderID).
Do(context.Background())
if err != nil {
return
}
result = b.convertOrder(res)
return
}
func (b *BinanceFutures) CancelOrder(symbol string, id string, opts ...OrderOption) (result *Order, err error) {
var orderID int64
orderID, err = strconv.ParseInt(id, 10, 64)
if err != nil {
return
}
var res *futures.CancelOrderResponse
res, err = b.client.NewCancelOrderService().
Symbol(symbol).
OrderID(orderID).
Do(context.Background())
if err != nil {
return
}
result = b.convertOrder2(res)
return
}
func (b *BinanceFutures) CancelAllOrders(symbol string, opts ...OrderOption) (err error) {
err = b.client.NewCancelAllOpenOrdersService().
Symbol(symbol).
Do(context.Background())
return
}
func (b *BinanceFutures) AmendOrder(symbol string, id string, price float64, size float64, opts ...OrderOption) (result *Order, err error) {
return
}
func (b *BinanceFutures) GetPositions(symbol string) (result []*Position, err error) {
var res []*futures.PositionRisk
res, err = b.client.NewGetPositionRiskService().
Do(context.Background())
if err != nil {
return
}
useFilter := symbol != ""
for _, v := range res {
if useFilter && v.Symbol != symbol {
continue
}
position := &Position{}
position.Symbol = v.Symbol
size := utils.ParseFloat64(v.PositionAmt)
if size != 0 {
position.Size = size
position.OpenPrice = utils.ParseFloat64(v.EntryPrice)
position.AvgPrice = position.OpenPrice
}
result = append(result, position)
}
return
}
func (b *BinanceFutures) convertOrder(order *futures.Order) (result *Order) {
result = &Order{}
result.ID = fmt.Sprint(order.OrderID)
result.Symbol = order.Symbol
result.Price = utils.ParseFloat64(order.Price)
result.StopPx = utils.ParseFloat64(order.StopPrice)
result.Amount = utils.ParseFloat64(order.OrigQuantity)
result.Direction = b.convertDirection(order.Side)
result.Type = b.convertOrderType(order.Type)
result.AvgPrice = utils.ParseFloat64(order.AvgPrice)
result.FilledAmount = utils.ParseFloat64(order.ExecutedQuantity)
if order.TimeInForce == futures.TimeInForceTypeGTX {
result.PostOnly = true
}
result.ReduceOnly = order.ReduceOnly
result.Status = b.orderStatus(order.Status)
return
}
func (b *BinanceFutures) convertOrder1(order *futures.CreateOrderResponse) (result *Order) {
result = &Order{}
result.ID = fmt.Sprint(order.OrderID)
result.Symbol = order.Symbol
result.Price = utils.ParseFloat64(order.Price)
result.StopPx = utils.ParseFloat64(order.StopPrice)
result.Amount = utils.ParseFloat64(order.OrigQuantity)
result.Direction = b.convertDirection(order.Side)
result.Type = b.convertOrderType(order.Type)
result.AvgPrice = utils.ParseFloat64(order.AvgPrice)
result.FilledAmount = utils.ParseFloat64(order.ExecutedQuantity)
if order.TimeInForce == futures.TimeInForceTypeGTX {
result.PostOnly = true
}
result.ReduceOnly = order.ReduceOnly
result.Status = b.orderStatus(order.Status)
return
}
func (b *BinanceFutures) convertOrder2(order *futures.CancelOrderResponse) (result *Order) {
result = &Order{}
result.ID = fmt.Sprint(order.OrderID)
result.Symbol = order.Symbol
result.Price = utils.ParseFloat64(order.Price)
result.StopPx = utils.ParseFloat64(order.StopPrice)
result.Amount = utils.ParseFloat64(order.OrigQuantity)
result.Direction = b.convertDirection(order.Side)
result.Type = b.convertOrderType(order.Type)
result.AvgPrice = 0
result.FilledAmount = utils.ParseFloat64(order.ExecutedQuantity)
if order.TimeInForce == futures.TimeInForceTypeGTX {
result.PostOnly = true
}
result.ReduceOnly = order.ReduceOnly
result.Status = b.orderStatus(order.Status)
return
}
func (b *BinanceFutures) convertDirection(side futures.SideType) Direction {
switch side {
case futures.SideTypeBuy:
return Buy
case futures.SideTypeSell:
return Sell
default:
return Buy
}
}
func (b *BinanceFutures) convertOrderType(orderType futures.OrderType) OrderType {
/*
OrderTypeTakeProfitMarket OrderType = "TAKE_PROFIT_MARKET"
OrderTypeTrailingStopMarket OrderType = "TRAILING_STOP_MARKET"
*/
switch orderType {
case futures.OrderTypeLimit:
return OrderTypeLimit
case futures.OrderTypeMarket:
return OrderTypeMarket
case futures.OrderTypeStop:
return OrderTypeStopLimit
case futures.OrderTypeStopMarket:
return OrderTypeStopMarket
default:
return OrderTypeLimit
}
}
func (b *BinanceFutures) orderStatus(status futures.OrderStatusType) OrderStatus {
switch status {
case futures.OrderStatusTypeNew:
return OrderStatusNew
case futures.OrderStatusTypePartiallyFilled:
return OrderStatusPartiallyFilled
case futures.OrderStatusTypeFilled:
return OrderStatusFilled
case futures.OrderStatusTypeCanceled:
return OrderStatusCancelled
case futures.OrderStatusTypeRejected:
return OrderStatusRejected
case futures.OrderStatusTypeExpired:
return OrderStatusCancelled
default:
return OrderStatusCreated
}
}
// SubscribeTrades 订阅逐笔成交.
func (b *BinanceFutures) SubscribeTrades(market Market, callback func(trades []*Trade)) error {
wsAggTradeHandler := func(event *WsAggTradeEvent) {
var trades []*Trade
trade := &Trade{
ID: string(event.AggTradeID),
Price: utils.ParseFloat64(event.Price),
Amount: utils.ParseFloat64(event.Quantity),
Ts: event.TradeTime,
Symbol: event.Symbol,
}
if event.IsBuyerMaker {
trade.Direction = Sell
} else {
trade.Direction = Buy
}
trades = append(trades, trade)
callback(trades)
}
errHandler := func(err error) {
fmt.Println(err)
glog.Error(err)
}
WsAggTradeServe(market.Symbol, wsAggTradeHandler, errHandler)
return nil
}
// SubscribeLevel2Snapshots 订阅orderbook .
func (b *BinanceFutures) SubscribeLevel2Snapshots(market Market, callback func(ob *OrderBook)) error {
wsDepthHandler := func(event *WsDepthEvent) {
ob := &OrderBook{
Symbol: event.Symbol,
Time: time.Unix(event.Time, 0),
}
for _, v := range event.Bids {
item := Item{
Price: utils.ParseFloat64(v.Price),
Amount: utils.ParseFloat64(v.Quantity),
}
ob.Bids = append(ob.Bids, item)
}
for _, v := range event.Asks {
item := Item{
Price: utils.ParseFloat64(v.Price),
Amount: utils.ParseFloat64(v.Quantity),
}
ob.Asks = append(ob.Asks, item)
}
callback(ob)
}
errHandler := func(err error) {
fmt.Println(err)
glog.Error(err)
}
_, _, err := WsDepthServe(market.Symbol, wsDepthHandler, errHandler)
if err != nil {
fmt.Println(err)
return err
}
return nil
}
func (b *BinanceFutures) SubscribeOrders(market Market, callback func(orders []*Order)) error {
b.orderCallBack = callback
b.subscribeUserData()
return nil
}
func (b *BinanceFutures) SubscribePositions(market Market, callback func(positions []*Position)) error {
b.positionCallBack = callback
b.subscribeUserData()
return nil
}
// EventType 用户获取用户私人数据推送过来的数据类型.
type EventType struct {
Event string `json:"e"`
T int64 `json:"T"`
E int64 `json:"E"`
}
// BinancePosition 仓位.
type BinancePosition struct {
Symbol string `json:"s"`
Size string `json:"pa"`
CostPrice string `json:"ep"`
}
// EventPosition 仓位信息事件.
type EventPosition struct {
Event string `json:"e"`
UpdateTime int64 `json:"E"`
A struct {
Positions []BinancePosition `json:"P"`
} `json:"a"`
}
// BinanceOrder .
type BinanceOrder struct {
ID int64 `json:"i"` // ID
ClientOId string `json:"c"` // 客户端订单ID
Symbol string `json:"s"` // 标
Price string `json:"p"` // 价格
StopPx string `json:"sp"` // 触发价
Amount string `json:"q"` // 委托数量
AvgPrice string `json:"ap"` // 平均成交价
FilledAmount string `json:"z"` // 成交数量
Direction string `json:"S"` // 委托方向
Type string `json:"ot"` // 委托类型
Status string `json:"X"` // 委托状态
}
// EventOrder .
type EventOrder struct {
Event string `json:"e"`
UpdateTime int64 `json:"E"`
Order BinanceOrder `json:"o"`
}
// subscribeUserData 订阅用户私人数据.
func (b *BinanceFutures) subscribeUserData() error {
if !b.userStream {
listenKey, err := b.client.NewStartUserStreamService().Do(context.Background())
if err != nil {
glog.Error(err)
fmt.Println(err)
}
b.listenKey = listenKey
wsUserDataHandler := func(message []byte) {
ep := EventType{}
// fmt.Println(string(message))
err := json.Unmarshal(message, &ep)
if err != nil {
glog.Error(err)
}
if ep.Event == "ACCOUNT_UPDATE" && b.positionCallBack != nil {
eb := EventPosition{}
err := json.Unmarshal(message, &eb)
if err != nil {
glog.Error(err)
fmt.Println(err)
}
fmt.Println(eb)
var positions []*Position
for _, v := range eb.A.Positions {
p := &Position{
Symbol: v.Symbol,
Size: utils.ParseFloat64(v.Size),
OpenPrice: utils.ParseFloat64(v.CostPrice),
AvgPrice: utils.ParseFloat64(v.CostPrice),
}
positions = append(positions, p)
}
b.positionCallBack(positions)
}
if ep.Event == "ORDER_TRADE_UPDATE" && b.orderCallBack != nil {
oe := EventOrder{}
err := json.Unmarshal(message, &oe)
if err != nil {
glog.Error(err)
}
// fmt.Printf("price:%s,amount:%s,side:%s,status:%s\n", oe.Order.Price, oe.Order.Amount, oe.Order.Direction, oe.Order.Status)
var orders []*Order
o := &Order{
ID: string(oe.Order.ID),
ClientOId: oe.Order.ClientOId,
Symbol: oe.Order.Symbol,
Time: time.Unix(oe.UpdateTime, 0),
Price: utils.ParseFloat64(oe.Order.Price),
StopPx: utils.ParseFloat64(oe.Order.StopPx),
AvgPrice: utils.ParseFloat64(oe.Order.AvgPrice),
FilledAmount: utils.ParseFloat64(oe.Order.FilledAmount),
Status: b.orderStatus(futures.OrderStatusType(oe.Order.Status)),
Amount: utils.ParseFloat64(oe.Order.Amount),
}
if oe.Order.Direction == "SELL" {
o.Direction = Sell
} else {
o.Direction = Buy
}
orders = append(orders, o)
b.orderCallBack(orders)
}
}
errHandler := func(err error) {
fmt.Println(err)
glog.Error(err)
}
_, _, err = WsUserDataServe(listenKey, wsUserDataHandler, errHandler)
if err != nil {
glog.Error(err)
fmt.Println(err)
}
// 定时给listenKey续期
go func() {
time.Sleep(1800 * time.Second)
err := b.client.NewKeepaliveUserStreamService().ListenKey(b.listenKey).Do(context.Background())
if err != nil {
glog.Error(err)
}
}()
}
return nil
}
func NewBinanceFutures(params *Parameters) *BinanceFutures {
client := futures.NewClient(params.AccessKey, params.SecretKey)
b := &BinanceFutures{
client: client,
}
if params.ProxyURL != "" {
b.SetProxy(params.ProxyURL)
}
return b
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
Go
1
https://gitee.com/378077287/exchanges.git
git@gitee.com:378077287/exchanges.git
378077287
exchanges
exchanges
v0.0.2

搜索帮助