mirror of
https://github.com/c9s/bbgo.git
synced 2024-09-21 16:51:10 +00:00
237 lines
5.7 KiB
Go
237 lines
5.7 KiB
Go
|
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
|
||
|
}
|