2022-06-28 17:58:15 +00:00
package bbgo
2022-06-26 08:13:58 +00:00
import (
"context"
"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types"
)
type RoiStopLoss struct {
2022-10-28 09:56:07 +00:00
Symbol string
Percentage fixedpoint . Value ` json:"percentage" `
CancelActiveOrders bool ` json:"cancelActiveOrders" `
2022-06-26 08:13:58 +00:00
2022-06-28 17:58:15 +00:00
session * ExchangeSession
orderExecutor * GeneralOrderExecutor
2022-06-26 08:13:58 +00:00
}
2022-07-01 07:30:06 +00:00
func ( s * RoiStopLoss ) Subscribe ( session * ExchangeSession ) {
// use 1m kline to handle roi stop
session . Subscribe ( types . KLineChannel , s . Symbol , types . SubscribeOptions { Interval : types . Interval1m } )
}
2022-06-28 17:58:15 +00:00
func ( s * RoiStopLoss ) Bind ( session * ExchangeSession , orderExecutor * GeneralOrderExecutor ) {
2022-06-26 08:13:58 +00:00
s . session = session
s . orderExecutor = orderExecutor
position := orderExecutor . Position ( )
2023-06-21 09:58:18 +00:00
f := func ( kline types . KLine ) {
2022-06-26 11:06:16 +00:00
s . checkStopPrice ( kline . Close , position )
2023-06-21 09:58:18 +00:00
}
session . MarketDataStream . OnKLineClosed ( types . KLineWith ( s . Symbol , types . Interval1m , f ) )
session . MarketDataStream . OnKLine ( types . KLineWith ( s . Symbol , types . Interval1m , f ) )
2022-06-26 11:06:16 +00:00
2022-07-16 16:59:35 +00:00
if ! IsBackTesting && enableMarketTradeStop {
2022-06-26 11:06:16 +00:00
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 )
2022-08-26 11:06:52 +00:00
// logrus.Debugf("ROIStopLoss: price=%f roi=%s stop=%s", closePrice.Float64(), roi.Percentage(), s.Percentage.Neg().Percentage())
2022-06-26 11:06:16 +00:00
if roi . Compare ( s . Percentage . Neg ( ) ) < 0 {
// stop loss
2023-06-21 09:56:40 +00:00
Notify ( "[RoiStopLoss] %s stop loss triggered by ROI %s/%s, currentPrice = %f" , position . Symbol , roi . Percentage ( ) , s . Percentage . Neg ( ) . Percentage ( ) , closePrice . Float64 ( ) )
2022-10-28 09:56:07 +00:00
if s . CancelActiveOrders {
_ = s . orderExecutor . GracefulCancel ( context . Background ( ) )
}
2022-06-27 10:17:57 +00:00
_ = s . orderExecutor . ClosePosition ( context . Background ( ) , fixedpoint . One , "roiStopLoss" )
2022-06-26 11:06:16 +00:00
return
}
2022-06-26 08:13:58 +00:00
}