mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-25 16:25:16 +00:00
block and query order until the market order for closing position is filled
This commit is contained in:
parent
b5f2f57678
commit
0360d9fa8b
|
@ -3,8 +3,8 @@ package bbgo
|
||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync/atomic"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
@ -14,6 +14,7 @@ import (
|
||||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
"github.com/c9s/bbgo/pkg/util"
|
"github.com/c9s/bbgo/pkg/util"
|
||||||
|
"github.com/c9s/bbgo/pkg/util/backoff"
|
||||||
)
|
)
|
||||||
|
|
||||||
var ErrExceededSubmitOrderRetryLimit = errors.New("exceeded submit order retry limit")
|
var ErrExceededSubmitOrderRetryLimit = errors.New("exceeded submit order retry limit")
|
||||||
|
@ -42,7 +43,6 @@ type GeneralOrderExecutor struct {
|
||||||
|
|
||||||
maxRetries uint
|
maxRetries uint
|
||||||
disableNotify bool
|
disableNotify bool
|
||||||
closing int64
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewGeneralOrderExecutor(session *ExchangeSession, symbol, strategy, strategyInstanceID string, position *types.Position) *GeneralOrderExecutor {
|
func NewGeneralOrderExecutor(session *ExchangeSession, symbol, strategy, strategyInstanceID string, position *types.Position) *GeneralOrderExecutor {
|
||||||
|
@ -442,23 +442,22 @@ func (e *GeneralOrderExecutor) GracefulCancel(ctx context.Context, orders ...typ
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var ErrPositionAlreadyClosing = errors.New("position is already in closing process, can't close it again")
|
||||||
|
|
||||||
// ClosePosition closes the current position by a percentage.
|
// ClosePosition closes the current position by a percentage.
|
||||||
// percentage 0.1 means close 10% position
|
// 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.
|
// 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 {
|
||||||
|
if !e.position.SetClosing(true) {
|
||||||
|
return ErrPositionAlreadyClosing
|
||||||
|
}
|
||||||
|
defer e.position.SetClosing(false)
|
||||||
|
|
||||||
submitOrder := e.position.NewMarketCloseOrder(percentage)
|
submitOrder := e.position.NewMarketCloseOrder(percentage)
|
||||||
if submitOrder == nil {
|
if submitOrder == nil {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
if e.closing > 0 {
|
|
||||||
log.Errorf("position is already closing")
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
atomic.AddInt64(&e.closing, 1)
|
|
||||||
defer atomic.StoreInt64(&e.closing, 0)
|
|
||||||
|
|
||||||
if e.session.Futures { // Futures: Use base qty in e.position
|
if e.session.Futures { // Futures: Use base qty in e.position
|
||||||
submitOrder.Quantity = e.position.GetBase().Abs()
|
submitOrder.Quantity = e.position.GetBase().Abs()
|
||||||
submitOrder.ReduceOnly = true
|
submitOrder.ReduceOnly = true
|
||||||
|
@ -496,8 +495,34 @@ func (e *GeneralOrderExecutor) ClosePosition(ctx context.Context, percentage fix
|
||||||
|
|
||||||
Notify("Closing %s position %s with tags: %s", e.symbol, percentage.Percentage(), tagStr)
|
Notify("Closing %s position %s with tags: %s", e.symbol, percentage.Percentage(), tagStr)
|
||||||
|
|
||||||
_, err := e.SubmitOrders(ctx, *submitOrder)
|
createdOrders, err := e.SubmitOrders(ctx, *submitOrder)
|
||||||
return err
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if queryOrderService, ok := e.session.Exchange.(types.ExchangeOrderQueryService); ok {
|
||||||
|
switch submitOrder.Type {
|
||||||
|
case types.OrderTypeMarket:
|
||||||
|
_ = backoff.RetryGeneral(ctx, func() error {
|
||||||
|
order, err2 := queryOrderService.QueryOrder(ctx, types.OrderQuery{
|
||||||
|
Symbol: e.symbol,
|
||||||
|
OrderID: strconv.FormatUint(createdOrders[0].OrderID, 10),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err2 != nil {
|
||||||
|
return err2
|
||||||
|
}
|
||||||
|
|
||||||
|
if order.Status != types.OrderStatusFilled {
|
||||||
|
return errors.New("order is not filled yet")
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *GeneralOrderExecutor) TradeCollector() *TradeCollector {
|
func (e *GeneralOrderExecutor) TradeCollector() *TradeCollector {
|
||||||
|
|
|
@ -58,6 +58,9 @@ type Position struct {
|
||||||
|
|
||||||
AccumulatedProfit fixedpoint.Value `json:"accumulatedProfit,omitempty" db:"accumulated_profit"`
|
AccumulatedProfit fixedpoint.Value `json:"accumulatedProfit,omitempty" db:"accumulated_profit"`
|
||||||
|
|
||||||
|
// closing is a flag for marking this position is closing
|
||||||
|
closing bool
|
||||||
|
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
|
||||||
// Modify position callbacks
|
// Modify position callbacks
|
||||||
|
@ -428,6 +431,25 @@ func (p *Position) BindStream(stream Stream) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (p *Position) SetClosing(c bool) bool {
|
||||||
|
p.Lock()
|
||||||
|
defer p.Unlock()
|
||||||
|
|
||||||
|
if p.closing && c {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
p.closing = c
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
func (p *Position) IsClosing() (c bool) {
|
||||||
|
p.Lock()
|
||||||
|
c = p.closing
|
||||||
|
p.Unlock()
|
||||||
|
return c
|
||||||
|
}
|
||||||
|
|
||||||
func (p *Position) AddTrades(trades []Trade) (fixedpoint.Value, fixedpoint.Value, bool) {
|
func (p *Position) AddTrades(trades []Trade) (fixedpoint.Value, fixedpoint.Value, bool) {
|
||||||
var totalProfitAmount, totalNetProfit fixedpoint.Value
|
var totalProfitAmount, totalNetProfit fixedpoint.Value
|
||||||
for _, trade := range trades {
|
for _, trade := range trades {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user