strategy/supertrend: func to get order side

This commit is contained in:
Andy Cheng 2022-07-06 18:11:09 +08:00
parent 8aa5b706b6
commit c43d4e0b24
2 changed files with 31 additions and 17 deletions

View File

@ -18,8 +18,8 @@ backtest:
# for testing max draw down (MDD) at 03-12
# see here for more details
# https://www.investopedia.com/terms/m/maximum-drawdown-mdd.asp
startTime: "2022-04-01"
endTime: "2022-04-30"
startTime: "2022-03-01"
endTime: "2022-06-30"
symbols:
- BTCUSDT
accounts:
@ -27,7 +27,7 @@ backtest:
makerCommission: 10 # 0.15%
takerCommission: 15 # 0.15%
balances:
BTC: 1.0
BTC: 10.0
USDT: 10000.0
exchangeStrategies:

View File

@ -237,6 +237,18 @@ func (s *Strategy) shouldStop(kline types.KLine, stSignal types.Direction, demaS
return stopNow
}
func (s *Strategy) getSide(stSignal types.Direction, demaSignal types.Direction, lgSignal types.Direction) types.SideType {
var side types.SideType
if stSignal == types.DirectionUp && demaSignal == types.DirectionUp && (s.LinearRegression == nil || lgSignal == types.DirectionUp) {
side = types.SideTypeBuy
} else if stSignal == types.DirectionDown && demaSignal == types.DirectionDown && (s.LinearRegression == nil || lgSignal == types.DirectionDown) {
side = types.SideTypeSell
}
return side
}
func (s *Strategy) generateOrderForm(side types.SideType, quantity fixedpoint.Value, marginOrderSideEffect types.MarginOrderSideEffectType) types.SubmitOrder {
orderForm := types.SubmitOrder{
Symbol: s.Symbol,
@ -348,14 +360,16 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
return
}
closePrice := kline.GetClose().Float64()
openPrice := kline.GetOpen().Float64()
closePrice := kline.GetClose()
openPrice := kline.GetOpen()
closePrice64 := closePrice.Float64()
openPrice64 := openPrice.Float64()
// Supertrend signal
stSignal := s.Supertrend.GetSignal()
// DEMA signal
demaSignal := s.getDemaSignal(openPrice, closePrice)
demaSignal := s.getDemaSignal(openPrice64, closePrice64)
// Linear Regression signal
var lgSignal types.Direction
@ -364,38 +378,38 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
}
// TP/SL if there's non-dust position and meets the criteria
if !s.Market.IsDustQuantity(s.Position.GetBase().Abs(), kline.GetClose()) && s.shouldStop(kline, stSignal, demaSignal, lgSignal) {
if !s.Market.IsDustQuantity(s.Position.GetBase().Abs(), closePrice) && s.shouldStop(kline, stSignal, demaSignal, lgSignal) {
if err := s.ClosePosition(ctx, fixedpoint.One); err == nil {
s.currentStopLossPrice = fixedpoint.Zero
s.currentTakeProfitPrice = fixedpoint.Zero
}
}
// Open position
var side types.SideType
if stSignal == types.DirectionUp && demaSignal == types.DirectionUp && (s.LinearRegression == nil || lgSignal == types.DirectionUp) {
side = types.SideTypeBuy
// Get order side
side := s.getSide(stSignal, demaSignal, lgSignal)
// Set TP/SL price if needed
if side == types.SideTypeBuy {
if s.StopLossByTriggeringK {
s.currentStopLossPrice = kline.GetLow()
}
if s.TakeProfitAtrMultiplier > 0 {
s.currentTakeProfitPrice = kline.GetClose().Add(fixedpoint.NewFromFloat(s.Supertrend.AverageTrueRange.Last() * s.TakeProfitAtrMultiplier))
s.currentTakeProfitPrice = closePrice.Add(fixedpoint.NewFromFloat(s.Supertrend.AverageTrueRange.Last() * s.TakeProfitAtrMultiplier))
}
} else if stSignal == types.DirectionDown && demaSignal == types.DirectionDown && (s.LinearRegression == nil || lgSignal == types.DirectionDown) {
side = types.SideTypeSell
} else if side == types.SideTypeSell {
if s.StopLossByTriggeringK {
s.currentStopLossPrice = kline.GetHigh()
}
if s.TakeProfitAtrMultiplier > 0 {
s.currentTakeProfitPrice = kline.GetClose().Sub(fixedpoint.NewFromFloat(s.Supertrend.AverageTrueRange.Last() * s.TakeProfitAtrMultiplier))
s.currentTakeProfitPrice = closePrice.Sub(fixedpoint.NewFromFloat(s.Supertrend.AverageTrueRange.Last() * s.TakeProfitAtrMultiplier))
}
}
// Open position
// The default value of side is an empty string. Unless side is set by the checks above, the result of the following condition is false
if side == types.SideTypeSell || side == types.SideTypeBuy {
bbgo.Notify("open %s position for signal %v", s.Symbol, side)
// Close opposite position if any
if !s.Position.IsDust(kline.GetClose()) {
if !s.Position.IsDust(closePrice) {
if (side == types.SideTypeSell && s.Position.IsLong()) || (side == types.SideTypeBuy && s.Position.IsShort()) {
bbgo.Notify("close existing %s position before open a new position", s.Symbol)
_ = s.ClosePosition(ctx, fixedpoint.One)
@ -405,7 +419,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
}
}
orderForm := s.generateOrderForm(side, s.calculateQuantity(kline.GetClose()), types.SideEffectTypeMarginBuy)
orderForm := s.generateOrderForm(side, s.calculateQuantity(closePrice), types.SideEffectTypeMarginBuy)
log.Infof("submit open position order %v", orderForm)
_, err := s.orderExecutor.SubmitOrders(ctx, orderForm)
if err != nil {