bbgo_origin/bbgo/exchange/max/maxapi/userdata.go

237 lines
5.7 KiB
Go
Raw Normal View History

2020-10-01 08:48:08 +00:00
package max
import (
"github.com/pkg/errors"
"github.com/valyala/fastjson"
)
func ParsePrivateEvent(message []byte) (interface{}, error) {
var fp fastjson.Parser
var v, err = fp.ParseBytes(message)
if err != nil {
return nil, errors.Wrap(err, "fail to parse account info raw message")
}
eventType := string(v.GetStringBytes("e"))
switch eventType {
case "order_snapshot":
return parserOrderSnapshotEvent(v)
case "order_update":
return parseOrderUpdateEvent(v)
case "trade_snapshot":
return parseTradeSnapshotEvent(v)
case "trade_update":
return parseTradeUpdateEvent(v)
case "account_snapshot":
return parserAccountSnapshotEvent(v)
case "account_update":
return parserAccountUpdateEvent(v)
case "authenticated":
return parserAuthEvent(v)
case "error":
logger.Errorf("error %s", message)
}
return nil, errors.Wrapf(ErrMessageTypeNotSupported, "private message %s", message)
}
var (
errParseOrder = errors.New("failed parse order")
errParseTrade = errors.New("failed parse trade")
errParseAccount = errors.New("failed parse account")
)
type OrderUpdate struct {
Event string `json:"e"`
ID uint64 `json:"i"`
Side string `json:"sd"`
OrderType string `json:"ot"`
Price string `json:"p"`
Volume string `json:"v"`
AveragePrice string `json:"ap"`
State string `json:"S"`
Market string `json:"M"`
RemainingVolume string `json:"rv"`
ExecutedVolume string `json:"ev"`
TradesCount int64 `json:"tc"`
GroupID int64 `json:"gi"`
ClientOID string `json:"ci"`
CreatedAtMs int64 `json:"T"`
}
func parserOrderUpdate(v *fastjson.Value) (OrderUpdate, error) {
return OrderUpdate{
Event: string(v.GetStringBytes("e")),
ID: v.GetUint64("i"),
Side: string(v.GetStringBytes("sd")),
Market: string(v.GetStringBytes("M")),
OrderType: string(v.GetStringBytes("ot")),
State: string(v.GetStringBytes("S")),
Price: string(v.GetStringBytes("p")),
AveragePrice: string(v.GetStringBytes("ap")),
Volume: string(v.GetStringBytes("v")),
RemainingVolume: string(v.GetStringBytes("rv")),
ExecutedVolume: string(v.GetStringBytes("ev")),
TradesCount: v.GetInt64("tc"),
GroupID: v.GetInt64("gi"),
ClientOID: string(v.GetStringBytes("ci")),
CreatedAtMs: v.GetInt64("T"),
}, nil
}
func parseOrderUpdateEvent(v *fastjson.Value) (OrderUpdate, error) {
rawOrders := v.GetArray("o")
if len(rawOrders) == 0 {
return OrderUpdate{}, errParseOrder
}
return parserOrderUpdate(rawOrders[0])
}
type OrderSnapshot []OrderUpdate
func parserOrderSnapshotEvent(v *fastjson.Value) (orderSnapshot OrderSnapshot, err error) {
var errCount int
rawOrders := v.GetArray("o")
for _, ov := range rawOrders {
o, e := parserOrderUpdate(ov)
if e != nil {
errCount++
err = e
} else {
orderSnapshot = append(orderSnapshot, o)
}
}
if errCount > 0 {
err = errors.Wrapf(err, "failed to parse order snapshot. %d errors in order snapshot. The last error: ", errCount)
}
return
}
type TradeUpdate struct {
ID uint64 `json:"i"`
Side string `json:"sd"`
Price string `json:"p"`
Volume string `json:"v"`
Market string `json:"M"`
Fee string `json:"f"`
FeeCurrency string `json:"fc"`
Timestamp int64 `json:"T"`
OrderID uint64 `json:"oi"`
}
func parseTradeUpdate(v *fastjson.Value) (TradeUpdate, error) {
return TradeUpdate{
ID: v.GetUint64("i"),
Side: string(v.GetStringBytes("sd")),
Price: string(v.GetStringBytes("p")),
Volume: string(v.GetStringBytes("v")),
Market: string(v.GetStringBytes("M")),
Fee: string(v.GetStringBytes("f")),
FeeCurrency: string(v.GetStringBytes("fc")),
Timestamp: v.GetInt64("T"),
OrderID: v.GetUint64("oi"),
}, nil
}
func parseTradeUpdateEvent(v *fastjson.Value) (TradeUpdate, error) {
rawTrades := v.GetArray("t")
if len(rawTrades) == 0 {
return TradeUpdate{}, errParseTrade
}
return parseTradeUpdate(rawTrades[0])
}
type TradeSnapshot []TradeUpdate
func parseTradeSnapshotEvent(v *fastjson.Value) (tradeSnapshot TradeSnapshot, err error) {
var errCount int
rawTrades := v.GetArray("t")
for _, tv := range rawTrades {
t, e := parseTradeUpdate(tv)
if e != nil {
errCount++
err = e
} else {
tradeSnapshot = append(tradeSnapshot, t)
}
}
if errCount > 0 {
err = errors.Wrapf(err, "failed to parse trade snapshot. %d errors in trade snapshot. The last error: ", errCount)
}
return
}
type Balance struct {
Currency string `json:"cu"`
Available string `json:"av"`
Locked string `json:"l"`
}
func parseBalance(v *fastjson.Value) (Balance, error) {
return Balance{
Currency: string(v.GetStringBytes("cu")),
Available: string(v.GetStringBytes("av")),
Locked: string(v.GetStringBytes("l")),
}, nil
}
func parserAccountUpdateEvent(v *fastjson.Value) (Balance, error) {
rawBalances := v.GetArray("B")
if len(rawBalances) == 0 {
return Balance{}, errParseAccount
}
return parseBalance(rawBalances[0])
}
type BalanceSnapshot []Balance
func parserAccountSnapshotEvent(v *fastjson.Value) (balanceSnapshot BalanceSnapshot, err error) {
var errCount int
rawBalances := v.GetArray("B")
for _, bv := range rawBalances {
b, e := parseBalance(bv)
if e != nil {
errCount++
err = e
} else {
balanceSnapshot = append(balanceSnapshot, b)
}
}
if errCount > 0 {
err = errors.Wrapf(err, "failed to parse balance snapshot. %d errors in balance snapshot. The last error: ", errCount)
}
return
}
func parserAuthEvent(v *fastjson.Value) (AuthEvent, error) {
return AuthEvent{
Event: string(v.GetStringBytes("e")),
ID: string(v.GetStringBytes("i")),
Timestamp: v.GetInt64("T"),
}, nil
}