mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-14 11:03:53 +00:00
pkg/exchange: add marketunit for submit order
This commit is contained in:
parent
d48fa7c202
commit
6f7e02daef
|
@ -12,7 +12,7 @@ type PlaceOrderResponse struct {
|
||||||
OrderLinkId string `json:"orderLinkId"`
|
OrderLinkId string `json:"orderLinkId"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//go:generate PostRequest -url "/v5/order/create" -type PlaceOrderRequest -responseDataType .PlaceOrderResponse
|
//go:generate PostRequest -url "/v5/order/create" -type PlaceOrderRequest -responseDataType .PlaceOrderResponse -rateLimiter 5+15/1s
|
||||||
type PlaceOrderRequest struct {
|
type PlaceOrderRequest struct {
|
||||||
client requestgen.AuthenticatedAPIClient
|
client requestgen.AuthenticatedAPIClient
|
||||||
|
|
||||||
|
@ -23,6 +23,8 @@ type PlaceOrderRequest struct {
|
||||||
qty string `param:"qty"`
|
qty string `param:"qty"`
|
||||||
orderLinkId string `param:"orderLinkId"`
|
orderLinkId string `param:"orderLinkId"`
|
||||||
timeInForce TimeInForce `param:"timeInForce"`
|
timeInForce TimeInForce `param:"timeInForce"`
|
||||||
|
// Select the unit for qty when create Spot market orders for UTA account
|
||||||
|
marketUnit *MarketUnit `param:"marketUnit"`
|
||||||
|
|
||||||
isLeverage *bool `param:"isLeverage"`
|
isLeverage *bool `param:"isLeverage"`
|
||||||
price *string `param:"price"`
|
price *string `param:"price"`
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
// Code generated by "requestgen -method POST -responseType .APIResponse -responseDataField Result -url /v5/order/create -type PlaceOrderRequest -responseDataType .PlaceOrderResponse"; DO NOT EDIT.
|
// Code generated by "requestgen -method POST -responseType .APIResponse -responseDataField Result -url /v5/order/create -type PlaceOrderRequest -responseDataType .PlaceOrderResponse -rateLimiter 5+15/1s"; DO NOT EDIT.
|
||||||
|
|
||||||
package bybitapi
|
package bybitapi
|
||||||
|
|
||||||
|
@ -6,11 +6,14 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"golang.org/x/time/rate"
|
||||||
"net/url"
|
"net/url"
|
||||||
"reflect"
|
"reflect"
|
||||||
"regexp"
|
"regexp"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var PlaceOrderRequestLimiter = rate.NewLimiter(15.000000150000002, 5)
|
||||||
|
|
||||||
func (p *PlaceOrderRequest) Category(category Category) *PlaceOrderRequest {
|
func (p *PlaceOrderRequest) Category(category Category) *PlaceOrderRequest {
|
||||||
p.category = category
|
p.category = category
|
||||||
return p
|
return p
|
||||||
|
@ -46,6 +49,11 @@ func (p *PlaceOrderRequest) TimeInForce(timeInForce TimeInForce) *PlaceOrderRequ
|
||||||
return p
|
return p
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *PlaceOrderRequest) MarketUnit(marketUnit MarketUnit) *PlaceOrderRequest {
|
||||||
|
p.marketUnit = &marketUnit
|
||||||
|
return p
|
||||||
|
}
|
||||||
|
|
||||||
func (p *PlaceOrderRequest) IsLeverage(isLeverage bool) *PlaceOrderRequest {
|
func (p *PlaceOrderRequest) IsLeverage(isLeverage bool) *PlaceOrderRequest {
|
||||||
p.isLeverage = &isLeverage
|
p.isLeverage = &isLeverage
|
||||||
return p
|
return p
|
||||||
|
@ -245,6 +253,25 @@ func (p *PlaceOrderRequest) GetParameters() (map[string]interface{}, error) {
|
||||||
|
|
||||||
// assign parameter of timeInForce
|
// assign parameter of timeInForce
|
||||||
params["timeInForce"] = timeInForce
|
params["timeInForce"] = timeInForce
|
||||||
|
// check marketUnit field -> json key marketUnit
|
||||||
|
if p.marketUnit != nil {
|
||||||
|
marketUnit := *p.marketUnit
|
||||||
|
|
||||||
|
// TEMPLATE check-valid-values
|
||||||
|
switch marketUnit {
|
||||||
|
case MarketUnitBase, MarketUnitQuote:
|
||||||
|
params["marketUnit"] = marketUnit
|
||||||
|
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("marketUnit value %v is invalid", marketUnit)
|
||||||
|
|
||||||
|
}
|
||||||
|
// END TEMPLATE check-valid-values
|
||||||
|
|
||||||
|
// assign parameter of marketUnit
|
||||||
|
params["marketUnit"] = marketUnit
|
||||||
|
} else {
|
||||||
|
}
|
||||||
// check isLeverage field -> json key isLeverage
|
// check isLeverage field -> json key isLeverage
|
||||||
if p.isLeverage != nil {
|
if p.isLeverage != nil {
|
||||||
isLeverage := *p.isLeverage
|
isLeverage := *p.isLeverage
|
||||||
|
@ -503,6 +530,9 @@ func (p *PlaceOrderRequest) GetPath() string {
|
||||||
|
|
||||||
// Do generates the request object and send the request object to the API endpoint
|
// Do generates the request object and send the request object to the API endpoint
|
||||||
func (p *PlaceOrderRequest) Do(ctx context.Context) (*PlaceOrderResponse, error) {
|
func (p *PlaceOrderRequest) Do(ctx context.Context) (*PlaceOrderResponse, error) {
|
||||||
|
if err := PlaceOrderRequestLimiter.Wait(ctx); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
params, err := p.GetParameters()
|
params, err := p.GetParameters()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -525,15 +555,29 @@ func (p *PlaceOrderRequest) Do(ctx context.Context) (*PlaceOrderResponse, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
var apiResponse APIResponse
|
var apiResponse APIResponse
|
||||||
if err := response.DecodeJSON(&apiResponse); err != nil {
|
|
||||||
return nil, err
|
type responseUnmarshaler interface {
|
||||||
|
Unmarshal(data []byte) error
|
||||||
|
}
|
||||||
|
|
||||||
|
if unmarshaler, ok := interface{}(&apiResponse).(responseUnmarshaler); ok {
|
||||||
|
if err := unmarshaler.Unmarshal(response.Body); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// The line below checks the content type, however, some API server might not send the correct content type header,
|
||||||
|
// Hence, this is commented for backward compatibility
|
||||||
|
// response.IsJSON()
|
||||||
|
if err := response.DecodeJSON(&apiResponse); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type responseValidator interface {
|
type responseValidator interface {
|
||||||
Validate() error
|
Validate() error
|
||||||
}
|
}
|
||||||
validator, ok := interface{}(apiResponse).(responseValidator)
|
|
||||||
if ok {
|
if validator, ok := interface{}(&apiResponse).(responseValidator); ok {
|
||||||
if err := validator.Validate(); err != nil {
|
if err := validator.Validate(); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
|
@ -128,3 +128,10 @@ const (
|
||||||
type AccountType string
|
type AccountType string
|
||||||
|
|
||||||
const AccountTypeSpot AccountType = "SPOT"
|
const AccountTypeSpot AccountType = "SPOT"
|
||||||
|
|
||||||
|
type MarketUnit string
|
||||||
|
|
||||||
|
const (
|
||||||
|
MarketUnitBase MarketUnit = "baseCoin"
|
||||||
|
MarketUnitQuote MarketUnit = "quoteCoin"
|
||||||
|
)
|
||||||
|
|
|
@ -272,23 +272,18 @@ func (e *Exchange) SubmitOrder(ctx context.Context, order types.SubmitOrder) (*t
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
req.Side(side)
|
req.Side(side)
|
||||||
|
req.Qty(order.Market.FormatQuantity(order.Quantity))
|
||||||
|
|
||||||
// set quantity
|
|
||||||
orderQty := order.Quantity
|
|
||||||
// if the order is market buy, the quantity is quote coin, instead of base coin. so we need to convert it.
|
|
||||||
if order.Type == types.OrderTypeMarket && order.Side == types.SideTypeBuy {
|
|
||||||
ticker, err := e.QueryTicker(ctx, order.Market.Symbol)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
orderQty = order.Quantity.Mul(ticker.Buy)
|
|
||||||
}
|
|
||||||
req.Qty(order.Market.FormatQuantity(orderQty))
|
|
||||||
|
|
||||||
// set price
|
|
||||||
switch order.Type {
|
switch order.Type {
|
||||||
case types.OrderTypeLimit:
|
case types.OrderTypeStopLimit, types.OrderTypeLimit, types.OrderTypeLimitMaker:
|
||||||
req.Price(order.Market.FormatPrice(order.Price))
|
req.Price(order.Market.FormatPrice(order.Price))
|
||||||
|
case types.OrderTypeMarket:
|
||||||
|
// Because our order.Quantity unit is base coin, so we indicate the target currency to Base.
|
||||||
|
if order.Side == types.SideTypeBuy {
|
||||||
|
req.MarketUnit(bybitapi.MarketUnitBase)
|
||||||
|
} else {
|
||||||
|
req.MarketUnit(bybitapi.MarketUnitQuote)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// set timeInForce
|
// set timeInForce
|
||||||
|
@ -309,9 +304,6 @@ 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 {
|
|
||||||
return nil, fmt.Errorf("place order rate limiter wait error: %w", err)
|
|
||||||
}
|
|
||||||
timeNow := time.Now()
|
timeNow := time.Now()
|
||||||
res, err := req.Do(ctx)
|
res, err := req.Do(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user