mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-26 08:45:16 +00:00
pivotshort: pull out stop price check to a single method
This commit is contained in:
parent
ef31e90728
commit
3604bae933
|
@ -5,10 +5,8 @@ import "github.com/c9s/bbgo/pkg/bbgo"
|
|||
type ExitMethod struct {
|
||||
RoiStopLoss *RoiStopLoss `json:"roiStopLoss"`
|
||||
ProtectionStopLoss *ProtectionStopLoss `json:"protectionStopLoss"`
|
||||
|
||||
RoiTakeProfit *RoiTakeProfit `json:"roiTakeProfit"`
|
||||
LowerShadowTakeProfit *LowerShadowTakeProfit `json:"lowerShadowTakeProfit"`
|
||||
|
||||
CumulatedVolumeTakeProfit *CumulatedVolumeTakeProfit `json:"cumulatedVolumeTakeProfit"`
|
||||
}
|
||||
|
||||
|
|
|
@ -110,6 +110,20 @@ func (s *ProtectionStopLoss) Bind(session *bbgo.ExchangeSession, orderExecutor *
|
|||
s.handleChange(context.Background(), position, kline.Close, s.orderExecutor)
|
||||
}
|
||||
})
|
||||
|
||||
if !bbgo.IsBackTesting {
|
||||
session.MarketDataStream.OnMarketTrade(func(trade types.Trade) {
|
||||
if trade.Symbol != position.Symbol {
|
||||
return
|
||||
}
|
||||
|
||||
if s.stopLossPrice.IsZero() || s.PlaceStopOrder {
|
||||
return
|
||||
}
|
||||
|
||||
s.checkStopPrice(trade.Price, position)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *ProtectionStopLoss) handleChange(ctx context.Context, position *types.Position, closePrice fixedpoint.Value, orderExecutor *bbgo.GeneralOrderExecutor) {
|
||||
|
@ -136,19 +150,27 @@ func (s *ProtectionStopLoss) handleChange(ctx context.Context, position *types.P
|
|||
|
||||
log.Infof("[ProtectionStopLoss] %s protection stop loss activated, current price = %f, average cost = %f, stop loss price = %f",
|
||||
position.Symbol, closePrice.Float64(), position.AverageCost.Float64(), s.stopLossPrice.Float64())
|
||||
|
||||
if s.PlaceStopOrder {
|
||||
if err := s.placeStopOrder(ctx, position, orderExecutor); err != nil {
|
||||
log.WithError(err).Errorf("failed to place stop limit order")
|
||||
}
|
||||
return
|
||||
}
|
||||
} else {
|
||||
// not activated, skip setup stop order
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if s.PlaceStopOrder {
|
||||
if err := s.placeStopOrder(ctx, position, orderExecutor); err != nil {
|
||||
log.WithError(err).Errorf("failed to place stop limit order")
|
||||
}
|
||||
} else if s.shouldStop(closePrice) {
|
||||
// check stop price
|
||||
s.checkStopPrice(closePrice, position)
|
||||
}
|
||||
|
||||
func (s *ProtectionStopLoss) checkStopPrice(closePrice fixedpoint.Value, position *types.Position) {
|
||||
if s.shouldStop(closePrice) {
|
||||
log.Infof("[ProtectionStopLoss] protection stop order is triggered at price %f, position = %+v", closePrice.Float64(), position)
|
||||
if err := orderExecutor.ClosePosition(ctx, one); err != nil {
|
||||
if err := s.orderExecutor.ClosePosition(context.Background(), one); err != nil {
|
||||
log.WithError(err).Errorf("failed to close position")
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,17 +25,30 @@ func (s *RoiStopLoss) Bind(session *bbgo.ExchangeSession, orderExecutor *bbgo.Ge
|
|||
return
|
||||
}
|
||||
|
||||
closePrice := kline.Close
|
||||
if position.IsClosed() || position.IsDust(closePrice) {
|
||||
return
|
||||
}
|
||||
|
||||
roi := position.ROI(closePrice)
|
||||
if roi.Compare(s.Percentage.Neg()) < 0 {
|
||||
// stop loss
|
||||
bbgo.Notify("[RoiStopLoss] %s stop loss triggered by ROI %s/%s, price: %f", position.Symbol, roi.Percentage(), s.Percentage.Neg().Percentage(), kline.Close.Float64())
|
||||
_ = orderExecutor.ClosePosition(context.Background(), fixedpoint.One)
|
||||
return
|
||||
}
|
||||
s.checkStopPrice(kline.Close, position)
|
||||
})
|
||||
|
||||
if !bbgo.IsBackTesting {
|
||||
session.MarketDataStream.OnMarketTrade(func(trade types.Trade) {
|
||||
if trade.Symbol != position.Symbol {
|
||||
return
|
||||
}
|
||||
|
||||
s.checkStopPrice(trade.Price, position)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *RoiStopLoss) checkStopPrice(closePrice fixedpoint.Value, position *types.Position) {
|
||||
if position.IsClosed() || position.IsDust(closePrice) {
|
||||
return
|
||||
}
|
||||
|
||||
roi := position.ROI(closePrice)
|
||||
if roi.Compare(s.Percentage.Neg()) < 0 {
|
||||
// stop loss
|
||||
bbgo.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)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
|
|
@ -123,6 +123,10 @@ func (s *Strategy) Subscribe(session *bbgo.ExchangeSession) {
|
|||
if s.BounceShort != nil && s.BounceShort.Enabled {
|
||||
session.Subscribe(types.KLineChannel, s.Symbol, types.SubscribeOptions{Interval: s.BounceShort.Interval})
|
||||
}
|
||||
|
||||
if !bbgo.IsBackTesting {
|
||||
session.Subscribe(types.MarketTradeChannel, s.Symbol, types.SubscribeOptions{})
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Strategy) useQuantityOrBaseBalance(quantity fixedpoint.Value) fixedpoint.Value {
|
||||
|
@ -189,6 +193,8 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
|||
s.TradeStats = &types.TradeStats{}
|
||||
}
|
||||
|
||||
s.lastLow = fixedpoint.Zero
|
||||
|
||||
// StrategyController
|
||||
s.Status = types.StrategyStatusRunning
|
||||
|
||||
|
@ -230,7 +236,13 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
|||
s.stopEWMA = standardIndicator.EWMA(*s.BreakLow.StopEMA)
|
||||
}
|
||||
|
||||
s.lastLow = fixedpoint.Zero
|
||||
for _, method := range s.ExitMethods {
|
||||
method.Bind(session, s.orderExecutor)
|
||||
}
|
||||
|
||||
session.MarketDataStream.OnMarketTrade(func(trade types.Trade) {
|
||||
log.Info(trade)
|
||||
})
|
||||
|
||||
session.UserDataStream.OnStart(func() {
|
||||
lastKLine := s.preloadPivot(s.pivot, store)
|
||||
|
@ -264,10 +276,6 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
|||
}
|
||||
})
|
||||
|
||||
for _, method := range s.ExitMethods {
|
||||
method.Bind(session, s.orderExecutor)
|
||||
}
|
||||
|
||||
// Always check whether you can open a short position or not
|
||||
session.MarketDataStream.OnKLineClosed(func(kline types.KLine) {
|
||||
if s.Status != types.StrategyStatusRunning {
|
||||
|
|
Loading…
Reference in New Issue
Block a user