add drift exit condition

This commit is contained in:
zenix 2022-07-05 20:43:05 +09:00
parent 6a9e00ebd4
commit 69b45e90e9
2 changed files with 39 additions and 6 deletions

View File

@ -13,6 +13,28 @@ exchangeStrategies:
symbol: ETHUSDT symbol: ETHUSDT
# kline interval for indicators # kline interval for indicators
interval: 15m interval: 15m
window: 3
exits:
- roiStopLoss:
percentage: 0.8%
- roiTakeProfit:
percentage: 35%
- protectiveStopLoss:
activationRatio: 0.6%
stopLossRatio: 0.1%
placeStopOrder: false
- protectiveStopLoss:
activationRatio: 5%
stopLossRatio: 1%
placeStopOrder: false
- cumulatedVolumeTakeProfit:
interval: 5m
window: 2
minQuoteVolume: 200_000_000
#- protectiveStopLoss:
# activationRatio: 2%
# stopLossRatio: 1%
# placeStopOrder: false
sync: sync:
userDataStream: userDataStream:
@ -32,7 +54,7 @@ backtest:
accounts: accounts:
binance: binance:
#makerFeeRate: 0 #makerFeeRate: 0
#takerFeeRate: 15 #takerFeeRate: 0
balances: balances:
ETH: 10.0 ETH: 0.0
USDT: 5000.0 USDT: 5000.0

View File

@ -40,6 +40,7 @@ type Strategy struct {
midPrice fixedpoint.Value midPrice fixedpoint.Value
lock sync.RWMutex lock sync.RWMutex
ExitMethods bbgo.ExitMethodSet `json:"exits"`
Session *bbgo.ExchangeSession Session *bbgo.ExchangeSession
*bbgo.GeneralOrderExecutor *bbgo.GeneralOrderExecutor
*bbgo.ActiveOrderBook *bbgo.ActiveOrderBook
@ -64,6 +65,7 @@ func (s *Strategy) Subscribe(session *bbgo.ExchangeSession) {
if !bbgo.IsBackTesting { if !bbgo.IsBackTesting {
session.Subscribe(types.MarketTradeChannel, s.Symbol, types.SubscribeOptions{}) session.Subscribe(types.MarketTradeChannel, s.Symbol, types.SubscribeOptions{})
} }
s.ExitMethods.SetAndSubscribe(session, s)
} }
var Three fixedpoint.Value = fixedpoint.NewFromInt(3) var Three fixedpoint.Value = fixedpoint.NewFromInt(3)
@ -155,12 +157,15 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
bbgo.Sync(s) bbgo.Sync(s)
}) })
s.GeneralOrderExecutor.Bind() s.GeneralOrderExecutor.Bind()
for _, method := range s.ExitMethods {
method.Bind(session, s.GeneralOrderExecutor)
}
s.ActiveOrderBook = bbgo.NewActiveOrderBook(s.Symbol) s.ActiveOrderBook = bbgo.NewActiveOrderBook(s.Symbol)
s.ActiveOrderBook.BindStream(session.UserDataStream) s.ActiveOrderBook.BindStream(session.UserDataStream)
store, _ := session.MarketDataStore(s.Symbol) store, _ := session.MarketDataStore(s.Symbol)
s.drift = &indicator.Drift{IntervalWindow: types.IntervalWindow{Interval: s.Interval, Window: 5}} s.drift = &indicator.Drift{IntervalWindow: types.IntervalWindow{Interval: s.Interval, Window: s.Window}}
s.atr = &indicator.ATR{IntervalWindow: types.IntervalWindow{Interval: s.Interval, Window: 34}} s.atr = &indicator.ATR{IntervalWindow: types.IntervalWindow{Interval: s.Interval, Window: 34}}
s.atr.Bind(store) s.atr.Bind(store)
@ -203,7 +208,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
hlc3 := kline.High.Add(kline.Low).Add(kline.Close).Div(Three) hlc3 := kline.High.Add(kline.Low).Add(kline.Close).Div(Three)
s.drift.Update(hlc3.Float64()) s.drift.Update(hlc3.Float64())
price := s.GetLastPrice() price := s.GetLastPrice()
if s.drift.Last() < 0 && s.drift.Index(1) >= 0 { if s.drift.Last() < 0 && s.drift.Index(1) > 0 {
if s.ActiveOrderBook.NumOfOrders() > 0 { if s.ActiveOrderBook.NumOfOrders() > 0 {
if err := s.GeneralOrderExecutor.GracefulCancelActiveOrderBook(ctx, s.ActiveOrderBook); err != nil { if err := s.GeneralOrderExecutor.GracefulCancelActiveOrderBook(ctx, s.ActiveOrderBook); err != nil {
log.WithError(err).Errorf("cannot cancel orders") log.WithError(err).Errorf("cannot cancel orders")
@ -222,6 +227,9 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
if s.Market.IsDustQuantity(baseBalance.Available, hlc3) { if s.Market.IsDustQuantity(baseBalance.Available, hlc3) {
return return
} }
if !s.Position.IsClosed() && !s.Position.IsDust(hlc3) {
return
}
_, err := s.GeneralOrderExecutor.SubmitOrders(ctx, types.SubmitOrder{ _, err := s.GeneralOrderExecutor.SubmitOrders(ctx, types.SubmitOrder{
Symbol: s.Symbol, Symbol: s.Symbol,
Side: types.SideTypeSell, Side: types.SideTypeSell,
@ -235,7 +243,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
return return
} }
} }
if s.drift.Last() > 0 && s.drift.Index(1) <= 0 { if s.drift.Last() > 0 && s.drift.Index(1) < 0 {
if s.ActiveOrderBook.NumOfOrders() > 0 { if s.ActiveOrderBook.NumOfOrders() > 0 {
if err := s.GeneralOrderExecutor.GracefulCancelActiveOrderBook(ctx, s.ActiveOrderBook); err != nil { if err := s.GeneralOrderExecutor.GracefulCancelActiveOrderBook(ctx, s.ActiveOrderBook); err != nil {
log.WithError(err).Errorf("cannot cancel orders") log.WithError(err).Errorf("cannot cancel orders")
@ -254,6 +262,9 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
quoteBalance.Available.Div(hlc3), hlc3) { quoteBalance.Available.Div(hlc3), hlc3) {
return return
} }
if !s.Position.IsClosed() && !s.Position.IsDust(hlc3) {
return
}
_, err := s.GeneralOrderExecutor.SubmitOrders(ctx, types.SubmitOrder{ _, err := s.GeneralOrderExecutor.SubmitOrders(ctx, types.SubmitOrder{
Symbol: s.Symbol, Symbol: s.Symbol,
Side: types.SideTypeBuy, Side: types.SideTypeBuy,