bbgo: add partial close option to stop loss and take profit

This commit is contained in:
c9s 2022-09-14 13:09:58 +08:00
parent 54782e763b
commit 1ea52e03c6
No known key found for this signature in database
GPG Key ID: 7385E7E464CB0A54
2 changed files with 54 additions and 9 deletions

View File

@ -3,14 +3,23 @@ package bbgo
import ( import (
"context" "context"
log "github.com/sirupsen/logrus"
"github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types" "github.com/c9s/bbgo/pkg/types"
) )
type RoiStopLoss struct { type RoiStopLoss struct {
Symbol string Symbol string
// Percentage is the ROI loss percentage
// 1% means when you loss 1% and it will close the position
Percentage fixedpoint.Value `json:"percentage"` Percentage fixedpoint.Value `json:"percentage"`
// Partial is a percentage of the position to be closed
// 50% means you will close halt the position
Partial fixedpoint.Value `json:"partial,omitempty"`
session *ExchangeSession session *ExchangeSession
orderExecutor *GeneralOrderExecutor orderExecutor *GeneralOrderExecutor
} }
@ -47,10 +56,25 @@ func (s *RoiStopLoss) checkStopPrice(closePrice fixedpoint.Value, position *type
roi := position.ROI(closePrice) roi := position.ROI(closePrice)
// logrus.Debugf("ROIStopLoss: price=%f roi=%s stop=%s", closePrice.Float64(), roi.Percentage(), s.Percentage.Neg().Percentage()) // logrus.Debugf("ROIStopLoss: price=%f roi=%s stop=%s", closePrice.Float64(), roi.Percentage(), s.Percentage.Neg().Percentage())
if roi.Compare(s.Percentage.Neg()) < 0 {
// stop loss if roi.Compare(s.Percentage.Neg()) > 0 {
Notify("[RoiStopLoss] %s stop loss triggered by ROI %s/%s, price: %f", position.Symbol, roi.Percentage(), s.Percentage.Neg().Percentage(), closePrice.Float64())
_ = s.orderExecutor.ClosePosition(context.Background(), fixedpoint.One, "roiStopLoss")
return return
} }
// default to close the whole position
percent := one
if !s.Partial.IsZero() {
percent = s.Partial
}
Notify("[RoiStopLoss] %s stop loss triggered by ROI %s/%s, price: %f, closing: %s",
position.Symbol,
roi.Percentage(),
s.Percentage.Neg().Percentage(),
closePrice.Float64(),
percent.Percentage())
if err := s.orderExecutor.ClosePosition(context.Background(), percent, "roiStopLoss"); err != nil {
log.WithError(err).Error("failed to close position")
}
} }

View File

@ -3,6 +3,8 @@ package bbgo
import ( import (
"context" "context"
log "github.com/sirupsen/logrus"
"github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types" "github.com/c9s/bbgo/pkg/types"
) )
@ -12,6 +14,10 @@ type RoiTakeProfit struct {
Symbol string `json:"symbol"` Symbol string `json:"symbol"`
Percentage fixedpoint.Value `json:"percentage"` Percentage fixedpoint.Value `json:"percentage"`
// Partial is a percentage of the position to be closed
// 50% means you will close halt the position
Partial fixedpoint.Value `json:"partial,omitempty"`
session *ExchangeSession session *ExchangeSession
orderExecutor *GeneralOrderExecutor orderExecutor *GeneralOrderExecutor
} }
@ -33,11 +39,26 @@ func (s *RoiTakeProfit) Bind(session *ExchangeSession, orderExecutor *GeneralOrd
} }
roi := position.ROI(closePrice) roi := position.ROI(closePrice)
if roi.Compare(s.Percentage) >= 0 { if roi.Compare(s.Percentage) < 0 {
// stop loss
Notify("[RoiTakeProfit] %s take profit is triggered by ROI %s/%s, price: %f", position.Symbol, roi.Percentage(), s.Percentage.Percentage(), kline.Close.Float64())
_ = orderExecutor.ClosePosition(context.Background(), fixedpoint.One, "roiTakeProfit")
return return
} }
// default to close the whole position
percent := one
if !s.Partial.IsZero() {
percent = s.Partial
}
// stop loss
Notify("[RoiTakeProfit] %s take profit is triggered by ROI %s/%s, price: %f, closing: %s",
position.Symbol,
roi.Percentage(),
s.Percentage.Percentage(),
kline.Close.Float64(),
percent.Percentage())
if err := orderExecutor.ClosePosition(context.Background(), percent, "roiTakeProfit"); err != nil {
log.WithError(err).Error("failed to close position")
}
})) }))
} }