bbgo_origin/pkg/exchange/max/maxapi/order.go

371 lines
9.8 KiB
Go
Raw Normal View History

2020-10-02 02:10:59 +00:00
package max
//go:generate -command GetRequest requestgen -method GET
//go:generate -command PostRequest requestgen -method POST
2020-10-02 02:10:59 +00:00
import (
2020-10-05 10:49:59 +00:00
"context"
"net/url"
2020-10-02 02:10:59 +00:00
"time"
"github.com/c9s/requestgen"
2020-10-02 02:10:59 +00:00
"github.com/pkg/errors"
2022-05-26 11:52:38 +00:00
"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types"
2020-10-02 02:10:59 +00:00
)
2022-05-27 08:46:29 +00:00
var (
relUrlV2Orders *url.URL
relUrlV2OrdersMultiOneByOne *url.URL
)
func mustParseURL(s string) *url.URL {
u, err := url.Parse(s)
if err != nil {
panic(err)
}
return u
}
func init() {
relUrlV2Orders = mustParseURL("v2/orders")
relUrlV2OrdersMultiOneByOne = mustParseURL("v2/orders/multi/onebyone")
}
2022-05-26 11:52:38 +00:00
type WalletType string
const (
WalletTypeSpot WalletType = "spot"
WalletTypeMargin WalletType = "m"
)
2020-10-02 02:10:59 +00:00
type OrderStateToQuery int
const (
All = iota
Active
Closed
)
2020-10-08 14:03:25 +00:00
type OrderState string
const (
OrderStateDone = OrderState("done")
OrderStateCancel = OrderState("cancel")
OrderStateWait = OrderState("wait")
OrderStateConvert = OrderState("convert")
OrderStateFinalizing = OrderState("finalizing")
2020-10-25 14:41:54 +00:00
OrderStateFailed = OrderState("failed")
2020-10-08 14:03:25 +00:00
)
2020-10-02 02:10:59 +00:00
type OrderType string
// Order types that the API can return.
const (
2020-10-25 14:41:54 +00:00
OrderTypeMarket = OrderType("market")
OrderTypeLimit = OrderType("limit")
2021-03-21 03:10:41 +00:00
OrderTypePostOnly = OrderType("post_only")
2020-10-25 14:41:54 +00:00
OrderTypeStopLimit = OrderType("stop_limit")
OrderTypeStopMarket = OrderType("stop_market")
OrderTypeIOCLimit = OrderType("ioc_limit")
2020-10-02 02:10:59 +00:00
)
type QueryOrderOptions struct {
GroupID int
2020-12-29 08:00:03 +00:00
Offset int
Limit int
Page int
2022-01-26 15:51:23 +00:00
OrderBy string
}
2020-10-02 02:10:59 +00:00
// OrderService manages the Order endpoint.
type OrderService struct {
client *RestClient
}
2022-05-26 11:52:38 +00:00
type SubmitOrder struct {
Side string `json:"side"`
Market string `json:"market"`
Price string `json:"price"`
StopPrice string `json:"stop_price,omitempty"`
OrderType OrderType `json:"ord_type"`
Volume string `json:"volume"`
GroupID uint32 `json:"group_id,omitempty"`
ClientOID string `json:"client_oid,omitempty"`
}
2020-10-02 02:10:59 +00:00
// Order represents one returned order (POST order/GET order/GET orders) on the max platform.
type Order struct {
ID uint64 `json:"id,omitempty"`
2022-05-26 11:52:38 +00:00
WalletType string `json:"wallet_type,omitempty"`
Side string `json:"side"`
OrderType OrderType `json:"ord_type"`
2022-05-26 11:52:38 +00:00
Price fixedpoint.Value `json:"price,omitempty"`
StopPrice fixedpoint.Value `json:"stop_price,omitempty"`
AveragePrice fixedpoint.Value `json:"avg_price,omitempty"`
State OrderState `json:"state,omitempty"`
Market string `json:"market,omitempty"`
2022-05-26 11:52:38 +00:00
Volume fixedpoint.Value `json:"volume"`
RemainingVolume fixedpoint.Value `json:"remaining_volume,omitempty"`
ExecutedVolume fixedpoint.Value `json:"executed_volume,omitempty"`
TradesCount int64 `json:"trades_count,omitempty"`
GroupID uint32 `json:"group_id,omitempty"`
ClientOID string `json:"client_oid,omitempty"`
2022-05-26 11:52:38 +00:00
CreatedAt time.Time `json:"-"`
CreatedAtMs types.MillisecondTimestamp `json:"created_at_in_ms,omitempty"`
2022-05-26 11:52:38 +00:00
InsertedAt time.Time `json:"-"`
}
2020-11-05 00:33:57 +00:00
// Open returns open orders
func (s *OrderService) Closed(market string, options QueryOrderOptions) ([]Order, error) {
2022-04-20 05:20:54 +00:00
req := s.NewGetOrdersRequest()
req.Market(market)
req.State([]OrderState{OrderStateDone, OrderStateCancel})
2020-11-05 00:33:57 +00:00
if options.GroupID > 0 {
2022-04-20 05:20:54 +00:00
req.GroupID(uint32(options.GroupID))
2020-11-05 00:33:57 +00:00
}
if options.Offset > 0 {
2022-04-20 05:20:54 +00:00
req.Offset(options.Offset)
2020-11-05 00:33:57 +00:00
}
if options.Limit > 0 {
2022-04-20 05:20:54 +00:00
req.Limit(options.Limit)
2022-01-26 15:51:23 +00:00
}
2020-11-05 00:33:57 +00:00
2022-04-20 05:20:54 +00:00
if options.Page > 0 {
req.Page(options.Page)
2020-11-05 00:33:57 +00:00
}
2022-04-20 05:20:54 +00:00
if len(options.OrderBy) > 0 {
req.OrderBy(options.OrderBy)
2020-11-05 00:33:57 +00:00
}
2022-04-20 05:20:54 +00:00
return req.Do(context.Background())
2020-11-05 00:33:57 +00:00
}
// Open returns open orders
func (s *OrderService) Open(market string, options QueryOrderOptions) ([]Order, error) {
2022-04-20 05:20:54 +00:00
req := s.NewGetOrdersRequest()
req.Market(market)
// state default ot wait and convert
if options.GroupID > 0 {
2022-04-20 05:20:54 +00:00
req.GroupID(uint32(options.GroupID))
}
2022-04-20 05:20:54 +00:00
return req.Do(context.Background())
2020-10-02 02:10:59 +00:00
}
//go:generate GetRequest -url "v2/orders/history" -type GetOrderHistoryRequest -responseType []Order
type GetOrderHistoryRequest struct {
client requestgen.AuthenticatedAPIClient
2022-05-23 10:34:08 +00:00
market string `param:"market"`
2022-04-21 05:18:00 +00:00
fromID *uint64 `param:"from_id"`
limit *uint `param:"limit"`
}
func (s *OrderService) NewGetOrderHistoryRequest() *GetOrderHistoryRequest {
return &GetOrderHistoryRequest{
client: s.client,
}
}
//go:generate GetRequest -url "v2/orders" -type GetOrdersRequest -responseType []Order
type GetOrdersRequest struct {
client requestgen.AuthenticatedAPIClient
market string `param:"market"`
side *string `param:"side"`
groupID *uint32 `param:"groupID"`
2022-04-20 05:20:54 +00:00
offset *int `param:"offset"`
limit *int `param:"limit"`
page *int `param:"page"`
orderBy *string `param:"order_by" default:"desc"`
state []OrderState `param:"state"`
}
func (s *OrderService) NewGetOrdersRequest() *GetOrdersRequest {
return &GetOrdersRequest{
client: s.client,
}
}
2020-10-02 02:10:59 +00:00
// All returns all orders for the authenticated account.
2020-10-08 14:03:25 +00:00
func (s *OrderService) All(market string, limit, page int, states ...OrderState) ([]Order, error) {
2020-10-02 02:10:59 +00:00
payload := map[string]interface{}{
"market": market,
"limit": limit,
"page": page,
"state": states,
"order_by": "desc",
}
2020-10-08 14:03:25 +00:00
req, err := s.client.newAuthenticatedRequest(context.Background(), "GET", "v2/orders", nil, payload, relUrlV2Orders)
2020-10-02 02:10:59 +00:00
if err != nil {
return nil, err
}
2022-04-19 04:10:15 +00:00
response, err := s.client.SendRequest(req)
2020-10-02 02:10:59 +00:00
if err != nil {
return nil, err
}
var orders []Order
if err := response.DecodeJSON(&orders); err != nil {
return nil, err
}
return orders, nil
}
// Options carry the option fields for REST API
type Options map[string]interface{}
2020-10-05 11:01:43 +00:00
// Create multiple order in a single request
2022-05-26 11:52:38 +00:00
func (s *OrderService) CreateMulti(market string, orders []SubmitOrder) (*MultiOrderResponse, error) {
2020-10-05 11:01:43 +00:00
req := s.NewCreateMultiOrderRequest()
req.Market(market)
req.AddOrders(orders...)
return req.Do(context.Background())
}
//go:generate PostRequest -url "v2/orders/clear" -type OrderCancelAllRequest -responseType []Order
2020-12-29 08:00:03 +00:00
type OrderCancelAllRequest struct {
client requestgen.AuthenticatedAPIClient
2020-12-29 08:00:03 +00:00
side *string `param:"side"`
market *string `param:"market"`
groupID *uint32 `param:"groupID"`
2020-12-29 08:00:03 +00:00
}
func (s *OrderService) NewOrderCancelAllRequest() *OrderCancelAllRequest {
return &OrderCancelAllRequest{client: s.client}
}
//go:generate PostRequest -url "v2/order/delete" -type OrderCancelRequest -responseType .Order
2020-10-05 10:49:59 +00:00
type OrderCancelRequest struct {
client requestgen.AuthenticatedAPIClient
2020-10-05 10:49:59 +00:00
id *uint64 `param:"id,omitempty"`
clientOrderID *string `param:"client_oid,omitempty"`
2020-10-05 10:49:59 +00:00
}
func (s *OrderService) NewOrderCancelRequest() *OrderCancelRequest {
return &OrderCancelRequest{client: s.client}
2020-10-02 02:10:59 +00:00
}
//go:generate GetRequest -url "v2/order" -type GetOrderRequest -responseType .Order
type GetOrderRequest struct {
client requestgen.AuthenticatedAPIClient
2020-10-02 02:10:59 +00:00
id *uint64 `param:"id,omitempty"`
clientOrderID *string `param:"client_oid,omitempty"`
}
2020-10-02 02:10:59 +00:00
func (s *OrderService) NewGetOrderRequest() *GetOrderRequest {
return &GetOrderRequest{client: s.client}
2020-10-02 02:10:59 +00:00
}
2020-10-05 10:49:59 +00:00
type MultiOrderRequestParams struct {
2020-10-25 14:41:54 +00:00
*PrivateRequestParams
2020-10-06 10:44:56 +00:00
2020-10-05 10:49:59 +00:00
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
2021-03-22 09:25:43 +00:00
market *string
groupID *uint32
2022-05-26 11:52:38 +00:00
orders []SubmitOrder
2021-03-22 09:25:43 +00:00
}
func (r *CreateMultiOrderRequest) GroupID(groupID uint32) *CreateMultiOrderRequest {
r.groupID = &groupID
return r
2020-10-05 10:49:59 +00:00
}
func (r *CreateMultiOrderRequest) Market(market string) *CreateMultiOrderRequest {
2021-03-22 09:25:43 +00:00
r.market = &market
2020-10-05 10:49:59 +00:00
return r
}
2022-05-26 11:52:38 +00:00
func (r *CreateMultiOrderRequest) AddOrders(orders ...SubmitOrder) *CreateMultiOrderRequest {
2021-03-22 09:25:43 +00:00
r.orders = append(r.orders, orders...)
2020-10-05 10:49:59 +00:00
return r
}
func (r *CreateMultiOrderRequest) Do(ctx context.Context) (multiOrderResponse *MultiOrderResponse, err error) {
2021-03-22 09:25:43 +00:00
var payload = map[string]interface{}{}
if r.market != nil {
payload["market"] = r.market
} else {
return nil, errors.New("parameter market is required")
}
if r.groupID != nil {
payload["group_id"] = r.groupID
}
if len(r.orders) == 0 {
return nil, errors.New("parameter orders can not be empty")
}
// clear group id
for i := range r.orders {
r.orders[i].GroupID = 0
}
payload["orders"] = r.orders
req, err := r.client.newAuthenticatedRequest(context.Background(), "POST", "v2/orders/multi/onebyone", nil, payload, relUrlV2OrdersMultiOneByOne)
2020-10-02 02:10:59 +00:00
if err != nil {
2020-10-05 10:49:59 +00:00
return multiOrderResponse, errors.Wrapf(err, "order create error")
2020-10-02 02:10:59 +00:00
}
2020-10-03 03:11:59 +00:00
2022-04-19 04:10:15 +00:00
response, err := r.client.SendRequest(req)
2020-10-02 02:10:59 +00:00
if err != nil {
2020-10-05 10:49:59 +00:00
return multiOrderResponse, err
2020-10-02 02:10:59 +00:00
}
2020-10-03 03:11:59 +00:00
2020-10-05 10:49:59 +00:00
multiOrderResponse = &MultiOrderResponse{}
if errJson := response.DecodeJSON(multiOrderResponse); errJson != nil {
return multiOrderResponse, errJson
2020-10-02 02:10:59 +00:00
}
2020-10-03 03:11:59 +00:00
2020-10-05 10:49:59 +00:00
return multiOrderResponse, err
}
func (s *OrderService) NewCreateMultiOrderRequest() *CreateMultiOrderRequest {
return &CreateMultiOrderRequest{client: s.client}
}
//go:generate PostRequest -url "v2/orders" -type CreateOrderRequest -responseType .Order
2020-10-05 11:01:43 +00:00
type CreateOrderRequest struct {
client requestgen.AuthenticatedAPIClient
2020-10-05 11:01:43 +00:00
market string `param:"market,required"`
side string `param:"side,required"`
volume string `param:"volume,required"`
orderType string `param:"ord_type"`
2020-10-05 11:01:43 +00:00
price *string `param:"price"`
stopPrice *string `param:"stop_price"`
clientOrderID *string `param:"client_oid"`
groupID *string `param:"group_id"`
2020-10-05 11:01:43 +00:00
}
func (s *OrderService) NewCreateOrderRequest() *CreateOrderRequest {
return &CreateOrderRequest{client: s.client}
2020-10-02 02:10:59 +00:00
}