From 776f89b2f2a7511a638692c1dab5574b36f2ce12 Mon Sep 17 00:00:00 2001 From: c9s Date: Mon, 12 Sep 2022 23:24:37 +0800 Subject: [PATCH] pivotshort: apply OpenPositionOptions to breakLow --- pkg/bbgo/order_executor_general.go | 24 +++++++------ pkg/strategy/pivotshort/breaklow.go | 52 ++++++++++------------------- 2 files changed, 30 insertions(+), 46 deletions(-) diff --git a/pkg/bbgo/order_executor_general.go b/pkg/bbgo/order_executor_general.go index 6b642a5b0..11cc76d48 100644 --- a/pkg/bbgo/order_executor_general.go +++ b/pkg/bbgo/order_executor_general.go @@ -129,12 +129,13 @@ func (e *GeneralOrderExecutor) SubmitOrders(ctx context.Context, submitOrders .. type OpenPositionOptions struct { // Long is for open a long position - // Long or Short must be set - Long bool `json:"long"` + // Long or Short must be set, avoid loading it from the config file + // it should be set from the strategy code + Long bool `json:"-" yaml:"-"` // Short is for open a short position // Long or Short must be set - Short bool `json:"short"` + Short bool `json:"-" yaml:"-"` // Leverage is used for leveraged position and account Leverage fixedpoint.Value `json:"leverage,omitempty"` @@ -148,15 +149,16 @@ type OpenPositionOptions struct { // LimitOrder set to true to open a position with a limit order LimitOrder bool `json:"limitOrder,omitempty"` - // LimitTakerRatio is used when LimitOrder = true, it adjusts the price of the limit order with a ratio. + // LimitOrderTakerRatio 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. - LimitTakerRatio fixedpoint.Value `json:"limitTakerRatio,omitempty"` - CurrentPrice fixedpoint.Value `json:"currentPrice,omitempty"` - Tags []string `json:"tags"` + LimitOrderTakerRatio fixedpoint.Value `json:"limitOrderTakerRatio,omitempty"` + + Price fixedpoint.Value `json:"-" yaml:"-"` + Tags []string `json:"-" yaml:"-"` } func (e *GeneralOrderExecutor) OpenPosition(ctx context.Context, options OpenPositionOptions) error { - price := options.CurrentPrice + price := options.Price submitOrder := types.SubmitOrder{ Symbol: e.position.Symbol, Type: types.OrderTypeMarket, @@ -164,13 +166,13 @@ func (e *GeneralOrderExecutor) OpenPosition(ctx context.Context, options OpenPos Tag: strings.Join(options.Tags, ","), } - if !options.LimitTakerRatio.IsZero() { + if !options.LimitOrderTakerRatio.IsZero() { if options.Long { // use higher price to buy (this ensures that our order will be filled) - price = price.Mul(one.Add(options.LimitTakerRatio)) + price = price.Mul(one.Add(options.LimitOrderTakerRatio)) } else if options.Short { // use lower price to sell (this ensures that our order will be filled) - price = price.Mul(one.Sub(options.LimitTakerRatio)) + price = price.Mul(one.Sub(options.LimitOrderTakerRatio)) } } diff --git a/pkg/strategy/pivotshort/breaklow.go b/pkg/strategy/pivotshort/breaklow.go index 048c996cb..4b9b02b43 100644 --- a/pkg/strategy/pivotshort/breaklow.go +++ b/pkg/strategy/pivotshort/breaklow.go @@ -25,13 +25,18 @@ type BreakLow struct { // MarketOrder is the option to enable market order short. MarketOrder bool `json:"marketOrder"` + // LimitOrder is the option to use limit order instead of market order to short + LimitOrder bool `json:"limitOrder"` + LimitTakerRatio fixedpoint.Value `json:"limitTakerRatio"` + Leverage fixedpoint.Value `json:"leverage"` + Quantity fixedpoint.Value `json:"quantity"` + + bbgo.OpenPositionOptions + // BounceRatio is a ratio used for placing the limit order sell price // limit sell price = breakLowPrice * (1 + BounceRatio) BounceRatio fixedpoint.Value `json:"bounceRatio"` - Leverage fixedpoint.Value `json:"leverage"` - Quantity fixedpoint.Value `json:"quantity"` - StopEMA *bbgo.StopEMA `json:"stopEMA"` TrendEMA *bbgo.TrendEMA `json:"trendEMA"` @@ -210,40 +215,17 @@ func (s *BreakLow) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.Gener // graceful cancel all active orders _ = orderExecutor.GracefulCancel(ctx) - quantity, err := bbgo.CalculateBaseQuantity(s.session, s.Market, closePrice, s.Quantity, s.Leverage) - if err != nil { - log.WithError(err).Errorf("quantity calculation error") + bbgo.Notify("%s price %f breaks the previous low %f with ratio %f, opening short position", symbol, kline.Close.Float64(), previousLow.Float64(), s.Ratio.Float64()) + opts := s.OpenPositionOptions + opts.Short = true + opts.Price = closePrice + opts.Tags = []string{"breakLowMarket"} + if opts.LimitOrder && !s.BounceRatio.IsZero() { + opts.Price = previousLow.Mul(fixedpoint.One.Add(s.BounceRatio)) } - if quantity.IsZero() { - log.Warn("quantity is zero, can not submit order, skip") - return - } - - if s.MarketOrder { - bbgo.Notify("%s price %f breaks the previous low %f with ratio %f, submitting market sell to open a short position", symbol, kline.Close.Float64(), previousLow.Float64(), s.Ratio.Float64()) - _, _ = s.orderExecutor.SubmitOrders(ctx, types.SubmitOrder{ - Symbol: s.Symbol, - Side: types.SideTypeSell, - Type: types.OrderTypeMarket, - Quantity: quantity, - MarginSideEffect: types.SideEffectTypeMarginBuy, - Tag: "breakLowMarket", - }) - - } else { - sellPrice := previousLow.Mul(fixedpoint.One.Add(s.BounceRatio)) - - bbgo.Notify("%s price %f breaks the previous low %f with ratio %f, submitting limit sell @ %f", symbol, kline.Close.Float64(), previousLow.Float64(), s.Ratio.Float64(), sellPrice.Float64()) - _, _ = s.orderExecutor.SubmitOrders(ctx, types.SubmitOrder{ - Symbol: kline.Symbol, - Side: types.SideTypeSell, - Type: types.OrderTypeLimit, - Price: sellPrice, - Quantity: quantity, - MarginSideEffect: types.SideEffectTypeMarginBuy, - Tag: "breakLowLimit", - }) + if err := s.orderExecutor.OpenPosition(ctx, opts); err != nil { + log.WithError(err).Errorf("failed to open short position") } })) }