mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-26 00:35:15 +00:00
Merge pull request #927 from c9s/refactor/submit-order
refactor: simplify submit order
This commit is contained in:
commit
d45bc9e509
|
@ -94,7 +94,7 @@ var rootCmd = &cobra.Command{
|
||||||
|
|
||||||
time.Sleep(time.Second)
|
time.Sleep(time.Second)
|
||||||
|
|
||||||
createdOrders, err := exchange.SubmitOrders(ctx, types.SubmitOrder{
|
createdOrder, err := exchange.SubmitOrder(ctx, types.SubmitOrder{
|
||||||
Symbol: symbol,
|
Symbol: symbol,
|
||||||
Market: market,
|
Market: market,
|
||||||
Side: types.SideTypeBuy,
|
Side: types.SideTypeBuy,
|
||||||
|
@ -108,7 +108,7 @@ var rootCmd = &cobra.Command{
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Info(createdOrders)
|
log.Info(createdOrder)
|
||||||
|
|
||||||
cmdutil.WaitForSignal(ctx, syscall.SIGINT, syscall.SIGTERM)
|
cmdutil.WaitForSignal(ctx, syscall.SIGINT, syscall.SIGTERM)
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -169,31 +169,23 @@ func (e *Exchange) QueryOrder(ctx context.Context, q types.OrderQuery) (*types.O
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder) (createdOrders types.OrderSlice, err error) {
|
func (e *Exchange) SubmitOrder(ctx context.Context, order types.SubmitOrder) (createdOrder *types.Order, err error) {
|
||||||
for _, order := range orders {
|
|
||||||
symbol := order.Symbol
|
symbol := order.Symbol
|
||||||
matching, ok := e.matchingBook(symbol)
|
matching, ok := e.matchingBook(symbol)
|
||||||
if !ok {
|
if !ok {
|
||||||
return nil, fmt.Errorf("matching engine is not initialized for symbol %s", symbol)
|
return nil, fmt.Errorf("matching engine is not initialized for symbol %s", symbol)
|
||||||
}
|
}
|
||||||
|
|
||||||
createdOrder, _, err := matching.PlaceOrder(order)
|
createdOrder, _, err = matching.PlaceOrder(order)
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if createdOrder != nil {
|
if createdOrder != nil {
|
||||||
createdOrders = append(createdOrders, *createdOrder)
|
|
||||||
|
|
||||||
// market order can be closed immediately.
|
// market order can be closed immediately.
|
||||||
switch createdOrder.Status {
|
switch createdOrder.Status {
|
||||||
case types.OrderStatusFilled, types.OrderStatusCanceled, types.OrderStatusRejected:
|
case types.OrderStatusFilled, types.OrderStatusCanceled, types.OrderStatusRejected:
|
||||||
e.addClosedOrder(*createdOrder)
|
e.addClosedOrder(*createdOrder)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return createdOrders, nil
|
return createdOrder, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) QueryOpenOrders(ctx context.Context, symbol string) (orders []types.Order, err error) {
|
func (e *Exchange) QueryOpenOrders(ctx context.Context, symbol string) (orders []types.Order, err error) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ func TestTrailingStop_ShortPosition(t *testing.T) {
|
||||||
|
|
||||||
mockEx := mocks.NewMockExchange(mockCtrl)
|
mockEx := mocks.NewMockExchange(mockCtrl)
|
||||||
mockEx.EXPECT().NewStream().Return(&types.StandardStream{}).Times(2)
|
mockEx.EXPECT().NewStream().Return(&types.StandardStream{}).Times(2)
|
||||||
mockEx.EXPECT().SubmitOrders(gomock.Any(), types.SubmitOrder{
|
mockEx.EXPECT().SubmitOrder(gomock.Any(), types.SubmitOrder{
|
||||||
Symbol: "BTCUSDT",
|
Symbol: "BTCUSDT",
|
||||||
Side: types.SideTypeBuy,
|
Side: types.SideTypeBuy,
|
||||||
Type: types.OrderTypeMarket,
|
Type: types.OrderTypeMarket,
|
||||||
|
@ -113,7 +113,7 @@ func TestTrailingStop_LongPosition(t *testing.T) {
|
||||||
|
|
||||||
mockEx := mocks.NewMockExchange(mockCtrl)
|
mockEx := mocks.NewMockExchange(mockCtrl)
|
||||||
mockEx.EXPECT().NewStream().Return(&types.StandardStream{}).Times(2)
|
mockEx.EXPECT().NewStream().Return(&types.StandardStream{}).Times(2)
|
||||||
mockEx.EXPECT().SubmitOrders(gomock.Any(), types.SubmitOrder{
|
mockEx.EXPECT().SubmitOrder(gomock.Any(), types.SubmitOrder{
|
||||||
Symbol: "BTCUSDT",
|
Symbol: "BTCUSDT",
|
||||||
Side: types.SideTypeSell,
|
Side: types.SideTypeSell,
|
||||||
Type: types.OrderTypeMarket,
|
Type: types.OrderTypeMarket,
|
||||||
|
|
|
@ -18,6 +18,10 @@ type PositionCloser interface {
|
||||||
ClosePosition(ctx context.Context, percentage fixedpoint.Value) error
|
ClosePosition(ctx context.Context, percentage fixedpoint.Value) error
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type PositionResetter interface {
|
||||||
|
ResetPosition() error
|
||||||
|
}
|
||||||
|
|
||||||
type PositionReader interface {
|
type PositionReader interface {
|
||||||
CurrentPosition() *types.Position
|
CurrentPosition() *types.Position
|
||||||
}
|
}
|
||||||
|
@ -172,7 +176,7 @@ func (it *CoreInteraction) Commands(i *interact.Interact) {
|
||||||
reply.AddMultipleButtons(generateStrategyButtonsForm(strategies))
|
reply.AddMultipleButtons(generateStrategyButtonsForm(strategies))
|
||||||
reply.Message("Please choose one strategy")
|
reply.Message("Please choose one strategy")
|
||||||
} else {
|
} else {
|
||||||
reply.Message("No strategy supports PositionReader")
|
reply.Message("No any strategy supports PositionReader")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}).Cycle(func(signature string, reply interact.Reply) error {
|
}).Cycle(func(signature string, reply interact.Reply) error {
|
||||||
|
@ -206,6 +210,47 @@ func (it *CoreInteraction) Commands(i *interact.Interact) {
|
||||||
return nil
|
return nil
|
||||||
})
|
})
|
||||||
|
|
||||||
|
i.PrivateCommand("/resetposition", "Reset position", func(reply interact.Reply) error {
|
||||||
|
// it.trader.exchangeStrategies
|
||||||
|
// send symbol options
|
||||||
|
if strategies, found := filterStrategyByInterface((*PositionResetter)(nil), it.exchangeStrategies); found {
|
||||||
|
reply.AddMultipleButtons(generateStrategyButtonsForm(strategies))
|
||||||
|
reply.Message("Please choose one strategy")
|
||||||
|
} else {
|
||||||
|
reply.Message("No strategy supports PositionResetter interface")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}).Next(func(signature string, reply interact.Reply) error {
|
||||||
|
strategy, ok := it.exchangeStrategies[signature]
|
||||||
|
if !ok {
|
||||||
|
reply.Message("Strategy not found")
|
||||||
|
return fmt.Errorf("strategy %s not found", signature)
|
||||||
|
}
|
||||||
|
|
||||||
|
resetter, implemented := strategy.(PositionResetter)
|
||||||
|
if implemented {
|
||||||
|
return resetter.ResetPosition()
|
||||||
|
}
|
||||||
|
|
||||||
|
reset := false
|
||||||
|
err := dynamic.IterateFields(strategy, func(ft reflect.StructField, fv reflect.Value) error {
|
||||||
|
posType := reflect.TypeOf(&types.Position{})
|
||||||
|
if ft.Type == posType {
|
||||||
|
if pos, typeOk := fv.Interface().(*types.Position); typeOk {
|
||||||
|
pos.Reset()
|
||||||
|
reset = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
|
||||||
|
if reset {
|
||||||
|
reply.Message("Position is reset")
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
})
|
||||||
|
|
||||||
i.PrivateCommand("/closeposition", "Close position", func(reply interact.Reply) error {
|
i.PrivateCommand("/closeposition", "Close position", func(reply interact.Reply) error {
|
||||||
// it.trader.exchangeStrategies
|
// it.trader.exchangeStrategies
|
||||||
// send symbol options
|
// send symbol options
|
||||||
|
@ -213,7 +258,7 @@ func (it *CoreInteraction) Commands(i *interact.Interact) {
|
||||||
reply.AddMultipleButtons(generateStrategyButtonsForm(strategies))
|
reply.AddMultipleButtons(generateStrategyButtonsForm(strategies))
|
||||||
reply.Message("Please choose one strategy")
|
reply.Message("Please choose one strategy")
|
||||||
} else {
|
} else {
|
||||||
reply.Message("No strategy supports PositionCloser")
|
reply.Message("No strategy supports PositionCloser interface")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}).Next(func(signature string, reply interact.Reply) error {
|
}).Next(func(signature string, reply interact.Reply) error {
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"go.uber.org/multierr"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
|
@ -42,7 +43,42 @@ func (e *ExchangeOrderExecutionRouter) SubmitOrdersTo(ctx context.Context, sessi
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
return es.Exchange.SubmitOrders(ctx, formattedOrders...)
|
createdOrders, _, err := BatchPlaceOrder(ctx, es.Exchange, formattedOrders...)
|
||||||
|
return createdOrders, err
|
||||||
|
}
|
||||||
|
|
||||||
|
func BatchRetryPlaceOrder(ctx context.Context, exchange types.Exchange, errIdx []int, submitOrders ...types.SubmitOrder) (types.OrderSlice, error) {
|
||||||
|
var createdOrders types.OrderSlice
|
||||||
|
var err error
|
||||||
|
for _, idx := range errIdx {
|
||||||
|
createdOrder, err2 := exchange.SubmitOrder(ctx, submitOrders[idx])
|
||||||
|
if err2 != nil {
|
||||||
|
err = multierr.Append(err, err2)
|
||||||
|
} else if createdOrder != nil {
|
||||||
|
createdOrders = append(createdOrders, *createdOrder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return createdOrders, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// BatchPlaceOrder
|
||||||
|
func BatchPlaceOrder(ctx context.Context, exchange types.Exchange, submitOrders ...types.SubmitOrder) (types.OrderSlice, []int, error) {
|
||||||
|
var createdOrders types.OrderSlice
|
||||||
|
var err error
|
||||||
|
var errIndexes []int
|
||||||
|
for i, submitOrder := range submitOrders {
|
||||||
|
createdOrder, err2 := exchange.SubmitOrder(ctx, submitOrder)
|
||||||
|
if err2 != nil {
|
||||||
|
err = multierr.Append(err, err2)
|
||||||
|
errIndexes = append(errIndexes, i)
|
||||||
|
} else if createdOrder != nil {
|
||||||
|
createdOrder.Tag = submitOrder.Tag
|
||||||
|
createdOrders = append(createdOrders, *createdOrder)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return createdOrders, errIndexes, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *ExchangeOrderExecutionRouter) CancelOrdersTo(ctx context.Context, session string, orders ...types.Order) error {
|
func (e *ExchangeOrderExecutionRouter) CancelOrdersTo(ctx context.Context, session string, orders ...types.Order) error {
|
||||||
|
@ -105,7 +141,8 @@ func (e *ExchangeOrderExecutor) SubmitOrders(ctx context.Context, orders ...type
|
||||||
|
|
||||||
e.notifySubmitOrders(formattedOrders...)
|
e.notifySubmitOrders(formattedOrders...)
|
||||||
|
|
||||||
return e.Session.Exchange.SubmitOrders(ctx, formattedOrders...)
|
createdOrders, _, err := BatchPlaceOrder(ctx, e.Session.Exchange, formattedOrders...)
|
||||||
|
return createdOrders, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *ExchangeOrderExecutor) CancelOrders(ctx context.Context, orders ...types.Order) error {
|
func (e *ExchangeOrderExecutor) CancelOrders(ctx context.Context, orders ...types.Order) error {
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"go.uber.org/multierr"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
|
@ -110,28 +111,14 @@ func (e *GeneralOrderExecutor) SubmitOrders(ctx context.Context, submitOrders ..
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
var createdOrders types.OrderSlice
|
createdOrders, errIdx, err := BatchPlaceOrder(ctx, e.session.Exchange, formattedOrders...)
|
||||||
|
if len(errIdx) > 0 {
|
||||||
retOrders, err := e.session.Exchange.SubmitOrders(ctx, formattedOrders...)
|
createdOrders2, err2 := BatchRetryPlaceOrder(ctx, e.session.Exchange, errIdx, formattedOrders...)
|
||||||
if len(retOrders) > 0 {
|
if err2 != nil {
|
||||||
createdOrders = append(createdOrders, retOrders...)
|
err = multierr.Append(err, err2)
|
||||||
|
} else {
|
||||||
|
createdOrders = append(createdOrders, createdOrders2...)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
// retry once
|
|
||||||
retOrders, err = e.session.Exchange.SubmitOrders(ctx, formattedOrders...)
|
|
||||||
if len(retOrders) > 0 {
|
|
||||||
createdOrders = append(createdOrders, retOrders...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
err = fmt.Errorf("can not place orders: %w", err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// FIXME: map by price and volume
|
|
||||||
for i := 0; i < len(createdOrders); i++ {
|
|
||||||
createdOrders[i].Tag = formattedOrders[i].Tag
|
|
||||||
}
|
}
|
||||||
|
|
||||||
e.orderStore.Add(createdOrders...)
|
e.orderStore.Add(createdOrders...)
|
||||||
|
@ -156,27 +143,25 @@ type OpenPositionOptions struct {
|
||||||
Quantity fixedpoint.Value `json:"quantity,omitempty"`
|
Quantity fixedpoint.Value `json:"quantity,omitempty"`
|
||||||
|
|
||||||
// MarketOrder set to true to open a position with a market order
|
// MarketOrder set to true to open a position with a market order
|
||||||
MarketOrder bool
|
MarketOrder bool `json:"marketOrder,omitempty"`
|
||||||
|
|
||||||
// LimitOrder set to true to open a position with a limit order
|
// LimitOrder set to true to open a position with a limit order
|
||||||
LimitOrder bool
|
LimitOrder bool `json:"limitOrder,omitempty"`
|
||||||
|
|
||||||
// LimitTakerRatio is used when LimitOrder = true, it adjusts the price of the limit order with a ratio.
|
// LimitTakerRatio is used when LimitOrder = true, it adjusts the price of the limit order with a ratio.
|
||||||
// So you can ensure that the limit order can be a taker order. Higher the ratio, higher the chance it could be a taker order.
|
// So you can ensure that the limit order can be a taker order. Higher the ratio, higher the chance it could be a taker order.
|
||||||
LimitTakerRatio fixedpoint.Value
|
LimitTakerRatio fixedpoint.Value `json:"limitTakerRatio,omitempty"`
|
||||||
CurrentPrice fixedpoint.Value
|
CurrentPrice fixedpoint.Value `json:"currentPrice,omitempty"`
|
||||||
Tag string
|
Tags []string `json:"tags"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *GeneralOrderExecutor) OpenPosition(ctx context.Context, options OpenPositionOptions) error {
|
func (e *GeneralOrderExecutor) OpenPosition(ctx context.Context, options OpenPositionOptions) error {
|
||||||
log.Infof("opening %s position: %+v", e.position.Symbol, options)
|
|
||||||
|
|
||||||
price := options.CurrentPrice
|
price := options.CurrentPrice
|
||||||
submitOrder := types.SubmitOrder{
|
submitOrder := types.SubmitOrder{
|
||||||
Symbol: e.position.Symbol,
|
Symbol: e.position.Symbol,
|
||||||
Type: types.OrderTypeMarket,
|
Type: types.OrderTypeMarket,
|
||||||
MarginSideEffect: types.SideEffectTypeMarginBuy,
|
MarginSideEffect: types.SideEffectTypeMarginBuy,
|
||||||
Tag: options.Tag,
|
Tag: strings.Join(options.Tags, ","),
|
||||||
}
|
}
|
||||||
|
|
||||||
if !options.LimitTakerRatio.IsZero() {
|
if !options.LimitTakerRatio.IsZero() {
|
||||||
|
@ -211,6 +196,7 @@ func (e *GeneralOrderExecutor) OpenPosition(ctx context.Context, options OpenPos
|
||||||
submitOrder.Side = types.SideTypeBuy
|
submitOrder.Side = types.SideTypeBuy
|
||||||
submitOrder.Quantity = quantity
|
submitOrder.Quantity = quantity
|
||||||
|
|
||||||
|
Notify("Opening %s long position with quantity %f at price %f", e.position.Symbol, quantity.Float64(), price.Float64())
|
||||||
createdOrder, err2 := e.SubmitOrders(ctx, submitOrder)
|
createdOrder, err2 := e.SubmitOrders(ctx, submitOrder)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
return err2
|
return err2
|
||||||
|
@ -229,6 +215,7 @@ func (e *GeneralOrderExecutor) OpenPosition(ctx context.Context, options OpenPos
|
||||||
submitOrder.Side = types.SideTypeSell
|
submitOrder.Side = types.SideTypeSell
|
||||||
submitOrder.Quantity = quantity
|
submitOrder.Quantity = quantity
|
||||||
|
|
||||||
|
Notify("Opening %s short position with quantity %f at price %f", e.position.Symbol, quantity.Float64(), price.Float64())
|
||||||
createdOrder, err2 := e.SubmitOrders(ctx, submitOrder)
|
createdOrder, err2 := e.SubmitOrders(ctx, submitOrder)
|
||||||
if err2 != nil {
|
if err2 != nil {
|
||||||
return err2
|
return err2
|
||||||
|
@ -275,14 +262,20 @@ func (e *GeneralOrderExecutor) GracefulCancel(ctx context.Context) error {
|
||||||
return e.GracefulCancelActiveOrderBook(ctx, e.activeMakerOrders)
|
return e.GracefulCancelActiveOrderBook(ctx, e.activeMakerOrders)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ClosePosition closes the current position by a percentage.
|
||||||
|
// percentage 0.1 means close 10% position
|
||||||
|
// tag is the order tag you want to attach, you may pass multiple tags, the tags will be combined into one tag string by commas.
|
||||||
func (e *GeneralOrderExecutor) ClosePosition(ctx context.Context, percentage fixedpoint.Value, tags ...string) error {
|
func (e *GeneralOrderExecutor) ClosePosition(ctx context.Context, percentage fixedpoint.Value, tags ...string) error {
|
||||||
submitOrder := e.position.NewMarketCloseOrder(percentage)
|
submitOrder := e.position.NewMarketCloseOrder(percentage)
|
||||||
if submitOrder == nil {
|
if submitOrder == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("closing %s position with tags: %v", e.symbol, tags)
|
tagStr := strings.Join(tags, ",")
|
||||||
submitOrder.Tag = strings.Join(tags, ",")
|
submitOrder.Tag = tagStr
|
||||||
|
|
||||||
|
Notify("closing %s position %s with tags: %v", e.symbol, percentage.Percentage(), tagStr)
|
||||||
|
|
||||||
_, err := e.SubmitOrders(ctx, *submitOrder)
|
_, err := e.SubmitOrders(ctx, *submitOrder)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -384,12 +384,12 @@ var submitOrderCmd = &cobra.Command{
|
||||||
so.TimeInForce = types.TimeInForceGTC
|
so.TimeInForce = types.TimeInForceGTC
|
||||||
}
|
}
|
||||||
|
|
||||||
co, err := session.Exchange.SubmitOrders(ctx, so)
|
co, err := session.Exchange.SubmitOrder(ctx, so)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
log.Infof("submitted order: %+v\ncreated order: %+v", so, co[0])
|
log.Infof("submitted order: %+v\ncreated order: %+v", so, co)
|
||||||
return nil
|
return nil
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
|
@ -11,7 +11,6 @@ func TestLower(t *testing.T) {
|
||||||
assert.Equal(t, []float64{10.0, 11.0}, out)
|
assert.Equal(t, []float64{10.0, 11.0}, out)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
func TestHigher(t *testing.T) {
|
func TestHigher(t *testing.T) {
|
||||||
out := Higher([]float64{10.0, 11.0, 12.0, 13.0, 15.0}, 12.0)
|
out := Higher([]float64{10.0, 11.0, 12.0, 13.0, 15.0}, 12.0)
|
||||||
assert.Equal(t, []float64{13.0, 15.0}, out)
|
assert.Equal(t, []float64{13.0, 15.0}, out)
|
||||||
|
|
|
@ -1251,13 +1251,11 @@ func (e *Exchange) submitSpotOrder(ctx context.Context, order types.SubmitOrder)
|
||||||
return createdOrder, err
|
return createdOrder, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder) (createdOrders types.OrderSlice, err error) {
|
func (e *Exchange) SubmitOrder(ctx context.Context, order types.SubmitOrder) (createdOrder *types.Order, err error) {
|
||||||
for _, order := range orders {
|
|
||||||
if err := orderLimiter.Wait(ctx); err != nil {
|
if err := orderLimiter.Wait(ctx); err != nil {
|
||||||
log.WithError(err).Errorf("order rate limiter wait error")
|
log.WithError(err).Errorf("order rate limiter wait error")
|
||||||
}
|
}
|
||||||
|
|
||||||
var createdOrder *types.Order
|
|
||||||
if e.IsMargin {
|
if e.IsMargin {
|
||||||
createdOrder, err = e.submitMarginOrder(ctx, order)
|
createdOrder, err = e.submitMarginOrder(ctx, order)
|
||||||
} else if e.IsFutures {
|
} else if e.IsFutures {
|
||||||
|
@ -1266,18 +1264,7 @@ func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder
|
||||||
createdOrder, err = e.submitSpotOrder(ctx, order)
|
createdOrder, err = e.submitSpotOrder(ctx, order)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err != nil {
|
return createdOrder, err
|
||||||
return createdOrders, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if createdOrder == nil {
|
|
||||||
return createdOrders, errors.New("nil converted order")
|
|
||||||
}
|
|
||||||
|
|
||||||
createdOrders = append(createdOrders, *createdOrder)
|
|
||||||
}
|
|
||||||
|
|
||||||
return createdOrders, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryKLines queries the Kline/candlestick bars for a symbol. Klines are uniquely identified by their open time.
|
// QueryKLines queries the Kline/candlestick bars for a symbol. Klines are uniquely identified by their open time.
|
||||||
|
|
|
@ -290,7 +290,7 @@ func (e *Exchange) _queryKLines(ctx context.Context, symbol string, interval typ
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
resp, err := e.newRest().HistoricalPrices(ctx, toLocalSymbol(symbol), interval, int64(options.Limit), options.StartTime, options.EndTime)
|
resp, err := e.newRest().marketRequest.HistoricalPrices(ctx, toLocalSymbol(symbol), interval, int64(options.Limit), options.StartTime, options.EndTime)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
@ -401,11 +401,10 @@ func (e *Exchange) QueryDepositHistory(ctx context.Context, asset string, since,
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder) (types.OrderSlice, error) {
|
func (e *Exchange) SubmitOrder(ctx context.Context, order types.SubmitOrder) (*types.Order, error) {
|
||||||
var createdOrders types.OrderSlice
|
|
||||||
// TODO: currently only support limit and market order
|
// TODO: currently only support limit and market order
|
||||||
// TODO: support time in force
|
// TODO: support time in force
|
||||||
for _, so := range orders {
|
so := order
|
||||||
if err := requestLimit.Wait(ctx); err != nil {
|
if err := requestLimit.Wait(ctx); err != nil {
|
||||||
logrus.WithError(err).Error("rate limit error")
|
logrus.WithError(err).Error("rate limit error")
|
||||||
}
|
}
|
||||||
|
@ -445,17 +444,11 @@ func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder
|
||||||
|
|
||||||
or, err := req.Do(ctx)
|
or, err := req.Do(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return createdOrders, fmt.Errorf("failed to place order %+v: %w", so, err)
|
return nil, fmt.Errorf("failed to place order %+v: %w", so, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
globalOrder, err := toGlobalOrderNew(*or)
|
globalOrder, err := toGlobalOrderNew(*or)
|
||||||
if err != nil {
|
return &globalOrder, err
|
||||||
return createdOrders, fmt.Errorf("failed to convert response to global order")
|
|
||||||
}
|
|
||||||
|
|
||||||
createdOrders = append(createdOrders, globalOrder)
|
|
||||||
}
|
|
||||||
return createdOrders, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) QueryOrder(ctx context.Context, q types.OrderQuery) (*types.Order, error) {
|
func (e *Exchange) QueryOrder(ctx context.Context, q types.OrderQuery) (*types.Order, error) {
|
||||||
|
@ -470,8 +463,12 @@ func (e *Exchange) QueryOrder(ctx context.Context, q types.OrderQuery) (*types.O
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
order, err := toGlobalOrderNew(*ftxOrder)
|
o, err := toGlobalOrderNew(*ftxOrder)
|
||||||
return &order, err
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &o, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) QueryOpenOrders(ctx context.Context, symbol string) (orders []types.Order, err error) {
|
func (e *Exchange) QueryOpenOrders(ctx context.Context, symbol string) (orders []types.Order, err error) {
|
||||||
|
@ -572,7 +569,6 @@ func (e *Exchange) QueryTicker(ctx context.Context, symbol string) (*types.Ticke
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) QueryTickers(ctx context.Context, symbol ...string) (map[string]types.Ticker, error) {
|
func (e *Exchange) QueryTickers(ctx context.Context, symbol ...string) (map[string]types.Ticker, error) {
|
||||||
|
|
||||||
var tickers = make(map[string]types.Ticker)
|
var tickers = make(map[string]types.Ticker)
|
||||||
|
|
||||||
markets, err := e._queryMarkets(ctx)
|
markets, err := e._queryMarkets(ctx)
|
||||||
|
@ -586,7 +582,6 @@ func (e *Exchange) QueryTickers(ctx context.Context, symbol ...string) (map[stri
|
||||||
}
|
}
|
||||||
|
|
||||||
rest := e.newRest()
|
rest := e.newRest()
|
||||||
|
|
||||||
for k, v := range markets {
|
for k, v := range markets {
|
||||||
|
|
||||||
// if we provide symbol as condition then we only query the gieven symbol ,
|
// if we provide symbol as condition then we only query the gieven symbol ,
|
||||||
|
@ -603,7 +598,7 @@ func (e *Exchange) QueryTickers(ctx context.Context, symbol ...string) (map[stri
|
||||||
now := time.Now()
|
now := time.Now()
|
||||||
since := now.Add(time.Duration(-1) * time.Hour)
|
since := now.Add(time.Duration(-1) * time.Hour)
|
||||||
until := now
|
until := now
|
||||||
prices, err := rest.HistoricalPrices(ctx, v.Market.LocalSymbol, types.Interval1h, 1, &since, &until)
|
prices, err := rest.marketRequest.HistoricalPrices(ctx, v.Market.LocalSymbol, types.Interval1h, 1, &since, &until)
|
||||||
if err != nil || !prices.Success || len(prices.Result) == 0 {
|
if err != nil || !prices.Success || len(prices.Result) == 0 {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
|
@ -34,7 +34,7 @@ func TestExchange_IOCOrder(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
ex := NewExchange(key, secret, "")
|
ex := NewExchange(key, secret, "")
|
||||||
createdOrder, err := ex.SubmitOrders(context.Background(), types.SubmitOrder{
|
createdOrder, err := ex.SubmitOrder(context.Background(), types.SubmitOrder{
|
||||||
Symbol: "LTCUSDT",
|
Symbol: "LTCUSDT",
|
||||||
Side: types.SideTypeBuy,
|
Side: types.SideTypeBuy,
|
||||||
Type: types.OrderTypeLimitMaker,
|
Type: types.OrderTypeLimitMaker,
|
||||||
|
|
|
@ -207,8 +207,7 @@ func (e *Exchange) QueryKLines(ctx context.Context, symbol string, interval type
|
||||||
return klines, nil
|
return klines, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder) (createdOrders types.OrderSlice, err error) {
|
func (e *Exchange) SubmitOrder(ctx context.Context, order types.SubmitOrder) (createdOrder *types.Order, err error) {
|
||||||
for _, order := range orders {
|
|
||||||
req := e.client.TradeService.NewPlaceOrderRequest()
|
req := e.client.TradeService.NewPlaceOrderRequest()
|
||||||
req.Symbol(toLocalSymbol(order.Symbol))
|
req.Symbol(toLocalSymbol(order.Symbol))
|
||||||
req.Side(toLocalSide(order.Side))
|
req.Side(toLocalSide(order.Side))
|
||||||
|
@ -262,10 +261,10 @@ func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder
|
||||||
|
|
||||||
orderResponse, err := req.Do(ctx)
|
orderResponse, err := req.Do(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return createdOrders, err
|
return createdOrder, err
|
||||||
}
|
}
|
||||||
|
|
||||||
createdOrders = append(createdOrders, types.Order{
|
return &types.Order{
|
||||||
SubmitOrder: order,
|
SubmitOrder: order,
|
||||||
Exchange: types.ExchangeKucoin,
|
Exchange: types.ExchangeKucoin,
|
||||||
OrderID: hashStringID(orderResponse.OrderID),
|
OrderID: hashStringID(orderResponse.OrderID),
|
||||||
|
@ -275,10 +274,7 @@ func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder
|
||||||
IsWorking: true,
|
IsWorking: true,
|
||||||
CreationTime: types.Time(time.Now()),
|
CreationTime: types.Time(time.Now()),
|
||||||
UpdateTime: types.Time(time.Now()),
|
UpdateTime: types.Time(time.Now()),
|
||||||
})
|
}, nil
|
||||||
}
|
|
||||||
|
|
||||||
return createdOrders, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// QueryOpenOrders
|
// QueryOpenOrders
|
||||||
|
|
|
@ -485,16 +485,16 @@ func (e *Exchange) Withdraw(ctx context.Context, asset string, amount fixedpoint
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder) (createdOrders types.OrderSlice, err error) {
|
func (e *Exchange) SubmitOrder(ctx context.Context, order types.SubmitOrder) (createdOrder *types.Order, err error) {
|
||||||
walletType := maxapi.WalletTypeSpot
|
walletType := maxapi.WalletTypeSpot
|
||||||
if e.MarginSettings.IsMargin {
|
if e.MarginSettings.IsMargin {
|
||||||
walletType = maxapi.WalletTypeMargin
|
walletType = maxapi.WalletTypeMargin
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, o := range orders {
|
o := order
|
||||||
orderType, err := toLocalOrderType(o.Type)
|
orderType, err := toLocalOrderType(o.Type)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return createdOrders, err
|
return createdOrder, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// case IOC type
|
// case IOC type
|
||||||
|
@ -543,22 +543,15 @@ func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder
|
||||||
|
|
||||||
retOrder, err := req.Do(ctx)
|
retOrder, err := req.Do(ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return createdOrders, err
|
return createdOrder, err
|
||||||
}
|
}
|
||||||
|
|
||||||
if retOrder == nil {
|
if retOrder == nil {
|
||||||
return createdOrders, errors.New("returned nil order")
|
return createdOrder, errors.New("returned nil order")
|
||||||
}
|
}
|
||||||
|
|
||||||
createdOrder, err := toGlobalOrder(*retOrder)
|
createdOrder, err = toGlobalOrder(*retOrder)
|
||||||
if err != nil {
|
return createdOrder, err
|
||||||
return createdOrders, err
|
|
||||||
}
|
|
||||||
|
|
||||||
createdOrders = append(createdOrders, *createdOrder)
|
|
||||||
}
|
|
||||||
|
|
||||||
return createdOrders, err
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// PlatformFeeCurrency
|
// PlatformFeeCurrency
|
||||||
|
|
|
@ -159,9 +159,7 @@ func (e *Exchange) QueryAccountBalances(ctx context.Context) (types.BalanceMap,
|
||||||
return balanceMap, nil
|
return balanceMap, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder) (createdOrders types.OrderSlice, err error) {
|
func (e *Exchange) SubmitOrder(ctx context.Context, order types.SubmitOrder) (*types.Order, error) {
|
||||||
var reqs []*okexapi.PlaceOrderRequest
|
|
||||||
for _, order := range orders {
|
|
||||||
orderReq := e.client.TradeService.NewPlaceOrderRequest()
|
orderReq := e.client.TradeService.NewPlaceOrderRequest()
|
||||||
|
|
||||||
orderType, err := toLocalOrderType(order.Type)
|
orderType, err := toLocalOrderType(order.Type)
|
||||||
|
@ -199,9 +197,31 @@ func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder
|
||||||
orderReq.OrderType(orderType)
|
orderReq.OrderType(orderType)
|
||||||
}
|
}
|
||||||
|
|
||||||
reqs = append(reqs, orderReq)
|
orderHead, err := orderReq.Do(ctx)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
orderID, err := strconv.ParseInt(orderHead.OrderID, 10, 64)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return &types.Order{
|
||||||
|
SubmitOrder: order,
|
||||||
|
Exchange: types.ExchangeOKEx,
|
||||||
|
OrderID: uint64(orderID),
|
||||||
|
Status: types.OrderStatusNew,
|
||||||
|
ExecutedQuantity: fixedpoint.Zero,
|
||||||
|
IsWorking: true,
|
||||||
|
CreationTime: types.Time(time.Now()),
|
||||||
|
UpdateTime: types.Time(time.Now()),
|
||||||
|
IsMargin: false,
|
||||||
|
IsIsolated: false,
|
||||||
|
}, nil
|
||||||
|
|
||||||
|
// TODO: move this to batch place orders interface
|
||||||
|
/*
|
||||||
batchReq := e.client.TradeService.NewBatchPlaceOrderRequest()
|
batchReq := e.client.TradeService.NewBatchPlaceOrderRequest()
|
||||||
batchReq.Add(reqs...)
|
batchReq.Add(reqs...)
|
||||||
orderHeads, err := batchReq.Do(ctx)
|
orderHeads, err := batchReq.Do(ctx)
|
||||||
|
@ -212,11 +232,11 @@ func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder
|
||||||
for idx, orderHead := range orderHeads {
|
for idx, orderHead := range orderHeads {
|
||||||
orderID, err := strconv.ParseInt(orderHead.OrderID, 10, 64)
|
orderID, err := strconv.ParseInt(orderHead.OrderID, 10, 64)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return createdOrders, err
|
return createdOrder, err
|
||||||
}
|
}
|
||||||
|
|
||||||
submitOrder := orders[idx]
|
submitOrder := order[idx]
|
||||||
createdOrders = append(createdOrders, types.Order{
|
createdOrder = append(createdOrder, types.Order{
|
||||||
SubmitOrder: submitOrder,
|
SubmitOrder: submitOrder,
|
||||||
Exchange: types.ExchangeOKEx,
|
Exchange: types.ExchangeOKEx,
|
||||||
OrderID: uint64(orderID),
|
OrderID: uint64(orderID),
|
||||||
|
@ -229,8 +249,7 @@ func (e *Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder
|
||||||
IsIsolated: false,
|
IsIsolated: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
return createdOrders, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) QueryOpenOrders(ctx context.Context, symbol string) (orders []types.Order, err error) {
|
func (e *Exchange) QueryOpenOrders(ctx context.Context, symbol string) (orders []types.Order, err error) {
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
log "github.com/sirupsen/logrus"
|
log "github.com/sirupsen/logrus"
|
||||||
|
"go.uber.org/multierr"
|
||||||
"google.golang.org/grpc"
|
"google.golang.org/grpc"
|
||||||
"google.golang.org/grpc/reflection"
|
"google.golang.org/grpc/reflection"
|
||||||
|
|
||||||
|
@ -46,20 +47,27 @@ func (s *TradingService) SubmitOrder(ctx context.Context, request *pb.SubmitOrde
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
createdOrders, err := session.Exchange.SubmitOrders(ctx, submitOrders...)
|
createdOrders, errIdx, err := bbgo.BatchPlaceOrder(ctx, session.Exchange, submitOrders...)
|
||||||
if err != nil {
|
if len(errIdx) > 0 {
|
||||||
return nil, err
|
createdOrders2, err2 := bbgo.BatchRetryPlaceOrder(ctx, session.Exchange, errIdx, submitOrders...)
|
||||||
|
if err2 != nil {
|
||||||
|
err = multierr.Append(err, err2)
|
||||||
|
} else {
|
||||||
|
createdOrders = append(createdOrders, createdOrders2...)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// convert response
|
||||||
resp := &pb.SubmitOrderResponse{
|
resp := &pb.SubmitOrderResponse{
|
||||||
Session: sessionName,
|
Session: sessionName,
|
||||||
Orders: nil,
|
Orders: nil,
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, createdOrder := range createdOrders {
|
for _, createdOrder := range createdOrders {
|
||||||
resp.Orders = append(resp.Orders, transOrder(session, createdOrder))
|
resp.Orders = append(resp.Orders, transOrder(session, createdOrder))
|
||||||
}
|
}
|
||||||
|
|
||||||
return resp, nil
|
return resp, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *TradingService) CancelOrder(ctx context.Context, request *pb.CancelOrderRequest) (*pb.CancelOrderResponse, error) {
|
func (s *TradingService) CancelOrder(ctx context.Context, request *pb.CancelOrderRequest) (*pb.CancelOrderResponse, error) {
|
||||||
|
|
|
@ -132,13 +132,14 @@ func (s *Strategy) ClosePosition(ctx context.Context, percentage fixedpoint.Valu
|
||||||
|
|
||||||
// s.Notify("Submitting %s %s order to close position by %v", s.Symbol, side.String(), percentage, submitOrder)
|
// s.Notify("Submitting %s %s order to close position by %v", s.Symbol, side.String(), percentage, submitOrder)
|
||||||
|
|
||||||
createdOrders, err := s.session.Exchange.SubmitOrders(ctx, submitOrder)
|
createdOrder, err := s.session.Exchange.SubmitOrder(ctx, submitOrder)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Errorf("can not place position close order")
|
log.WithError(err).Errorf("can not place position close order")
|
||||||
|
} else if createdOrder != nil {
|
||||||
|
s.orderStore.Add(*createdOrder)
|
||||||
|
s.activeMakerOrders.Add(*createdOrder)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.orderStore.Add(createdOrders...)
|
|
||||||
s.activeMakerOrders.Add(createdOrders...)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
func (s *Strategy) InstanceID() string {
|
func (s *Strategy) InstanceID() string {
|
||||||
|
@ -464,7 +465,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
// Price: kline.Close.Mul(fixedpoint.One.Add(s.Spread)),
|
// Price: kline.Close.Mul(fixedpoint.One.Add(s.Spread)),
|
||||||
// Quantity: fixedpoint.NewFromFloat(math.Max(math.Min(eq, 0.003), 0.0005)), //0.0005
|
// Quantity: fixedpoint.NewFromFloat(math.Max(math.Min(eq, 0.003), 0.0005)), //0.0005
|
||||||
// }
|
// }
|
||||||
// createdOrders, err = orderExecutor.SubmitOrders(ctx, submitOrder)
|
// createdOrders, err = orderExecutor.SubmitOrder(ctx, submitOrder)
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// log.WithError(err).Errorf("can not place orders")
|
// log.WithError(err).Errorf("can not place orders")
|
||||||
// }
|
// }
|
||||||
|
@ -495,7 +496,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
// Price: kline.Close.Mul(fixedpoint.One.Sub(s.Spread)),
|
// Price: kline.Close.Mul(fixedpoint.One.Sub(s.Spread)),
|
||||||
// Quantity: fixedpoint.NewFromFloat(math.Max(math.Min(eq, 0.003), 0.0005)), //0.0005
|
// Quantity: fixedpoint.NewFromFloat(math.Max(math.Min(eq, 0.003), 0.0005)), //0.0005
|
||||||
// }
|
// }
|
||||||
// createdOrders, err = orderExecutor.SubmitOrders(ctx, submitOrder)
|
// createdOrders, err = orderExecutor.SubmitOrder(ctx, submitOrder)
|
||||||
// if err != nil {
|
// if err != nil {
|
||||||
// log.WithError(err).Errorf("can not place orders")
|
// log.WithError(err).Errorf("can not place orders")
|
||||||
// }
|
// }
|
||||||
|
|
|
@ -350,7 +350,7 @@ func (s *Strategy) CrossRun(ctx context.Context, _ bbgo.OrderExecutionRouter, se
|
||||||
s.tradingMarket.MinNotional.Mul(NotionModifier).Div(price))
|
s.tradingMarket.MinNotional.Mul(NotionModifier).Div(price))
|
||||||
}
|
}
|
||||||
|
|
||||||
createdOrders, err := tradingSession.Exchange.SubmitOrders(ctx, types.SubmitOrder{
|
createdOrders, _, err := bbgo.BatchPlaceOrder(ctx, tradingSession.Exchange, types.SubmitOrder{
|
||||||
Symbol: s.Symbol,
|
Symbol: s.Symbol,
|
||||||
Side: types.SideTypeBuy,
|
Side: types.SideTypeBuy,
|
||||||
Type: types.OrderTypeLimit,
|
Type: types.OrderTypeLimit,
|
||||||
|
@ -369,6 +369,7 @@ func (s *Strategy) CrossRun(ctx context.Context, _ bbgo.OrderExecutionRouter, se
|
||||||
// TimeInForce: types.TimeInForceGTC,
|
// TimeInForce: types.TimeInForceGTC,
|
||||||
GroupID: s.groupID,
|
GroupID: s.groupID,
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.WithError(err).Error("order submit error")
|
log.WithError(err).Error("order submit error")
|
||||||
}
|
}
|
||||||
|
|
|
@ -96,7 +96,7 @@ type ExchangeTradeService interface {
|
||||||
|
|
||||||
QueryAccountBalances(ctx context.Context) (BalanceMap, error)
|
QueryAccountBalances(ctx context.Context) (BalanceMap, error)
|
||||||
|
|
||||||
SubmitOrders(ctx context.Context, orders ...SubmitOrder) (createdOrders OrderSlice, err error)
|
SubmitOrder(ctx context.Context, order SubmitOrder) (createdOrder *Order, err error)
|
||||||
|
|
||||||
QueryOpenOrders(ctx context.Context, symbol string) (orders []Order, err error)
|
QueryOpenOrders(ctx context.Context, symbol string) (orders []Order, err error)
|
||||||
|
|
||||||
|
|
|
@ -206,22 +206,17 @@ func (mr *MockExchangeMockRecorder) QueryTickers(arg0 interface{}, arg1 ...inter
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryTickers", reflect.TypeOf((*MockExchange)(nil).QueryTickers), varargs...)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "QueryTickers", reflect.TypeOf((*MockExchange)(nil).QueryTickers), varargs...)
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubmitOrders mocks base method.
|
// SubmitOrder mocks base method.
|
||||||
func (m *MockExchange) SubmitOrders(arg0 context.Context, arg1 ...types.SubmitOrder) (types.OrderSlice, error) {
|
func (m *MockExchange) SubmitOrder(arg0 context.Context, arg1 types.SubmitOrder) (*types.Order, error) {
|
||||||
m.ctrl.T.Helper()
|
m.ctrl.T.Helper()
|
||||||
varargs := []interface{}{arg0}
|
ret := m.ctrl.Call(m, "SubmitOrder", arg0, arg1)
|
||||||
for _, a := range arg1 {
|
ret0, _ := ret[0].(*types.Order)
|
||||||
varargs = append(varargs, a)
|
|
||||||
}
|
|
||||||
ret := m.ctrl.Call(m, "SubmitOrders", varargs...)
|
|
||||||
ret0, _ := ret[0].(types.OrderSlice)
|
|
||||||
ret1, _ := ret[1].(error)
|
ret1, _ := ret[1].(error)
|
||||||
return ret0, ret1
|
return ret0, ret1
|
||||||
}
|
}
|
||||||
|
|
||||||
// SubmitOrders indicates an expected call of SubmitOrders.
|
// SubmitOrder indicates an expected call of SubmitOrder.
|
||||||
func (mr *MockExchangeMockRecorder) SubmitOrders(arg0 interface{}, arg1 ...interface{}) *gomock.Call {
|
func (mr *MockExchangeMockRecorder) SubmitOrder(arg0, arg1 interface{}) *gomock.Call {
|
||||||
mr.mock.ctrl.T.Helper()
|
mr.mock.ctrl.T.Helper()
|
||||||
varargs := append([]interface{}{arg0}, arg1...)
|
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitOrder", reflect.TypeOf((*MockExchange)(nil).SubmitOrder), arg0, arg1)
|
||||||
return mr.mock.ctrl.RecordCallWithMethodType(mr.mock, "SubmitOrders", reflect.TypeOf((*MockExchange)(nil).SubmitOrders), varargs...)
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user