mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-25 16:25:16 +00:00
first max token market maker
This commit is contained in:
parent
cd80a68e50
commit
a8c972dfb1
|
@ -32,20 +32,20 @@ type OrderService struct {
|
|||
type Order struct {
|
||||
ID uint64 `json:"id,omitempty" db:"exchange_id"`
|
||||
Side string `json:"side" db:"side"`
|
||||
OrderType string `json:"ord_type" db:"order_type"`
|
||||
OrderType string `json:"ord_type,omitempty" db:"order_type"`
|
||||
Price string `json:"price" db:"price"`
|
||||
AveragePrice string `json:"avg_price,omitempty" db:"average_price"`
|
||||
State string `json:"state,omitempty" db:"state"`
|
||||
Market string `json:"market" db:"market"`
|
||||
Market string `json:"market,omitempty" db:"market"`
|
||||
Volume string `json:"volume" db:"volume"`
|
||||
RemainingVolume string `json:"remaining_volume,omitempty" db:"remaining_volume"`
|
||||
ExecutedVolume string `json:"executed_volume,omitempty" db:"executed_volume"`
|
||||
TradesCount int64 `json:"trades_count,omitempty" db:"trades_count"`
|
||||
GroupID int64 `json:"group_id,omitempty" db:"group_id"`
|
||||
ClientOID string `json:"client_oid,omitempty" db:"client_oid"`
|
||||
CreatedAt time.Time `db:"created_at"`
|
||||
CreatedAt time.Time `json:"-" db:"created_at"`
|
||||
CreatedAtMs int64 `json:"created_at_in_ms,omitempty"`
|
||||
InsertedAt time.Time `db:"inserted_at"`
|
||||
InsertedAt time.Time `json:"-" db:"inserted_at"`
|
||||
}
|
||||
|
||||
// All returns all orders for the authenticated account.
|
||||
|
@ -182,20 +182,22 @@ func (s *OrderService) Get(orderID uint64) (*Order, error) {
|
|||
// Create multiple order in a single request
|
||||
func (s *OrderService) CreateMulti(market string, orders []Order) ([]Order, error) {
|
||||
var returnOrders []Order
|
||||
req, err := s.client.newAuthenticatedRequest("POST", "v2/orders/multi", map[string]interface{}{
|
||||
req, err := s.client.newAuthenticatedRequest("POST", "v2/orders/multi/onebyone", map[string]interface{}{
|
||||
"market": market,
|
||||
"orders": orders,
|
||||
})
|
||||
if err != nil {
|
||||
return returnOrders, errors.Wrapf(err, "failed to create %s orders", market)
|
||||
}
|
||||
|
||||
response, err := s.client.sendRequest(req)
|
||||
if err != nil {
|
||||
return returnOrders, err
|
||||
}
|
||||
|
||||
if errJson := response.DecodeJSON(&returnOrders); errJson != nil {
|
||||
return returnOrders, errJson
|
||||
}
|
||||
|
||||
return returnOrders, err
|
||||
}
|
||||
|
||||
|
|
|
@ -3,6 +3,9 @@ package max
|
|||
import (
|
||||
"github.com/pkg/errors"
|
||||
"github.com/valyala/fastjson"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/bbgo/types"
|
||||
"github.com/c9s/bbgo/pkg/util"
|
||||
)
|
||||
|
||||
type BaseEvent struct {
|
||||
|
@ -165,6 +168,24 @@ type BalanceMessage struct {
|
|||
Locked string `json:"l"`
|
||||
}
|
||||
|
||||
func (m *BalanceMessage) Balance() (*types.Balance, error) {
|
||||
available, err := util.ParseFloat(m.Available)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
locked, err := util.ParseFloat(m.Locked)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return &types.Balance{
|
||||
Currency: m.Currency,
|
||||
Locked: locked,
|
||||
Available: available,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func parseBalance(v *fastjson.Value) BalanceMessage {
|
||||
return BalanceMessage{
|
||||
Currency: string(v.GetStringBytes("cu")),
|
||||
|
|
|
@ -15,6 +15,10 @@ func (v Value) Float64() float64 {
|
|||
return float64(v) / DefaultPow
|
||||
}
|
||||
|
||||
func (v Value) Int64() int64 {
|
||||
return int64(v)
|
||||
}
|
||||
|
||||
func (v Value) Mul(v2 Value) Value {
|
||||
return NewFromFloat(v.Float64() * v2.Float64())
|
||||
}
|
||||
|
@ -43,3 +47,11 @@ func NewFromString(input string) (Value, error) {
|
|||
func NewFromFloat(val float64) Value {
|
||||
return Value(int64(math.Round(val * DefaultPow)))
|
||||
}
|
||||
|
||||
func NewFromInt(val int) Value {
|
||||
return Value(int64(val * DefaultPow))
|
||||
}
|
||||
|
||||
func NewFromInt64(val int64) Value {
|
||||
return Value(val * DefaultPow)
|
||||
}
|
||||
|
|
|
@ -13,3 +13,13 @@ type Account struct {
|
|||
AccountType string
|
||||
Balances map[string]Balance
|
||||
}
|
||||
|
||||
func (a *Account) UpdateBalance(b Balance) {
|
||||
a.Balances[b.Currency] = b
|
||||
}
|
||||
|
||||
func NewAccount() *Account {
|
||||
return &Account{
|
||||
Balances: make(map[string]Balance),
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,6 +3,7 @@ package types
|
|||
import (
|
||||
"fmt"
|
||||
"sort"
|
||||
"sync"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/bbgo/fixedpoint"
|
||||
)
|
||||
|
@ -34,14 +35,27 @@ func (slice PriceVolumeSlice) Trim() (pvs PriceVolumeSlice) {
|
|||
}
|
||||
|
||||
func (slice PriceVolumeSlice) Copy() PriceVolumeSlice {
|
||||
// this is faster than make
|
||||
// this is faster than make (however it's only for simple types)
|
||||
return append(slice[:0:0], slice...)
|
||||
}
|
||||
|
||||
func (slice PriceVolumeSlice) IndexByVolumeDepth(requiredVolume fixedpoint.Value) int {
|
||||
var tv int64 = 0
|
||||
for x, el := range slice {
|
||||
tv += el.Volume.Int64()
|
||||
if tv >= requiredVolume.Int64() {
|
||||
return x
|
||||
}
|
||||
}
|
||||
|
||||
// not deep enough
|
||||
return -1
|
||||
}
|
||||
|
||||
func (slice PriceVolumeSlice) InsertAt(idx int, pv PriceVolume) PriceVolumeSlice {
|
||||
rear := append([]PriceVolume{}, slice[idx:]...)
|
||||
slice = append(slice[:idx], pv)
|
||||
return append(slice, rear...)
|
||||
newSlice := append(slice[:idx], pv)
|
||||
return append(newSlice, rear...)
|
||||
}
|
||||
|
||||
func (slice PriceVolumeSlice) Remove(price fixedpoint.Value, descending bool) PriceVolumeSlice {
|
||||
|
@ -89,13 +103,26 @@ func (slice PriceVolumeSlice) Upsert(pv PriceVolume, descending bool) PriceVolum
|
|||
return slice
|
||||
}
|
||||
|
||||
//go:generate callbackgen -type OrderBook
|
||||
type OrderBook struct {
|
||||
Symbol string
|
||||
Bids PriceVolumeSlice
|
||||
Asks PriceVolumeSlice
|
||||
|
||||
loadCallbacks []func(book *OrderBook)
|
||||
updateCallbacks []func(book *OrderBook)
|
||||
bidsChangeCallbacks []func(pvs PriceVolumeSlice)
|
||||
asksChangeCallbacks []func(pvs PriceVolumeSlice)
|
||||
}
|
||||
|
||||
func (b *OrderBook) UpdateAsks(pvs PriceVolumeSlice) {
|
||||
func (b *OrderBook) Copy() (book OrderBook) {
|
||||
book = *b
|
||||
book.Bids = b.Bids.Copy()
|
||||
book.Asks = b.Asks.Copy()
|
||||
return book
|
||||
}
|
||||
|
||||
func (b *OrderBook) updateAsks(pvs PriceVolumeSlice) {
|
||||
for _, pv := range pvs {
|
||||
if pv.Volume == 0 {
|
||||
b.Asks = b.Asks.Remove(pv.Price, false)
|
||||
|
@ -103,9 +130,11 @@ func (b *OrderBook) UpdateAsks(pvs PriceVolumeSlice) {
|
|||
b.Asks = b.Asks.Upsert(pv, false)
|
||||
}
|
||||
}
|
||||
|
||||
b.EmitAsksChange(b.Asks)
|
||||
}
|
||||
|
||||
func (b *OrderBook) UpdateBids(pvs PriceVolumeSlice) {
|
||||
func (b *OrderBook) updateBids(pvs PriceVolumeSlice) {
|
||||
for _, pv := range pvs {
|
||||
if pv.Volume == 0 {
|
||||
b.Bids = b.Bids.Remove(pv.Price, true)
|
||||
|
@ -113,17 +142,29 @@ func (b *OrderBook) UpdateBids(pvs PriceVolumeSlice) {
|
|||
b.Bids = b.Bids.Upsert(pv, true)
|
||||
}
|
||||
}
|
||||
|
||||
b.EmitBidsChange(b.Bids)
|
||||
}
|
||||
|
||||
func (b *OrderBook) update(book OrderBook) {
|
||||
b.updateBids(book.Bids)
|
||||
b.updateAsks(book.Asks)
|
||||
}
|
||||
|
||||
func (b *OrderBook) Reset() {
|
||||
b.Bids = nil
|
||||
b.Asks = nil
|
||||
}
|
||||
|
||||
func (b *OrderBook) Load(book OrderBook) {
|
||||
b.Bids = nil
|
||||
b.Asks = nil
|
||||
b.Update(book)
|
||||
b.Reset()
|
||||
b.update(book)
|
||||
b.EmitLoad(b)
|
||||
}
|
||||
|
||||
func (b *OrderBook) Update(book OrderBook) {
|
||||
b.UpdateBids(book.Bids)
|
||||
b.UpdateAsks(book.Asks)
|
||||
b.update(book)
|
||||
b.EmitUpdate(b)
|
||||
}
|
||||
|
||||
func (b *OrderBook) Print() {
|
||||
|
@ -138,3 +179,36 @@ func (b *OrderBook) Print() {
|
|||
fmt.Printf("- BID: %s\n", bid.String())
|
||||
}
|
||||
}
|
||||
|
||||
type MutexOrderBook struct {
|
||||
sync.Mutex
|
||||
|
||||
*OrderBook
|
||||
}
|
||||
|
||||
func NewMutexOrderBook(symbol string) *MutexOrderBook {
|
||||
return &MutexOrderBook{
|
||||
OrderBook: &OrderBook{Symbol: symbol},
|
||||
}
|
||||
}
|
||||
|
||||
func (b *MutexOrderBook) Load(book OrderBook) {
|
||||
b.Lock()
|
||||
defer b.Unlock()
|
||||
|
||||
b.Reset()
|
||||
b.update(book)
|
||||
b.EmitLoad(b.OrderBook)
|
||||
}
|
||||
|
||||
func (b *MutexOrderBook) Get() OrderBook {
|
||||
return b.OrderBook.Copy()
|
||||
}
|
||||
|
||||
func (b *MutexOrderBook) Update(book OrderBook) {
|
||||
b.Lock()
|
||||
defer b.Unlock()
|
||||
|
||||
b.update(book)
|
||||
b.EmitUpdate(b.OrderBook)
|
||||
}
|
||||
|
|
45
bbgo/types/orderbook_callbacks.go
Normal file
45
bbgo/types/orderbook_callbacks.go
Normal file
|
@ -0,0 +1,45 @@
|
|||
// Code generated by "callbackgen -type OrderBook"; DO NOT EDIT.
|
||||
|
||||
package types
|
||||
|
||||
import ()
|
||||
|
||||
func (b *OrderBook) OnLoad(cb func(book *OrderBook)) {
|
||||
b.loadCallbacks = append(b.loadCallbacks, cb)
|
||||
}
|
||||
|
||||
func (b *OrderBook) EmitLoad(book *OrderBook) {
|
||||
for _, cb := range b.loadCallbacks {
|
||||
cb(book)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *OrderBook) OnUpdate(cb func(book *OrderBook)) {
|
||||
b.updateCallbacks = append(b.updateCallbacks, cb)
|
||||
}
|
||||
|
||||
func (b *OrderBook) EmitUpdate(book *OrderBook) {
|
||||
for _, cb := range b.updateCallbacks {
|
||||
cb(book)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *OrderBook) OnBidsChange(cb func(pvs PriceVolumeSlice)) {
|
||||
b.bidsChangeCallbacks = append(b.bidsChangeCallbacks, cb)
|
||||
}
|
||||
|
||||
func (b *OrderBook) EmitBidsChange(pvs PriceVolumeSlice) {
|
||||
for _, cb := range b.bidsChangeCallbacks {
|
||||
cb(pvs)
|
||||
}
|
||||
}
|
||||
|
||||
func (b *OrderBook) OnAsksChange(cb func(pvs PriceVolumeSlice)) {
|
||||
b.asksChangeCallbacks = append(b.asksChangeCallbacks, cb)
|
||||
}
|
||||
|
||||
func (b *OrderBook) EmitAsksChange(pvs PriceVolumeSlice) {
|
||||
for _, cb := range b.asksChangeCallbacks {
|
||||
cb(pvs)
|
||||
}
|
||||
}
|
|
@ -22,6 +22,15 @@ func FormatFloat(val float64, prec int) string {
|
|||
return strconv.FormatFloat(val, 'f', prec, 64)
|
||||
}
|
||||
|
||||
func ParseFloat(s string) (float64, error) {
|
||||
if len(s) == 0 {
|
||||
return 0.0, nil
|
||||
}
|
||||
|
||||
return strconv.ParseFloat(s, 64)
|
||||
}
|
||||
|
||||
|
||||
func MustParseFloat(s string) float64 {
|
||||
if len(s) == 0 {
|
||||
return 0.0
|
||||
|
|
Loading…
Reference in New Issue
Block a user