mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-10 09:11:55 +00:00
queryOrder() and test for it
This commit is contained in:
parent
1c5d2dc759
commit
ea5b45bfe4
1
go.sum
1
go.sum
|
@ -1000,7 +1000,6 @@ golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8T
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20220517211312-f3a8303e98df/go.mod h1:K8+ghG5WaK9qNqU5K3HdILfMLy1f3aNYFI/wnl100a8=
|
|
||||||
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
gonum.org/v1/gonum v0.0.0-20180816165407-929014505bf4/go.mod h1:Y+Yx5eoAFn32cQvJDxZx5Dpnq+c3wtXuadVZAcxbbBo=
|
||||||
gonum.org/v1/gonum v0.0.0-20190226202314-149afe6ec0b6/go.mod h1:jevfED4GnIEnJrWW55YmY9DMhajHcnkqVnEXmEtMyNI=
|
gonum.org/v1/gonum v0.0.0-20190226202314-149afe6ec0b6/go.mod h1:jevfED4GnIEnJrWW55YmY9DMhajHcnkqVnEXmEtMyNI=
|
||||||
gonum.org/v1/gonum v0.0.0-20190902003836-43865b531bee/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
|
gonum.org/v1/gonum v0.0.0-20190902003836-43865b531bee/go.mod h1:9mxDZsDKxgMAuccQkewq682L+0eCu4dCN2yonUJTCLU=
|
||||||
|
|
|
@ -2,6 +2,7 @@ package okex
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"hash/fnv"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -172,10 +173,7 @@ func toGlobalOrders(orderDetails []okexapi.OrderDetails) ([]types.Order, error)
|
||||||
|
|
||||||
side := types.SideType(strings.ToUpper(string(orderDetail.Side)))
|
side := types.SideType(strings.ToUpper(string(orderDetail.Side)))
|
||||||
|
|
||||||
orderType, err := toGlobalOrderType(orderDetail.OrderType)
|
orderType := toGlobalOrderType(orderDetail.OrderType)
|
||||||
if err != nil {
|
|
||||||
return orders, err
|
|
||||||
}
|
|
||||||
|
|
||||||
timeInForce := types.TimeInForceGTC
|
timeInForce := types.TimeInForceGTC
|
||||||
switch orderDetail.OrderType {
|
switch orderDetail.OrderType {
|
||||||
|
@ -186,10 +184,7 @@ func toGlobalOrders(orderDetails []okexapi.OrderDetails) ([]types.Order, error)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
orderStatus, err := toGlobalOrderStatus(orderDetail.State)
|
orderStatus := toGlobalOrderStatus(orderDetail.State)
|
||||||
if err != nil {
|
|
||||||
return orders, err
|
|
||||||
}
|
|
||||||
|
|
||||||
isWorking := false
|
isWorking := false
|
||||||
switch orderStatus {
|
switch orderStatus {
|
||||||
|
@ -258,16 +253,21 @@ func toLocalOrderType(orderType types.OrderType) (okexapi.OrderType, error) {
|
||||||
|
|
||||||
func toGlobalOrderType(orderType okexapi.OrderType) types.OrderType {
|
func toGlobalOrderType(orderType okexapi.OrderType) types.OrderType {
|
||||||
switch orderType {
|
switch orderType {
|
||||||
case okexapi.OrderTypeMarket:
|
case okexapi.OrderTypeMarket, okexapi.OrderTypeMarketMakerProtection:
|
||||||
return types.OrderTypeMarket
|
return types.OrderTypeMarket
|
||||||
|
|
||||||
case okexapi.OrderTypeLimit:
|
case okexapi.OrderTypeLimit:
|
||||||
return types.OrderTypeLimit
|
return types.OrderTypeLimit
|
||||||
|
|
||||||
case okexapi.OrderTypePostOnly:
|
case okexapi.OrderTypePostOnly:
|
||||||
return types.OrderTypeLimitMaker
|
return types.OrderTypeLimitMaker
|
||||||
case okexapi.OrderTypeFOK:
|
|
||||||
return types.OrderTypeFillOrKill
|
case okexapi.OrderTypeIOC, okexapi.OrderTypeFOK:
|
||||||
case okexapi.OrderTypeIOC:
|
return types.OrderTypeMarket
|
||||||
return types.OrderTypeIOC
|
|
||||||
|
case okexapi.OrderTypeMarektMakerProtectionPostOnly:
|
||||||
|
return types.OrderTypeLimitMaker
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log.Errorf("unsupported order type: %v", orderType)
|
log.Errorf("unsupported order type: %v", orderType)
|
||||||
return ""
|
return ""
|
||||||
|
@ -280,3 +280,34 @@ func toLocalInterval(src string) string {
|
||||||
return strings.ToUpper(w)
|
return strings.ToUpper(w)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func hashStringID(s string) uint64 {
|
||||||
|
h := fnv.New64a()
|
||||||
|
h.Write([]byte(s))
|
||||||
|
return h.Sum64()
|
||||||
|
}
|
||||||
|
|
||||||
|
func toGlobalOrder(okexOrder *okexapi.OrderDetails, isMargin bool) (*types.Order, error) {
|
||||||
|
timeInForce := types.TimeInForceFOK
|
||||||
|
if okexOrder.OrderType == okexapi.OrderTypeIOC {
|
||||||
|
timeInForce = types.TimeInForceIOC
|
||||||
|
}
|
||||||
|
return &types.Order{
|
||||||
|
SubmitOrder: types.SubmitOrder{
|
||||||
|
ClientOrderID: okexOrder.ClientOrderID,
|
||||||
|
Symbol: okexOrder.InstrumentID,
|
||||||
|
Side: types.SideType(okexOrder.Side),
|
||||||
|
Type: toGlobalOrderType(okexOrder.OrderType),
|
||||||
|
Quantity: okexOrder.Quantity,
|
||||||
|
Price: okexOrder.Price,
|
||||||
|
TimeInForce: types.TimeInForce(timeInForce),
|
||||||
|
},
|
||||||
|
Exchange: types.ExchangeOKEx,
|
||||||
|
OrderID: hashStringID(okexOrder.OrderID),
|
||||||
|
Status: toGlobalOrderStatus(okexOrder.State),
|
||||||
|
ExecutedQuantity: okexOrder.FilledQuantity,
|
||||||
|
CreationTime: types.Time(okexOrder.CreationTime),
|
||||||
|
UpdateTime: types.Time(okexOrder.UpdateTime),
|
||||||
|
IsMargin: isMargin,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
|
|
|
@ -351,37 +351,18 @@ func (e *Exchange) QueryOrder(ctx context.Context, q types.OrderQuery) (*types.O
|
||||||
req.InstrumentID(q.Symbol).
|
req.InstrumentID(q.Symbol).
|
||||||
OrderID(q.OrderID).
|
OrderID(q.OrderID).
|
||||||
ClientOrderID(q.ClientOrderID)
|
ClientOrderID(q.ClientOrderID)
|
||||||
orderID, err := strconv.ParseInt(q.OrderID, 10, 64)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
var order *okexapi.OrderDetails
|
var order *okexapi.OrderDetails
|
||||||
order, err = req.Do(ctx)
|
order, err := req.Do(ctx)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
timeInForce := types.TimeInForceFOK
|
isMargin := false
|
||||||
if order.OrderType == okexapi.OrderTypeIOC {
|
if order.InstrumentType == string(okexapi.InstrumentTypeMARGIN) {
|
||||||
timeInForce = types.TimeInForceIOC
|
isMargin = true
|
||||||
}
|
}
|
||||||
return &types.Order{
|
|
||||||
SubmitOrder: types.SubmitOrder{
|
return toGlobalOrder(order, isMargin)
|
||||||
ClientOrderID: order.ClientOrderID,
|
|
||||||
Symbol: order.InstrumentID,
|
|
||||||
Side: types.SideType(order.Side),
|
|
||||||
Type: toGlobalOrderType(order.OrderType),
|
|
||||||
Quantity: order.Quantity,
|
|
||||||
Price: order.Price,
|
|
||||||
TimeInForce: types.TimeInForce(timeInForce),
|
|
||||||
},
|
|
||||||
Exchange: types.ExchangeOKEx,
|
|
||||||
OrderID: uint64(orderID),
|
|
||||||
Status: toGlobalOrderStatus(order.State),
|
|
||||||
ExecutedQuantity: order.FilledQuantity,
|
|
||||||
CreationTime: types.Time(order.CreationTime),
|
|
||||||
UpdateTime: types.Time(order.UpdateTime),
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,8 @@ const (
|
||||||
OrderTypePostOnly OrderType = "post_only"
|
OrderTypePostOnly OrderType = "post_only"
|
||||||
OrderTypeFOK OrderType = "fok"
|
OrderTypeFOK OrderType = "fok"
|
||||||
OrderTypeIOC OrderType = "ioc"
|
OrderTypeIOC OrderType = "ioc"
|
||||||
|
OrderTypeMarketMakerProtection OrderType = "mmp"
|
||||||
|
OrderTypeMarektMakerProtectionPostOnly OrderType = "mmp_and_post_only"
|
||||||
)
|
)
|
||||||
|
|
||||||
type InstrumentType string
|
type InstrumentType string
|
||||||
|
@ -47,6 +49,7 @@ const (
|
||||||
InstrumentTypeSwap InstrumentType = "SWAP"
|
InstrumentTypeSwap InstrumentType = "SWAP"
|
||||||
InstrumentTypeFutures InstrumentType = "FUTURES"
|
InstrumentTypeFutures InstrumentType = "FUTURES"
|
||||||
InstrumentTypeOption InstrumentType = "OPTION"
|
InstrumentTypeOption InstrumentType = "OPTION"
|
||||||
|
InstrumentTypeMARGIN InstrumentType = "MARGIN"
|
||||||
)
|
)
|
||||||
|
|
||||||
type OrderState string
|
type OrderState string
|
||||||
|
|
|
@ -63,16 +63,16 @@ func TestClient_PlaceOrderRequest(t *testing.T) {
|
||||||
req := srv.NewPlaceOrderRequest()
|
req := srv.NewPlaceOrderRequest()
|
||||||
|
|
||||||
order, err := req.
|
order, err := req.
|
||||||
InstrumentID("XTZ-BTC").
|
InstrumentID("BTC-USDT").
|
||||||
TradeMode("cash").
|
TradeMode("cash").
|
||||||
Side(SideTypeSell).
|
Side(SideTypeBuy).
|
||||||
OrderType(OrderTypeLimit).
|
OrderType(OrderTypeLimit).
|
||||||
Price("0.001").
|
Price("15000").
|
||||||
Quantity("0.01").
|
Quantity("0.0001").
|
||||||
Do(ctx)
|
Do(ctx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.NotEmpty(t, order)
|
assert.NotEmpty(t, order)
|
||||||
t.Logf("order: %+v", order) // Right now account has no money
|
t.Logf("place order: %+v", order)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClient_GetPendingOrderRequest(t *testing.T) {
|
func TestClient_GetPendingOrderRequest(t *testing.T) {
|
||||||
|
@ -83,12 +83,12 @@ func TestClient_GetPendingOrderRequest(t *testing.T) {
|
||||||
odr_type := []string{string(OrderTypeLimit), string(OrderTypeIOC)}
|
odr_type := []string{string(OrderTypeLimit), string(OrderTypeIOC)}
|
||||||
|
|
||||||
pending_order, err := req.
|
pending_order, err := req.
|
||||||
InstrumentID("XTZ-BTC").
|
InstrumentID("BTC-USDT").
|
||||||
OrderTypes(odr_type).
|
OrderTypes(odr_type).
|
||||||
Do(ctx)
|
Do(ctx)
|
||||||
assert.NoError(t, err)
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, pending_order)
|
assert.NotEmpty(t, pending_order)
|
||||||
t.Logf("order: %+v", pending_order)
|
t.Logf("pending order: %+v", pending_order)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestClient_GetOrderDetailsRequest(t *testing.T) {
|
func TestClient_GetOrderDetailsRequest(t *testing.T) {
|
||||||
|
@ -99,9 +99,9 @@ func TestClient_GetOrderDetailsRequest(t *testing.T) {
|
||||||
|
|
||||||
orderDetail, err := req.
|
orderDetail, err := req.
|
||||||
InstrumentID("BTC-USDT").
|
InstrumentID("BTC-USDT").
|
||||||
OrderID("xxx-test-order-id").
|
OrderID("609869603774656544").
|
||||||
Do(ctx)
|
Do(ctx)
|
||||||
assert.Error(t, err) // Right now account has no orders
|
assert.NoError(t, err)
|
||||||
assert.Empty(t, orderDetail)
|
assert.NotEmpty(t, orderDetail)
|
||||||
t.Logf("err: %+v", err)
|
t.Logf("order detail: %+v", orderDetail)
|
||||||
}
|
}
|
||||||
|
|
36
pkg/exchange/okex/query_order_test.go
Normal file
36
pkg/exchange/okex/query_order_test.go
Normal file
|
@ -0,0 +1,36 @@
|
||||||
|
package okex
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"os"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func Test_QueryOrder(t *testing.T) {
|
||||||
|
key := os.Getenv("OKEX_API_KEY")
|
||||||
|
secret := os.Getenv("OKEX_API_SECRET")
|
||||||
|
passphrase := os.Getenv("OKEX_API_PASSPHRASE")
|
||||||
|
if len(key) == 0 && len(secret) == 0 {
|
||||||
|
t.Skip("api key/secret are not configured")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(passphrase) == 0 {
|
||||||
|
t.Skip("passphrase are not configured")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
e := New(key, secret, passphrase)
|
||||||
|
|
||||||
|
queryOrder := types.OrderQuery{
|
||||||
|
Symbol: "BTC-USDT",
|
||||||
|
OrderID: "609869603774656544",
|
||||||
|
}
|
||||||
|
orderDetail, err := e.QueryOrder(context.Background(), queryOrder)
|
||||||
|
if assert.NoError(t, err) {
|
||||||
|
assert.NotEmpty(t, orderDetail)
|
||||||
|
}
|
||||||
|
t.Logf("order detail: %+v", orderDetail)
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user