bbgo_origin/pkg/exchange/max/maxapi/order.go
c9s cad8349a1a remove state OrderStateFinalizing from the order state
since we are only interested in the closed orders
2021-03-18 01:15:49 +08:00

496 lines
12 KiB
Go

package max
import (
"context"
"strconv"
"time"
"github.com/pkg/errors"
)
type OrderStateToQuery int
const (
All = iota
Active
Closed
)
type OrderState string
const (
OrderStateDone = OrderState("done")
OrderStateCancel = OrderState("cancel")
OrderStateWait = OrderState("wait")
OrderStateConvert = OrderState("convert")
OrderStateFinalizing = OrderState("finalizing")
OrderStateFailed = OrderState("failed")
)
type OrderType string
// Order types that the API can return.
const (
OrderTypeMarket = OrderType("market")
OrderTypeLimit = OrderType("limit")
OrderTypeStopLimit = OrderType("stop_limit")
OrderTypeStopMarket = OrderType("stop_market")
)
type QueryOrderOptions struct {
GroupID int
Offset int
Limit int
}
// OrderService manages the Order endpoint.
type OrderService struct {
client *RestClient
}
// Order represents one returned order (POST order/GET order/GET orders) on the max platform.
type Order struct {
ID uint64 `json:"id,omitempty" db:"exchange_id"`
Side string `json:"side" db:"side"`
OrderType OrderType `json:"ord_type,omitempty" db:"order_type"`
Price string `json:"price" db:"price"`
AveragePrice string `json:"avg_price,omitempty" db:"average_price"`
State OrderState `json:"state,omitempty" db:"state"`
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 `json:"-" db:"created_at"`
CreatedAtMs int64 `json:"created_at_in_ms,omitempty"`
InsertedAt time.Time `json:"-" db:"inserted_at"`
}
// Open returns open orders
func (s *OrderService) Closed(market string, options QueryOrderOptions) ([]Order, error) {
payload := map[string]interface{}{
"market": market,
"state": []OrderState{OrderStateDone, OrderStateCancel, OrderStateFailed},
"order_by": "desc",
"pagination": false,
}
if options.GroupID > 0 {
payload["group_id"] = options.GroupID
}
if options.Offset > 0 {
payload["offset"] = options.Offset
}
if options.Limit > 0 {
payload["limit"] = options.Limit
}
req, err := s.client.newAuthenticatedRequest("GET", "v2/orders", payload)
if err != nil {
return nil, err
}
response, err := s.client.sendRequest(req)
if err != nil {
return nil, err
}
var orders []Order
if err := response.DecodeJSON(&orders); err != nil {
return nil, err
}
return orders, nil
}
// Open returns open orders
func (s *OrderService) Open(market string, options QueryOrderOptions) ([]Order, error) {
payload := map[string]interface{}{
"market": market,
// "state": []OrderState{OrderStateWait, OrderStateConvert},
"order_by": "desc",
"pagination": false,
}
if options.GroupID > 0 {
payload["group_id"] = options.GroupID
}
req, err := s.client.newAuthenticatedRequest("GET", "v2/orders", payload)
if err != nil {
return nil, err
}
response, err := s.client.sendRequest(req)
if err != nil {
return nil, err
}
var orders []Order
if err := response.DecodeJSON(&orders); err != nil {
return nil, err
}
return orders, nil
}
// All returns all orders for the authenticated account.
func (s *OrderService) All(market string, limit, page int, states ...OrderState) ([]Order, error) {
payload := map[string]interface{}{
"market": market,
"limit": limit,
"page": page,
"state": states,
"order_by": "desc",
}
req, err := s.client.newAuthenticatedRequest("GET", "v2/orders", payload)
if err != nil {
return nil, err
}
response, err := s.client.sendRequest(req)
if err != nil {
return nil, err
}
var orders []Order
if err := response.DecodeJSON(&orders); err != nil {
return nil, err
}
return orders, nil
}
// CancelAll active orders for the authenticated account.
func (s *OrderService) CancelAll(side string, market string) error {
payload := map[string]interface{}{}
if side == "buy" || side == "sell" {
payload["side"] = side
}
if market != "all" {
payload["market"] = market
}
req, err := s.client.newAuthenticatedRequest("POST", "v2/orders/clear", payload)
if err != nil {
return err
}
_, err = s.client.sendRequest(req)
if err != nil {
return err
}
return nil
}
// Options carry the option fields for REST API
type Options map[string]interface{}
// Create a new order.
func (s *OrderService) Create(market string, side string, volume float64, price float64, orderType string, options Options) (*Order, error) {
options["market"] = market
options["volume"] = strconv.FormatFloat(volume, 'f', -1, 64)
options["price"] = strconv.FormatFloat(price, 'f', -1, 64)
options["side"] = side
options["ord_type"] = orderType
response, err := s.client.sendAuthenticatedRequest("POST", "v2/orders", options)
if err != nil {
return nil, err
}
var order = Order{}
if err := response.DecodeJSON(&order); err != nil {
return nil, err
}
return &order, nil
}
// Create multiple order in a single request
func (s *OrderService) CreateMulti(market string, orders []Order) (*MultiOrderResponse, error) {
req := s.NewCreateMultiOrderRequest()
req.Market(market)
req.AddOrders(orders...)
return req.Do(context.Background())
}
// Cancel the order with id `orderID`.
func (s *OrderService) Cancel(orderID uint64, clientOrderID string) error {
req := s.NewOrderCancelRequest()
if orderID > 0 {
req.ID(orderID)
} else if len(clientOrderID) > 0 {
req.ClientOrderID(clientOrderID)
}
return req.Do(context.Background())
}
type OrderCancelAllRequestParams struct {
*PrivateRequestParams
Side string `json:"side,omitempty"`
Market string `json:"market,omitempty"`
GroupID int64 `json:"groupID,omitempty"`
}
type OrderCancelAllRequest struct {
client *RestClient
params OrderCancelAllRequestParams
side *string
market *string
groupID *int64
}
func (r *OrderCancelAllRequest) Side(side string) *OrderCancelAllRequest {
r.side = &side
return r
}
func (r *OrderCancelAllRequest) Market(market string) *OrderCancelAllRequest {
r.market = &market
return r
}
func (r *OrderCancelAllRequest) GroupID(groupID int64) *OrderCancelAllRequest {
r.groupID = &groupID
return r
}
func (r *OrderCancelAllRequest) Do(ctx context.Context) (orders []Order, err error) {
var payload = map[string]interface{}{}
if r.side != nil {
payload["side"] = *r.side
}
if r.market != nil {
payload["market"] = *r.market
}
if r.groupID != nil {
payload["groupID"] = *r.groupID
}
req, err := r.client.newAuthenticatedRequest("POST", "v2/orders/clear", payload)
if err != nil {
return
}
response, err := r.client.sendRequest(req)
if err != nil {
return
}
err = response.DecodeJSON(&orders)
return
}
func (s *OrderService) NewOrderCancelAllRequest() *OrderCancelAllRequest {
return &OrderCancelAllRequest{client: s.client}
}
type OrderCancelRequestParams struct {
*PrivateRequestParams
ID uint64 `json:"id,omitempty"`
ClientOrderID string `json:"client_oid,omitempty"`
}
type OrderCancelRequest struct {
client *RestClient
params OrderCancelRequestParams
}
func (r *OrderCancelRequest) ID(id uint64) *OrderCancelRequest {
r.params.ID = id
return r
}
func (r *OrderCancelRequest) ClientOrderID(id string) *OrderCancelRequest {
r.params.ClientOrderID = id
return r
}
func (r *OrderCancelRequest) Do(ctx context.Context) error {
req, err := r.client.newAuthenticatedRequest("POST", "v2/order/delete", &r.params)
if err != nil {
return err
}
response, err := r.client.sendRequest(req)
if err != nil {
return err
}
var order = Order{}
if err := response.DecodeJSON(&order); err != nil {
return err
}
return err
}
func (s *OrderService) NewOrderCancelRequest() *OrderCancelRequest {
return &OrderCancelRequest{client: s.client}
}
// Status retrieves the given order from the API.
func (s *OrderService) Get(orderID uint64) (*Order, error) {
payload := map[string]interface{}{
"id": orderID,
}
req, err := s.client.newAuthenticatedRequest("GET", "v2/order", payload)
if err != nil {
return &Order{}, err
}
response, err := s.client.sendRequest(req)
if err != nil {
return nil, err
}
var order = Order{}
if err := response.DecodeJSON(&order); err != nil {
return nil, err
}
return &order, nil
}
type MultiOrderRequestParams struct {
*PrivateRequestParams
Market string `json:"market"`
Orders []Order `json:"orders"`
}
type MultiOrderResponse []struct {
Error string `json:"error,omitempty"`
Order Order `json:"order,omitempty"`
}
type CreateMultiOrderRequest struct {
client *RestClient
params MultiOrderRequestParams
}
func (r *CreateMultiOrderRequest) Market(market string) *CreateMultiOrderRequest {
r.params.Market = market
return r
}
func (r *CreateMultiOrderRequest) AddOrders(orders ...Order) *CreateMultiOrderRequest {
r.params.Orders = append(r.params.Orders, orders...)
return r
}
func (r *CreateMultiOrderRequest) Do(ctx context.Context) (multiOrderResponse *MultiOrderResponse, err error) {
req, err := r.client.newAuthenticatedRequest("POST", "v2/orders/multi/onebyone", r.params)
if err != nil {
return multiOrderResponse, errors.Wrapf(err, "order create error")
}
response, err := r.client.sendRequest(req)
if err != nil {
return multiOrderResponse, err
}
multiOrderResponse = &MultiOrderResponse{}
if errJson := response.DecodeJSON(multiOrderResponse); errJson != nil {
return multiOrderResponse, errJson
}
return multiOrderResponse, err
}
func (s *OrderService) NewCreateMultiOrderRequest() *CreateMultiOrderRequest {
return &CreateMultiOrderRequest{client: s.client}
}
type CreateOrderRequestParams struct {
*PrivateRequestParams
Market string `json:"market"`
Volume string `json:"volume"`
Price string `json:"price,omitempty"`
StopPrice string `json:"stop_price,omitempty"`
Side string `json:"side"`
OrderType string `json:"ord_type"`
ClientOrderID string `json:"client_oid,omitempty"`
GroupID string `json:"group_id,omitempty"`
}
type CreateOrderRequest struct {
client *RestClient
params CreateOrderRequestParams
}
func (r *CreateOrderRequest) Market(market string) *CreateOrderRequest {
r.params.Market = market
return r
}
func (r *CreateOrderRequest) Volume(volume string) *CreateOrderRequest {
r.params.Volume = volume
return r
}
func (r *CreateOrderRequest) Price(price string) *CreateOrderRequest {
r.params.Price = price
return r
}
func (r *CreateOrderRequest) StopPrice(price string) *CreateOrderRequest {
r.params.StopPrice = price
return r
}
func (r *CreateOrderRequest) Side(side string) *CreateOrderRequest {
r.params.Side = side
return r
}
func (r *CreateOrderRequest) OrderType(orderType string) *CreateOrderRequest {
r.params.OrderType = orderType
return r
}
func (r *CreateOrderRequest) ClientOrderID(clientOrderID string) *CreateOrderRequest {
r.params.ClientOrderID = clientOrderID
return r
}
func (r *CreateOrderRequest) Do(ctx context.Context) (order *Order, err error) {
req, err := r.client.newAuthenticatedRequest("POST", "v2/orders", &r.params)
if err != nil {
return order, errors.Wrapf(err, "order create error")
}
response, err := r.client.sendRequest(req)
if err != nil {
return order, err
}
order = &Order{}
if err := response.DecodeJSON(order); err != nil {
return nil, err
}
return order, err
}
func (s *OrderService) NewCreateOrderRequest() *CreateOrderRequest {
return &CreateOrderRequest{client: s.client}
}