bbgo/pkg/exchange/kucoin/kucoinapi/trade.go

338 lines
10 KiB
Go
Raw Normal View History

package kucoinapi
//go:generate -command GetRequest requestgen -method GET -responseType .APIResponse -responseDataField Data
//go:generate -command PostRequest requestgen -method POST -responseType .APIResponse -responseDataField Data
//go:generate -command DeleteRequest requestgen -method DELETE -responseType .APIResponse -responseDataField Data
import (
"context"
"time"
"github.com/c9s/requestgen"
"github.com/pkg/errors"
"git.qtrade.icu/lychiyu/bbgo/pkg/fixedpoint"
"git.qtrade.icu/lychiyu/bbgo/pkg/types"
)
type TradeService struct {
client *RestClient
}
type OrderResponse struct {
OrderID string `json:"orderId"`
}
func (c *TradeService) NewListHistoryOrdersRequest() *ListHistoryOrdersRequest {
return &ListHistoryOrdersRequest{client: c.client}
}
func (c *TradeService) NewPlaceOrderRequest() *PlaceOrderRequest {
return &PlaceOrderRequest{client: c.client}
}
func (c *TradeService) NewBatchPlaceOrderRequest() *BatchPlaceOrderRequest {
return &BatchPlaceOrderRequest{client: c.client}
}
func (c *TradeService) NewCancelOrderRequest() *CancelOrderRequest {
return &CancelOrderRequest{client: c.client}
}
func (c *TradeService) NewCancelAllOrderRequest() *CancelAllOrderRequest {
return &CancelAllOrderRequest{client: c.client}
}
func (c *TradeService) NewGetFillsRequest() *GetFillsRequest {
return &GetFillsRequest{client: c.client}
}
//go:generate GetRequest -url /api/v1/fills -type GetFillsRequest -responseDataType .FillListPage
type GetFillsRequest struct {
client requestgen.AuthenticatedAPIClient
orderID *string `param:"orderId"`
tradeType *string `param:"tradeType" default:"TRADE"`
symbol *string `param:"symbol"`
side *string `param:"side" validValues:"buy,sell"`
orderType *string `param:"type" validValues:"limit,market,limit_stop,market_stop"`
startAt *time.Time `param:"startAt,milliseconds"`
endAt *time.Time `param:"endAt,milliseconds"`
}
type FillListPage struct {
CurrentPage int `json:"currentPage"`
PageSize int `json:"pageSize"`
TotalNumber int `json:"totalNum"`
TotalPage int `json:"totalPage"`
Items []Fill `json:"items"`
}
type Fill struct {
Symbol string `json:"symbol"`
TradeId string `json:"tradeId"`
OrderId string `json:"orderId"`
CounterOrderId string `json:"counterOrderId"`
Side SideType `json:"side"`
Liquidity LiquidityType `json:"liquidity"`
ForceTaker bool `json:"forceTaker"`
Price fixedpoint.Value `json:"price"`
Size fixedpoint.Value `json:"size"`
Funds fixedpoint.Value `json:"funds"`
Fee fixedpoint.Value `json:"fee"`
FeeRate fixedpoint.Value `json:"feeRate"`
FeeCurrency string `json:"feeCurrency"`
Stop string `json:"stop"`
Type OrderType `json:"type"`
CreatedAt types.MillisecondTimestamp `json:"createdAt"`
TradeType TradeType `json:"tradeType"`
}
//go:generate GetRequest -url /api/v1/hist-orders -type ListHistoryOrdersRequest -responseDataType .HistoryOrderListPage
type ListHistoryOrdersRequest struct {
client requestgen.AuthenticatedAPIClient
symbol *string `param:"symbol"`
startAt *time.Time `param:"startAt,milliseconds"`
endAt *time.Time `param:"endAt,milliseconds"`
}
type HistoryOrder struct {
Symbol string `json:"symbol"`
DealPrice string `json:"dealPrice"`
DealValue string `json:"dealValue"`
Amount string `json:"amount"`
Fee string `json:"fee"`
Side string `json:"side"`
CreatedAt int `json:"createdAt"`
}
type HistoryOrderListPage struct {
CurrentPage int `json:"currentPage"`
PageSize int `json:"pageSize"`
TotalNum int `json:"totalNum"`
TotalPage int `json:"totalPage"`
Items []HistoryOrder `json:"items"`
}
//go:generate GetRequest -url /api/v1/orders -type ListOrdersRequest -responseDataType .OrderListPage
type ListOrdersRequest struct {
client requestgen.AuthenticatedAPIClient
status *string `param:"status" validValues:"active,done"`
symbol *string `param:"symbol"`
side *SideType `param:"side" validValues:"buy,sell"`
orderType *OrderType `param:"type"`
tradeType *TradeType `param:"tradeType" default:"TRADE"`
startAt *time.Time `param:"startAt,milliseconds"`
endAt *time.Time `param:"endAt,milliseconds"`
}
type Order struct {
ID string `json:"id"`
Symbol string `json:"symbol"`
OperationType string `json:"opType"`
Type string `json:"type"`
Side string `json:"side"`
Price fixedpoint.Value `json:"price"`
Size fixedpoint.Value `json:"size"`
Funds fixedpoint.Value `json:"funds"`
DealFunds fixedpoint.Value `json:"dealFunds"`
DealSize fixedpoint.Value `json:"dealSize"`
Fee fixedpoint.Value `json:"fee"`
FeeCurrency string `json:"feeCurrency"`
StopType string `json:"stop"`
StopTriggerred bool `json:"stopTriggered"`
StopPrice fixedpoint.Value `json:"stopPrice"`
TimeInForce TimeInForceType `json:"timeInForce"`
PostOnly bool `json:"postOnly"`
Hidden bool `json:"hidden"`
Iceberg bool `json:"iceberg"`
Channel string `json:"channel"`
ClientOrderID string `json:"clientOid"`
Remark string `json:"remark"`
IsActive bool `json:"isActive"`
CancelExist bool `json:"cancelExist"`
CreatedAt types.MillisecondTimestamp `json:"createdAt"`
}
type OrderListPage struct {
CurrentPage int `json:"currentPage"`
PageSize int `json:"pageSize"`
TotalNumber int `json:"totalNum"`
TotalPage int `json:"totalPage"`
Items []Order `json:"items"`
}
func (c *TradeService) NewListOrdersRequest() *ListOrdersRequest {
return &ListOrdersRequest{client: c.client}
}
//go:generate PostRequest -url /api/v1/orders -type PlaceOrderRequest -responseDataType .OrderResponse
type PlaceOrderRequest struct {
client requestgen.AuthenticatedAPIClient
// A combination of case-sensitive alphanumerics, all numbers, or all letters of up to 32 characters.
clientOrderID *string `param:"clientOid,required" defaultValuer:"uuid()"`
symbol string `param:"symbol,required"`
// A combination of case-sensitive alphanumerics, all numbers, or all letters of up to 8 characters.
tag *string `param:"tag"`
// "buy" or "sell"
side SideType `param:"side"`
orderType OrderType `param:"ordType"`
// limit order parameters
size string `param:"size,required"`
price *string `param:"price"`
timeInForce *TimeInForceType `param:"timeInForce,required"`
postOnly *bool `param:"postOnly"`
}
type CancelOrderResponse struct {
CancelledOrderIDs []string `json:"cancelledOrderIds,omitempty"`
// used when using client order id for canceling order
CancelledOrderId string `json:"cancelledOrderId,omitempty"`
ClientOrderID string `json:"clientOid,omitempty"`
}
//go:generate requestgen -type CancelOrderRequest
type CancelOrderRequest struct {
client requestgen.AuthenticatedAPIClient
orderID *string `param:"orderID"`
clientOrderID *string `param:"clientOrderID"`
}
func (r *CancelOrderRequest) Do(ctx context.Context) (*CancelOrderResponse, error) {
if r.orderID == nil && r.clientOrderID == nil {
return nil, errors.New("either orderID or clientOrderID is required for canceling order")
}
var refURL string
if r.orderID != nil {
refURL = "/api/v1/orders/" + *r.orderID
} else if r.clientOrderID != nil {
refURL = "/api/v1/order/client-order/" + *r.clientOrderID
}
req, err := r.client.NewAuthenticatedRequest(ctx, "DELETE", refURL, nil, nil)
if err != nil {
return nil, err
}
response, err := r.client.SendRequest(req)
if err != nil {
return nil, err
}
var apiResponse struct {
Code string `json:"code"`
Message string `json:"msg"`
Data *CancelOrderResponse `json:"data"`
}
if err := response.DecodeJSON(&apiResponse); err != nil {
return nil, err
}
if apiResponse.Data == nil {
return nil, errors.New("api error: [" + apiResponse.Code + "] " + apiResponse.Message)
}
return apiResponse.Data, nil
}
//go:generate DeleteRequest -url /api/v1/orders -type CancelAllOrderRequest -responseDataType .CancelOrderResponse
type CancelAllOrderRequest struct {
client requestgen.AuthenticatedAPIClient
symbol *string `param:"symbol"`
tradeType *string `param:"tradeType"`
}
// Request via this endpoint to place 5 orders at the same time.
// The order type must be a limit order of the same symbol.
// The interface currently only supports spot trading
type BatchPlaceOrderRequest struct {
client *RestClient
symbol string
reqs []*PlaceOrderRequest
}
func (r *BatchPlaceOrderRequest) Symbol(symbol string) *BatchPlaceOrderRequest {
r.symbol = symbol
return r
}
func (r *BatchPlaceOrderRequest) Add(reqs ...*PlaceOrderRequest) *BatchPlaceOrderRequest {
r.reqs = append(r.reqs, reqs...)
return r
}
func (r *BatchPlaceOrderRequest) Do(ctx context.Context) ([]OrderResponse, error) {
var orderList []map[string]interface{}
for _, req := range r.reqs {
params, err := req.GetParameters()
if err != nil {
return nil, err
}
orderList = append(orderList, params)
}
var payload = map[string]interface{}{
"symbol": r.symbol,
"orderList": orderList,
}
req, err := r.client.NewAuthenticatedRequest(ctx, "POST", "/api/v1/orders/multi", nil, payload)
if err != nil {
return nil, err
}
response, err := r.client.SendRequest(req)
if err != nil {
return nil, err
}
var apiResponse struct {
Code string `json:"code"`
Message string `json:"msg"`
Data []OrderResponse `json:"data"`
}
if err := response.DecodeJSON(&apiResponse); err != nil {
return nil, err
}
if apiResponse.Data == nil {
return nil, errors.New("api error: [" + apiResponse.Code + "] " + apiResponse.Message)
}
return apiResponse.Data, nil
}