mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-10 09:11:55 +00:00
Merge pull request #1250 from bailantaotao/edwin/cancel-order
FEATURE: [bybit] support cancel order
This commit is contained in:
commit
270283d027
35
pkg/exchange/bybit/bybitapi/cancel_order_request.go
Normal file
35
pkg/exchange/bybit/bybitapi/cancel_order_request.go
Normal file
|
@ -0,0 +1,35 @@
|
||||||
|
package bybitapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/c9s/requestgen"
|
||||||
|
)
|
||||||
|
|
||||||
|
//go:generate -command GetRequest requestgen -method GET -responseType .APIResponse -responseDataField Result
|
||||||
|
//go:generate -command PostRequest requestgen -method POST -responseType .APIResponse -responseDataField Result
|
||||||
|
|
||||||
|
type CancelOrderResponse struct {
|
||||||
|
OrderId string `json:"orderId"`
|
||||||
|
OrderLinkId string `json:"orderLinkId"`
|
||||||
|
}
|
||||||
|
|
||||||
|
//go:generate PostRequest -url "/v5/order/cancel" -type CancelOrderRequest -responseDataType .CancelOrderResponse
|
||||||
|
type CancelOrderRequest struct {
|
||||||
|
client requestgen.AuthenticatedAPIClient
|
||||||
|
|
||||||
|
category Category `param:"category" validValues:"spot"`
|
||||||
|
symbol string `param:"symbol"`
|
||||||
|
// User customised order ID. Either orderId or orderLinkId is required
|
||||||
|
orderLinkId string `param:"orderLinkId"`
|
||||||
|
|
||||||
|
orderId *string `param:"orderLinkId"`
|
||||||
|
// orderFilter default type is Order
|
||||||
|
// tpsl order type are not currently supported
|
||||||
|
orderFilter *string `param:"timeInForce" validValues:"Order"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *RestClient) NewCancelOrderRequest() *CancelOrderRequest {
|
||||||
|
return &CancelOrderRequest{
|
||||||
|
client: c,
|
||||||
|
category: CategorySpot,
|
||||||
|
}
|
||||||
|
}
|
219
pkg/exchange/bybit/bybitapi/cancel_order_request_requestgen.go
Normal file
219
pkg/exchange/bybit/bybitapi/cancel_order_request_requestgen.go
Normal file
|
@ -0,0 +1,219 @@
|
||||||
|
// Code generated by "requestgen -method POST -responseType .APIResponse -responseDataField Result -url /v5/order/cancel -type CancelOrderRequest -responseDataType .CancelOrderResponse"; DO NOT EDIT.
|
||||||
|
|
||||||
|
package bybitapi
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"encoding/json"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"reflect"
|
||||||
|
"regexp"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (p *CancelOrderRequest) Category(category Category) *CancelOrderRequest {
|
||||||
|
p.category = category
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CancelOrderRequest) Symbol(symbol string) *CancelOrderRequest {
|
||||||
|
p.symbol = symbol
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CancelOrderRequest) OrderLinkId(orderLinkId string) *CancelOrderRequest {
|
||||||
|
p.orderLinkId = orderLinkId
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CancelOrderRequest) OrderId(orderId string) *CancelOrderRequest {
|
||||||
|
p.orderId = &orderId
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CancelOrderRequest) OrderFilter(orderFilter string) *CancelOrderRequest {
|
||||||
|
p.orderFilter = &orderFilter
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||||
|
func (p *CancelOrderRequest) GetQueryParameters() (url.Values, error) {
|
||||||
|
var params = map[string]interface{}{}
|
||||||
|
|
||||||
|
query := url.Values{}
|
||||||
|
for _k, _v := range params {
|
||||||
|
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||||
|
}
|
||||||
|
|
||||||
|
return query, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetParameters builds and checks the parameters and return the result in a map object
|
||||||
|
func (p *CancelOrderRequest) GetParameters() (map[string]interface{}, error) {
|
||||||
|
var params = map[string]interface{}{}
|
||||||
|
// check category field -> json key category
|
||||||
|
category := p.category
|
||||||
|
|
||||||
|
// TEMPLATE check-valid-values
|
||||||
|
switch category {
|
||||||
|
case "spot":
|
||||||
|
params["category"] = category
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("category value %v is invalid", category)
|
||||||
|
|
||||||
|
}
|
||||||
|
// END TEMPLATE check-valid-values
|
||||||
|
|
||||||
|
// assign parameter of category
|
||||||
|
params["category"] = category
|
||||||
|
// check symbol field -> json key symbol
|
||||||
|
symbol := p.symbol
|
||||||
|
|
||||||
|
// assign parameter of symbol
|
||||||
|
params["symbol"] = symbol
|
||||||
|
// check orderLinkId field -> json key orderLinkId
|
||||||
|
orderLinkId := p.orderLinkId
|
||||||
|
|
||||||
|
// assign parameter of orderLinkId
|
||||||
|
params["orderLinkId"] = orderLinkId
|
||||||
|
// check orderId field -> json key orderLinkId
|
||||||
|
if p.orderId != nil {
|
||||||
|
orderId := *p.orderId
|
||||||
|
|
||||||
|
// assign parameter of orderId
|
||||||
|
params["orderLinkId"] = orderId
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
// check orderFilter field -> json key timeInForce
|
||||||
|
if p.orderFilter != nil {
|
||||||
|
orderFilter := *p.orderFilter
|
||||||
|
|
||||||
|
// TEMPLATE check-valid-values
|
||||||
|
switch orderFilter {
|
||||||
|
case "Order":
|
||||||
|
params["timeInForce"] = orderFilter
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("timeInForce value %v is invalid", orderFilter)
|
||||||
|
|
||||||
|
}
|
||||||
|
// END TEMPLATE check-valid-values
|
||||||
|
|
||||||
|
// assign parameter of orderFilter
|
||||||
|
params["timeInForce"] = orderFilter
|
||||||
|
} else {
|
||||||
|
}
|
||||||
|
|
||||||
|
return params, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||||
|
func (p *CancelOrderRequest) GetParametersQuery() (url.Values, error) {
|
||||||
|
query := url.Values{}
|
||||||
|
|
||||||
|
params, err := p.GetParameters()
|
||||||
|
if err != nil {
|
||||||
|
return query, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _k, _v := range params {
|
||||||
|
if p.isVarSlice(_v) {
|
||||||
|
p.iterateSlice(_v, func(it interface{}) {
|
||||||
|
query.Add(_k+"[]", fmt.Sprintf("%v", it))
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
query.Add(_k, fmt.Sprintf("%v", _v))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return query, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetParametersJSON converts the parameters from GetParameters into the JSON format
|
||||||
|
func (p *CancelOrderRequest) GetParametersJSON() ([]byte, error) {
|
||||||
|
params, err := p.GetParameters()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return json.Marshal(params)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetSlugParameters builds and checks the slug parameters and return the result in a map object
|
||||||
|
func (p *CancelOrderRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||||
|
var params = map[string]interface{}{}
|
||||||
|
|
||||||
|
return params, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CancelOrderRequest) applySlugsToUrl(url string, slugs map[string]string) string {
|
||||||
|
for _k, _v := range slugs {
|
||||||
|
needleRE := regexp.MustCompile(":" + _k + "\\b")
|
||||||
|
url = needleRE.ReplaceAllString(url, _v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return url
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CancelOrderRequest) iterateSlice(slice interface{}, _f func(it interface{})) {
|
||||||
|
sliceValue := reflect.ValueOf(slice)
|
||||||
|
for _i := 0; _i < sliceValue.Len(); _i++ {
|
||||||
|
it := sliceValue.Index(_i).Interface()
|
||||||
|
_f(it)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CancelOrderRequest) isVarSlice(_v interface{}) bool {
|
||||||
|
rt := reflect.TypeOf(_v)
|
||||||
|
switch rt.Kind() {
|
||||||
|
case reflect.Slice:
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CancelOrderRequest) GetSlugsMap() (map[string]string, error) {
|
||||||
|
slugs := map[string]string{}
|
||||||
|
params, err := p.GetSlugParameters()
|
||||||
|
if err != nil {
|
||||||
|
return slugs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _k, _v := range params {
|
||||||
|
slugs[_k] = fmt.Sprintf("%v", _v)
|
||||||
|
}
|
||||||
|
|
||||||
|
return slugs, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *CancelOrderRequest) Do(ctx context.Context) (*CancelOrderResponse, error) {
|
||||||
|
|
||||||
|
params, err := p.GetParameters()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
query := url.Values{}
|
||||||
|
|
||||||
|
apiURL := "/v5/order/cancel"
|
||||||
|
|
||||||
|
req, err := p.client.NewAuthenticatedRequest(ctx, "POST", apiURL, query, params)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
response, err := p.client.SendRequest(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var apiResponse APIResponse
|
||||||
|
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
var data CancelOrderResponse
|
||||||
|
if err := json.Unmarshal(apiResponse.Result, &data); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return &data, nil
|
||||||
|
}
|
|
@ -79,7 +79,7 @@ func TestClient(t *testing.T) {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.Run("PostPlaceOrderRequest", func(t *testing.T) {
|
t.Run("PlaceOrderRequest", func(t *testing.T) {
|
||||||
req := client.NewPlaceOrderRequest().
|
req := client.NewPlaceOrderRequest().
|
||||||
Symbol("DOTUSDT").
|
Symbol("DOTUSDT").
|
||||||
Side(SideBuy).
|
Side(SideBuy).
|
||||||
|
@ -97,4 +97,36 @@ func TestClient(t *testing.T) {
|
||||||
assert.Equal(t, len(ordersResp.List), 1)
|
assert.Equal(t, len(ordersResp.List), 1)
|
||||||
t.Logf("apiResp: %+v", ordersResp.List[0])
|
t.Logf("apiResp: %+v", ordersResp.List[0])
|
||||||
})
|
})
|
||||||
|
|
||||||
|
t.Run("CancelOrderRequest", func(t *testing.T) {
|
||||||
|
req := client.NewPlaceOrderRequest().
|
||||||
|
Symbol("DOTUSDT").
|
||||||
|
Side(SideBuy).
|
||||||
|
OrderType(OrderTypeLimit).
|
||||||
|
Qty("1").
|
||||||
|
Price("4.6").
|
||||||
|
OrderLinkId(uuid.NewString()).
|
||||||
|
TimeInForce(TimeInForceGTC)
|
||||||
|
apiResp, err := req.Do(ctx)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
t.Logf("apiResp: %+v", apiResp)
|
||||||
|
|
||||||
|
ordersResp, err := client.NewGetOpenOrderRequest().OrderLinkId(apiResp.OrderLinkId).Do(ctx)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, len(ordersResp.List), 1)
|
||||||
|
t.Logf("apiResp: %+v", ordersResp.List[0])
|
||||||
|
|
||||||
|
cancelReq := client.NewCancelOrderRequest().
|
||||||
|
Symbol("DOTUSDT").
|
||||||
|
OrderLinkId(apiResp.OrderLinkId)
|
||||||
|
cancelResp, err := cancelReq.Do(ctx)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
t.Logf("apiResp: %+v", cancelResp)
|
||||||
|
|
||||||
|
ordersResp, err = client.NewGetOpenOrderRequest().OrderLinkId(apiResp.OrderLinkId).Do(ctx)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.Equal(t, len(ordersResp.List), 1)
|
||||||
|
assert.Equal(t, ordersResp.List[0].OrderStatus, OrderStatusCancelled)
|
||||||
|
t.Logf("apiResp: %+v", ordersResp.List[0])
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,8 +12,8 @@ type PlaceOrderResponse struct {
|
||||||
OrderLinkId string `json:"orderLinkId"`
|
OrderLinkId string `json:"orderLinkId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:generate PostRequest -url "/v5/order/create" -type PostPlaceOrderRequest -responseDataType .PlaceOrderResponse
|
//go:generate PostRequest -url "/v5/order/create" -type PlaceOrderRequest -responseDataType .PlaceOrderResponse
|
||||||
type PostPlaceOrderRequest struct {
|
type PlaceOrderRequest struct {
|
||||||
client requestgen.AuthenticatedAPIClient
|
client requestgen.AuthenticatedAPIClient
|
||||||
|
|
||||||
category Category `param:"category" validValues:"spot"`
|
category Category `param:"category" validValues:"spot"`
|
||||||
|
@ -49,8 +49,8 @@ type PostPlaceOrderRequest struct {
|
||||||
slOrderType *string `param:"slOrderType"`
|
slOrderType *string `param:"slOrderType"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *RestClient) NewPlaceOrderRequest() *PostPlaceOrderRequest {
|
func (c *RestClient) NewPlaceOrderRequest() *PlaceOrderRequest {
|
||||||
return &PostPlaceOrderRequest{
|
return &PlaceOrderRequest{
|
||||||
client: c,
|
client: c,
|
||||||
category: CategorySpot,
|
category: CategorySpot,
|
||||||
}
|
}
|
|
@ -1,4 +1,4 @@
|
||||||
// Code generated by "requestgen -method POST -responseType .APIResponse -responseDataField Result -url /v5/order/create -type PostPlaceOrderRequest -responseDataType .PlaceOrderResponse"; DO NOT EDIT.
|
// Code generated by "requestgen -method POST -responseType .APIResponse -responseDataField Result -url /v5/order/create -type PlaceOrderRequest -responseDataType .PlaceOrderResponse"; DO NOT EDIT.
|
||||||
|
|
||||||
package bybitapi
|
package bybitapi
|
||||||
|
|
||||||
|
@ -11,148 +11,148 @@ import (
|
||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) Category(category Category) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) Category(category Category) *PlaceOrderRequest {
|
||||||
p.category = category
|
p.category = category
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) Symbol(symbol string) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) Symbol(symbol string) *PlaceOrderRequest {
|
||||||
p.symbol = symbol
|
p.symbol = symbol
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) Side(side Side) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) Side(side Side) *PlaceOrderRequest {
|
||||||
p.side = side
|
p.side = side
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) OrderType(orderType OrderType) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) OrderType(orderType OrderType) *PlaceOrderRequest {
|
||||||
p.orderType = orderType
|
p.orderType = orderType
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) Qty(qty string) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) Qty(qty string) *PlaceOrderRequest {
|
||||||
p.qty = qty
|
p.qty = qty
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) OrderLinkId(orderLinkId string) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) OrderLinkId(orderLinkId string) *PlaceOrderRequest {
|
||||||
p.orderLinkId = orderLinkId
|
p.orderLinkId = orderLinkId
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) TimeInForce(timeInForce TimeInForce) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) TimeInForce(timeInForce TimeInForce) *PlaceOrderRequest {
|
||||||
p.timeInForce = timeInForce
|
p.timeInForce = timeInForce
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) IsLeverage(isLeverage bool) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) IsLeverage(isLeverage bool) *PlaceOrderRequest {
|
||||||
p.isLeverage = &isLeverage
|
p.isLeverage = &isLeverage
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) Price(price string) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) Price(price string) *PlaceOrderRequest {
|
||||||
p.price = &price
|
p.price = &price
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) TriggerDirection(triggerDirection int) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) TriggerDirection(triggerDirection int) *PlaceOrderRequest {
|
||||||
p.triggerDirection = &triggerDirection
|
p.triggerDirection = &triggerDirection
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) OrderFilter(orderFilter string) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) OrderFilter(orderFilter string) *PlaceOrderRequest {
|
||||||
p.orderFilter = &orderFilter
|
p.orderFilter = &orderFilter
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) TriggerPrice(triggerPrice string) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) TriggerPrice(triggerPrice string) *PlaceOrderRequest {
|
||||||
p.triggerPrice = &triggerPrice
|
p.triggerPrice = &triggerPrice
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) TriggerBy(triggerBy string) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) TriggerBy(triggerBy string) *PlaceOrderRequest {
|
||||||
p.triggerBy = &triggerBy
|
p.triggerBy = &triggerBy
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) OrderIv(orderIv string) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) OrderIv(orderIv string) *PlaceOrderRequest {
|
||||||
p.orderIv = &orderIv
|
p.orderIv = &orderIv
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) PositionIdx(positionIdx string) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) PositionIdx(positionIdx string) *PlaceOrderRequest {
|
||||||
p.positionIdx = &positionIdx
|
p.positionIdx = &positionIdx
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) TakeProfit(takeProfit string) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) TakeProfit(takeProfit string) *PlaceOrderRequest {
|
||||||
p.takeProfit = &takeProfit
|
p.takeProfit = &takeProfit
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) StopLoss(stopLoss string) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) StopLoss(stopLoss string) *PlaceOrderRequest {
|
||||||
p.stopLoss = &stopLoss
|
p.stopLoss = &stopLoss
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) TpTriggerBy(tpTriggerBy string) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) TpTriggerBy(tpTriggerBy string) *PlaceOrderRequest {
|
||||||
p.tpTriggerBy = &tpTriggerBy
|
p.tpTriggerBy = &tpTriggerBy
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) SlTriggerBy(slTriggerBy string) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) SlTriggerBy(slTriggerBy string) *PlaceOrderRequest {
|
||||||
p.slTriggerBy = &slTriggerBy
|
p.slTriggerBy = &slTriggerBy
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) ReduceOnly(reduceOnly bool) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) ReduceOnly(reduceOnly bool) *PlaceOrderRequest {
|
||||||
p.reduceOnly = &reduceOnly
|
p.reduceOnly = &reduceOnly
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) CloseOnTrigger(closeOnTrigger bool) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) CloseOnTrigger(closeOnTrigger bool) *PlaceOrderRequest {
|
||||||
p.closeOnTrigger = &closeOnTrigger
|
p.closeOnTrigger = &closeOnTrigger
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) SmpType(smpType string) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) SmpType(smpType string) *PlaceOrderRequest {
|
||||||
p.smpType = &smpType
|
p.smpType = &smpType
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) Mmp(mmp bool) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) Mmp(mmp bool) *PlaceOrderRequest {
|
||||||
p.mmp = &mmp
|
p.mmp = &mmp
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) TpslMode(tpslMode string) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) TpslMode(tpslMode string) *PlaceOrderRequest {
|
||||||
p.tpslMode = &tpslMode
|
p.tpslMode = &tpslMode
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) TpLimitPrice(tpLimitPrice string) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) TpLimitPrice(tpLimitPrice string) *PlaceOrderRequest {
|
||||||
p.tpLimitPrice = &tpLimitPrice
|
p.tpLimitPrice = &tpLimitPrice
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) SlLimitPrice(slLimitPrice string) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) SlLimitPrice(slLimitPrice string) *PlaceOrderRequest {
|
||||||
p.slLimitPrice = &slLimitPrice
|
p.slLimitPrice = &slLimitPrice
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) TpOrderType(tpOrderType string) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) TpOrderType(tpOrderType string) *PlaceOrderRequest {
|
||||||
p.tpOrderType = &tpOrderType
|
p.tpOrderType = &tpOrderType
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) SlOrderType(slOrderType string) *PostPlaceOrderRequest {
|
func (p *PlaceOrderRequest) SlOrderType(slOrderType string) *PlaceOrderRequest {
|
||||||
p.slOrderType = &slOrderType
|
p.slOrderType = &slOrderType
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
// GetQueryParameters builds and checks the query parameters and returns url.Values
|
||||||
func (p *PostPlaceOrderRequest) GetQueryParameters() (url.Values, error) {
|
func (p *PlaceOrderRequest) GetQueryParameters() (url.Values, error) {
|
||||||
var params = map[string]interface{}{}
|
var params = map[string]interface{}{}
|
||||||
|
|
||||||
query := url.Values{}
|
query := url.Values{}
|
||||||
|
@ -164,7 +164,7 @@ func (p *PostPlaceOrderRequest) GetQueryParameters() (url.Values, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetParameters builds and checks the parameters and return the result in a map object
|
// GetParameters builds and checks the parameters and return the result in a map object
|
||||||
func (p *PostPlaceOrderRequest) GetParameters() (map[string]interface{}, error) {
|
func (p *PlaceOrderRequest) GetParameters() (map[string]interface{}, error) {
|
||||||
var params = map[string]interface{}{}
|
var params = map[string]interface{}{}
|
||||||
// check category field -> json key category
|
// check category field -> json key category
|
||||||
category := p.category
|
category := p.category
|
||||||
|
@ -418,7 +418,7 @@ func (p *PostPlaceOrderRequest) GetParameters() (map[string]interface{}, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
// GetParametersQuery converts the parameters from GetParameters into the url.Values format
|
||||||
func (p *PostPlaceOrderRequest) GetParametersQuery() (url.Values, error) {
|
func (p *PlaceOrderRequest) GetParametersQuery() (url.Values, error) {
|
||||||
query := url.Values{}
|
query := url.Values{}
|
||||||
|
|
||||||
params, err := p.GetParameters()
|
params, err := p.GetParameters()
|
||||||
|
@ -440,7 +440,7 @@ func (p *PostPlaceOrderRequest) GetParametersQuery() (url.Values, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetParametersJSON converts the parameters from GetParameters into the JSON format
|
// GetParametersJSON converts the parameters from GetParameters into the JSON format
|
||||||
func (p *PostPlaceOrderRequest) GetParametersJSON() ([]byte, error) {
|
func (p *PlaceOrderRequest) GetParametersJSON() ([]byte, error) {
|
||||||
params, err := p.GetParameters()
|
params, err := p.GetParameters()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -450,13 +450,13 @@ func (p *PostPlaceOrderRequest) GetParametersJSON() ([]byte, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSlugParameters builds and checks the slug parameters and return the result in a map object
|
// GetSlugParameters builds and checks the slug parameters and return the result in a map object
|
||||||
func (p *PostPlaceOrderRequest) GetSlugParameters() (map[string]interface{}, error) {
|
func (p *PlaceOrderRequest) GetSlugParameters() (map[string]interface{}, error) {
|
||||||
var params = map[string]interface{}{}
|
var params = map[string]interface{}{}
|
||||||
|
|
||||||
return params, nil
|
return params, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) applySlugsToUrl(url string, slugs map[string]string) string {
|
func (p *PlaceOrderRequest) applySlugsToUrl(url string, slugs map[string]string) string {
|
||||||
for _k, _v := range slugs {
|
for _k, _v := range slugs {
|
||||||
needleRE := regexp.MustCompile(":" + _k + "\\b")
|
needleRE := regexp.MustCompile(":" + _k + "\\b")
|
||||||
url = needleRE.ReplaceAllString(url, _v)
|
url = needleRE.ReplaceAllString(url, _v)
|
||||||
|
@ -465,7 +465,7 @@ func (p *PostPlaceOrderRequest) applySlugsToUrl(url string, slugs map[string]str
|
||||||
return url
|
return url
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) iterateSlice(slice interface{}, _f func(it interface{})) {
|
func (p *PlaceOrderRequest) iterateSlice(slice interface{}, _f func(it interface{})) {
|
||||||
sliceValue := reflect.ValueOf(slice)
|
sliceValue := reflect.ValueOf(slice)
|
||||||
for _i := 0; _i < sliceValue.Len(); _i++ {
|
for _i := 0; _i < sliceValue.Len(); _i++ {
|
||||||
it := sliceValue.Index(_i).Interface()
|
it := sliceValue.Index(_i).Interface()
|
||||||
|
@ -473,7 +473,7 @@ func (p *PostPlaceOrderRequest) iterateSlice(slice interface{}, _f func(it inter
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) isVarSlice(_v interface{}) bool {
|
func (p *PlaceOrderRequest) isVarSlice(_v interface{}) bool {
|
||||||
rt := reflect.TypeOf(_v)
|
rt := reflect.TypeOf(_v)
|
||||||
switch rt.Kind() {
|
switch rt.Kind() {
|
||||||
case reflect.Slice:
|
case reflect.Slice:
|
||||||
|
@ -482,7 +482,7 @@ func (p *PostPlaceOrderRequest) isVarSlice(_v interface{}) bool {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) GetSlugsMap() (map[string]string, error) {
|
func (p *PlaceOrderRequest) GetSlugsMap() (map[string]string, error) {
|
||||||
slugs := map[string]string{}
|
slugs := map[string]string{}
|
||||||
params, err := p.GetSlugParameters()
|
params, err := p.GetSlugParameters()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -496,7 +496,7 @@ func (p *PostPlaceOrderRequest) GetSlugsMap() (map[string]string, error) {
|
||||||
return slugs, nil
|
return slugs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (p *PostPlaceOrderRequest) Do(ctx context.Context) (*PlaceOrderResponse, error) {
|
func (p *PlaceOrderRequest) Do(ctx context.Context) (*PlaceOrderResponse, error) {
|
||||||
|
|
||||||
params, err := p.GetParameters()
|
params, err := p.GetParameters()
|
||||||
if err != nil {
|
if err != nil {
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
|
"go.uber.org/multierr"
|
||||||
"golang.org/x/time/rate"
|
"golang.org/x/time/rate"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/exchange/bybit/bybitapi"
|
"github.com/c9s/bbgo/pkg/exchange/bybit/bybitapi"
|
||||||
|
@ -66,14 +67,12 @@ func (e *Exchange) PlatformFeeCurrency() string {
|
||||||
|
|
||||||
func (e *Exchange) QueryMarkets(ctx context.Context) (types.MarketMap, error) {
|
func (e *Exchange) QueryMarkets(ctx context.Context) (types.MarketMap, error) {
|
||||||
if err := sharedRateLimiter.Wait(ctx); err != nil {
|
if err := sharedRateLimiter.Wait(ctx); err != nil {
|
||||||
log.WithError(err).Errorf("markets rate limiter wait error")
|
return nil, fmt.Errorf("markets rate limiter wait error: %v", err)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
instruments, err := e.client.NewGetInstrumentsInfoRequest().Do(ctx)
|
instruments, err := e.client.NewGetInstrumentsInfoRequest().Do(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("failed to query instruments, err: %v", err)
|
return nil, fmt.Errorf("failed to get instruments, err: %v", err)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
marketMap := types.MarketMap{}
|
marketMap := types.MarketMap{}
|
||||||
|
@ -86,18 +85,15 @@ func (e *Exchange) QueryMarkets(ctx context.Context) (types.MarketMap, error) {
|
||||||
|
|
||||||
func (e *Exchange) QueryTicker(ctx context.Context, symbol string) (*types.Ticker, error) {
|
func (e *Exchange) QueryTicker(ctx context.Context, symbol string) (*types.Ticker, error) {
|
||||||
if err := sharedRateLimiter.Wait(ctx); err != nil {
|
if err := sharedRateLimiter.Wait(ctx); err != nil {
|
||||||
log.WithError(err).Errorf("ticker rate limiter wait error")
|
return nil, fmt.Errorf("ticker order rate limiter wait error: %v", err)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
s, err := e.client.NewGetTickersRequest().Symbol(symbol).DoWithResponseTime(ctx)
|
s, err := e.client.NewGetTickersRequest().Symbol(symbol).DoWithResponseTime(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("failed to get tickers, symbol: %s, err: %v", symbol, err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(s.List) != 1 {
|
if len(s.List) != 1 {
|
||||||
log.Warnf("unexpected ticker length, exp: 1, got: %d", len(s.List))
|
|
||||||
return nil, fmt.Errorf("unexpected ticker lenght, exp:1, got:%d", len(s.List))
|
return nil, fmt.Errorf("unexpected ticker lenght, exp:1, got:%d", len(s.List))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -121,12 +117,10 @@ func (e *Exchange) QueryTickers(ctx context.Context, symbols ...string) (map[str
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := sharedRateLimiter.Wait(ctx); err != nil {
|
if err := sharedRateLimiter.Wait(ctx); err != nil {
|
||||||
log.WithError(err).Errorf("ticker rate limiter wait error")
|
return nil, fmt.Errorf("tickers rate limiter wait error: %v", err)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
allTickers, err := e.client.NewGetTickersRequest().DoWithResponseTime(ctx)
|
allTickers, err := e.client.NewGetTickersRequest().DoWithResponseTime(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("failed to get tickers, err: %v", err)
|
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -147,20 +141,17 @@ func (e *Exchange) QueryOpenOrders(ctx context.Context, symbol string) (orders [
|
||||||
}
|
}
|
||||||
|
|
||||||
if err = tradeRateLimiter.Wait(ctx); err != nil {
|
if err = tradeRateLimiter.Wait(ctx); err != nil {
|
||||||
log.WithError(err).Errorf("trade rate limiter wait error")
|
return nil, fmt.Errorf("place order rate limiter wait error: %v", err)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
res, err := req.Do(ctx)
|
res, err := req.Do(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("failed to get open order, cursor: %s, err: %v", cursor, err)
|
return nil, fmt.Errorf("failed to query open orders, err: %v", err)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, order := range res.List {
|
for _, order := range res.List {
|
||||||
order, err := toGlobalOrder(order)
|
order, err := toGlobalOrder(order)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("failed to convert order, err: %v", err)
|
return nil, fmt.Errorf("failed to convert order, err: %v", err)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
orders = append(orders, *order)
|
orders = append(orders, *order)
|
||||||
|
@ -223,13 +214,11 @@ func (e *Exchange) SubmitOrder(ctx context.Context, order types.SubmitOrder) (*t
|
||||||
req.OrderLinkId(order.ClientOrderID)
|
req.OrderLinkId(order.ClientOrderID)
|
||||||
|
|
||||||
if err := orderRateLimiter.Wait(ctx); err != nil {
|
if err := orderRateLimiter.Wait(ctx); err != nil {
|
||||||
log.WithError(err).Errorf("place order rate limiter wait error")
|
return nil, fmt.Errorf("place order rate limiter wait error: %v", err)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
res, err := req.Do(ctx)
|
res, err := req.Do(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Warnf("failed to place order, order: %#v, err: %v", order, err)
|
return nil, fmt.Errorf("failed to place order, order: %#v, err: %v", order, err)
|
||||||
return nil, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if len(res.OrderId) == 0 || res.OrderLinkId != order.ClientOrderID {
|
if len(res.OrderId) == 0 || res.OrderLinkId != order.ClientOrderID {
|
||||||
|
@ -247,3 +236,44 @@ func (e *Exchange) SubmitOrder(ctx context.Context, order types.SubmitOrder) (*t
|
||||||
|
|
||||||
return toGlobalOrder(ordersResp.List[0])
|
return toGlobalOrder(ordersResp.List[0])
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (e *Exchange) CancelOrders(ctx context.Context, orders ...types.Order) (errs error) {
|
||||||
|
if len(orders) == 0 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, order := range orders {
|
||||||
|
req := e.client.NewCancelOrderRequest()
|
||||||
|
|
||||||
|
switch {
|
||||||
|
case len(order.ClientOrderID) != 0:
|
||||||
|
req.OrderLinkId(order.ClientOrderID)
|
||||||
|
case len(order.UUID) != 0 && order.OrderID != 0:
|
||||||
|
req.OrderId(order.UUID)
|
||||||
|
default:
|
||||||
|
errs = multierr.Append(
|
||||||
|
errs,
|
||||||
|
fmt.Errorf("the order uuid and client order id are empty, order: %#v", order),
|
||||||
|
)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Symbol(order.Market.Symbol)
|
||||||
|
|
||||||
|
if err := orderRateLimiter.Wait(ctx); err != nil {
|
||||||
|
errs = multierr.Append(errs, fmt.Errorf("cancel order rate limiter wait, order id: %s, error: %v", order.ClientOrderID, err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
res, err := req.Do(ctx)
|
||||||
|
if err != nil {
|
||||||
|
errs = multierr.Append(errs, fmt.Errorf("failed to cancel order id: %s, err: %v", order.ClientOrderID, err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if res.OrderId != order.UUID || res.OrderLinkId != order.ClientOrderID {
|
||||||
|
errs = multierr.Append(errs, fmt.Errorf("unexpected order id, resp: %#v, order: %#v", res, order))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return errs
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user