fix: doing some performance tuning

This commit is contained in:
zenix 2022-04-11 19:55:34 +09:00
parent 66a401f93f
commit fcf29f7e11
2 changed files with 69 additions and 68 deletions

View File

@ -9,17 +9,18 @@ exchangeStrategies:
- on: binance - on: binance
ewo_dgtrd: ewo_dgtrd:
symbol: MATICUSDT symbol: MATICUSDT
interval: 1h interval: 15m
threshold: 13 threshold: 0.9
useEma: true useEma: true
sigWin: 5 sigWin: 5
stoploss: 2% stoploss: 2%
backtest: backtest:
startTime: "2022-03-01" startTime: "2022-04-09"
endTime: "2022-04-10" endTime: "2022-04-13"
symbols: symbols:
- MATICUSDT - MATICUSDT
sessions: [binance]
account: account:
binance: binance:
balances: balances:

View File

@ -14,6 +14,7 @@ import (
const ID = "ewo_dgtrd" const ID = "ewo_dgtrd"
var log = logrus.WithField("strategy", ID) var log = logrus.WithField("strategy", ID)
var modifier = fixedpoint.NewFromFloat(0.99)
func init() { func init() {
bbgo.RegisterStrategy(ID, &Strategy{}) bbgo.RegisterStrategy(ID, &Strategy{})
@ -49,21 +50,25 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
log.Errorf("cannot get indicatorSet of %s", s.Symbol) log.Errorf("cannot get indicatorSet of %s", s.Symbol)
return nil return nil
} }
//store, ok := session.MarketDataStore(s.Symbol) orders, ok := session.OrderStore(s.Symbol)
//if !ok { if !ok {
// log.Errorf("cannot get marketdatastore of %s", s.Symbol) log.Errorf("cannot get orderbook of %s", s.Symbol)
// return nil return nil
//} }
/*store, ok := session.MarketDataStore(s.Symbol)
if !ok {
log.Errorf("cannot get marketdatastore of %s", s.Symbol)
return nil
}*/
market, ok := session.Market(s.Symbol) market, ok := session.Market(s.Symbol)
if !ok { if !ok {
log.Errorf("fetch market fail %s", s.Symbol) log.Errorf("fetch market fail %s", s.Symbol)
return nil return nil
} }
//window, ok := store.KLinesOfInterval(s.Interval) /*window, ok := store.KLinesOfInterval(s.Interval)
//if !ok { if !ok {
// log.Errorf("cannot get klinewindow of %s", s.Interval) log.Errorf("cannot get klinewindow of %s", s.Interval)
//} }*/
//mid := types.Div(types.Add(window.Open(), window.Close()), 2)
var ma5, ma34, ewo types.Series var ma5, ma34, ewo types.Series
if s.UseEma { if s.UseEma {
ma5 = indicatorSet.EWMA(types.IntervalWindow{s.Interval, 5}) ma5 = indicatorSet.EWMA(types.IntervalWindow{s.Interval, 5})
@ -81,7 +86,6 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
} }
entryPrice := fixedpoint.Zero entryPrice := fixedpoint.Zero
stopPrice := fixedpoint.Zero stopPrice := fixedpoint.Zero
inTrade := false
tradeDirectionLong := true tradeDirectionLong := true
session.MarketDataStream.OnKLineClosed(func(kline types.KLine) { session.MarketDataStream.OnKLineClosed(func(kline types.KLine) {
if kline.Symbol != s.Symbol { if kline.Symbol != s.Symbol {
@ -106,22 +110,20 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
} }
// stoploss // stoploss
if inTrade { if tradeDirectionLong && kline.Low.Compare(stopPrice) <= 0 && !stopPrice.IsZero() {
if tradeDirectionLong && kline.Low.Compare(stopPrice) <= 0 {
balances := session.Account.Balances() balances := session.Account.Balances()
baseBalance := balances[market.BaseCurrency].Available baseBalance := balances[market.BaseCurrency].Available.Mul(modifier)
baseAmount := baseBalance.Mul(lastPrice) baseAmount := baseBalance.Mul(lastPrice)
if baseBalance.Sign() <= 0 || if baseBalance.Sign() <= 0 ||
baseBalance.Compare(market.MinQuantity) < 0 || baseBalance.Compare(market.MinQuantity) < 0 ||
baseAmount.Compare(market.MinNotional) < 0 { baseAmount.Compare(market.MinNotional) < 0 {
//log.Infof("base balance %v is not enough. stop generating sell orders", baseBalance) } else {
return
}
_, err := orderExecutor.SubmitOrders(ctx, types.SubmitOrder{ _, err := orderExecutor.SubmitOrders(ctx, types.SubmitOrder{
Symbol: kline.Symbol, Symbol: kline.Symbol,
Side: types.SideTypeSell, Side: types.SideTypeSell,
Type: types.OrderTypeMarket, Type: types.OrderTypeMarket,
Quantity: baseBalance, Quantity: baseBalance,
Price: lastPrice,
Market: market, Market: market,
TimeInForce: types.TimeInForceGTC, TimeInForce: types.TimeInForceGTC,
}) })
@ -130,28 +132,26 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
return return
} }
log.Warnf("StopLoss Long at %v", lastPrice) log.Warnf("StopLoss Long at %v", lastPrice)
inTrade = false
entryPrice = fixedpoint.Zero entryPrice = fixedpoint.Zero
stopPrice = fixedpoint.Zero stopPrice = fixedpoint.Zero
return }
} else if !tradeDirectionLong && kline.High.Compare(stopPrice) >= 0 { } else if !tradeDirectionLong && kline.High.Compare(stopPrice) >= 0 && !stopPrice.IsZero() {
quoteBalance, ok := session.Account.Balance(market.QuoteCurrency) quoteBalance, ok := session.Account.Balance(market.QuoteCurrency)
if !ok { if !ok {
return return
} }
quantityAmount := quoteBalance.Available quantityAmount := quoteBalance.Available
totalQuantity := quantityAmount.Div(lastPrice) totalQuantity := quantityAmount.Div(lastPrice).Mul(modifier)
if quantityAmount.Sign() <= 0 || if quantityAmount.Sign() <= 0 ||
quantityAmount.Compare(market.MinNotional) < 0 || quantityAmount.Compare(market.MinNotional) < 0 ||
totalQuantity.Compare(market.MinQuantity) < 0 { totalQuantity.Compare(market.MinQuantity) < 0 {
//log.Infof("quote balance %v is not enough. stop generating buy orders", quoteBalance) } else {
return
}
_, err := orderExecutor.SubmitOrders(ctx, types.SubmitOrder{ _, err := orderExecutor.SubmitOrders(ctx, types.SubmitOrder{
Symbol: kline.Symbol, Symbol: kline.Symbol,
Side: types.SideTypeBuy, Side: types.SideTypeBuy,
Type: types.OrderTypeMarket, Type: types.OrderTypeMarket,
Quantity: totalQuantity, Quantity: totalQuantity,
Price: lastPrice,
Market: market, Market: market,
TimeInForce: types.TimeInForceGTC, TimeInForce: types.TimeInForceGTC,
}) })
@ -160,36 +160,37 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
return return
} }
log.Warnf("StopLoss Short at %v", lastPrice) log.Warnf("StopLoss Short at %v", lastPrice)
inTrade = false
entryPrice = fixedpoint.Zero entryPrice = fixedpoint.Zero
stopPrice = fixedpoint.Zero stopPrice = fixedpoint.Zero
return
} }
} }
if kline.Interval != s.Interval { if kline.Interval != s.Interval {
return return
} }
var toCancel []types.Order
for _, order := range orders.Orders() {
if order.Status == types.OrderStatusNew || order.Status == types.OrderStatusPartiallyFilled {
toCancel = append(toCancel, order)
}
}
if err := orderExecutor.CancelOrders(ctx, toCancel...); err != nil {
log.WithError(err).Errorf("cancel order error")
}
longSignal := types.CrossOver(ewo, ewoSignal) longSignal := types.CrossOver(ewo, ewoSignal)
shortSignal := types.CrossUnder(ewo, ewoSignal) shortSignal := types.CrossUnder(ewo, ewoSignal)
IsBull := kline.Close.Compare(kline.Open) > 0 IsBull := kline.Close.Compare(kline.Open) > 0
//nextVal := types.Predict(mid, 3, 1)
//IsBull := lastPrice.Float64() < nextVal
//log.Warnf("mid %v, last %v, next %v", kline.Mid(), mid.Last(), nextVal)
//log.Warnf("long %v %v, short %v %v", longSignal.Index(1), longSignal.Last(), shortSignal.Index(1), shortSignal.Last())
//log.Infof("(%f, %f, %f) (%f, %f, %f)", ewo.Last(), ewo.Index(1), ewo.Index(2), ewoSignal.Last(), ewoSignal.Index(1), ewoSignal.Index(2))
//log.Infof("long %v %v %v", longSignal.Last(), longSignal.Index(1), ewo.Last() >= ewoSignal.Last() && ewoSignal.Index(1) >= ewo.Index(1))
//log.Infof("short %v %v", shortSignal.Last(), shortSignal.Index(1))
var orders []types.SubmitOrder var orders []types.SubmitOrder
price := lastPrice
if longSignal.Index(1) && !shortSignal.Last() && IsBull { if longSignal.Index(1) && !shortSignal.Last() && IsBull {
quoteBalance, ok := session.Account.Balance(market.QuoteCurrency) quoteBalance, ok := session.Account.Balance(market.QuoteCurrency)
if !ok { if !ok {
return return
} }
quantityAmount := quoteBalance.Available quantityAmount := quoteBalance.Available
totalQuantity := quantityAmount.Div(lastPrice) totalQuantity := quantityAmount.Div(price).Mul(modifier).Div(types.Two)
if quantityAmount.Sign() <= 0 || if quantityAmount.Sign() <= 0 ||
quantityAmount.Compare(market.MinNotional) < 0 || quantityAmount.Compare(market.MinNotional) < 0 ||
totalQuantity.Compare(market.MinQuantity) < 0 { totalQuantity.Compare(market.MinQuantity) < 0 {
@ -198,19 +199,19 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
} }
if ewo.Last() < -s.Threshold { if ewo.Last() < -s.Threshold {
// strong long // strong long
log.Infof("strong long at %v, timestamp: %s", lastPrice, kline.StartTime) log.Infof("strong long at %v, timestamp: %s", price, kline.StartTime)
orders = append(orders, types.SubmitOrder{ orders = append(orders, types.SubmitOrder{
Symbol: kline.Symbol, Symbol: kline.Symbol,
Side: types.SideTypeBuy, Side: types.SideTypeBuy,
Type: types.OrderTypeLimit, Type: types.OrderTypeMarket,
Price: lastPrice, Price: price,
Quantity: totalQuantity, Quantity: totalQuantity.Mul(types.Two),
Market: market, Market: market,
TimeInForce: types.TimeInForceGTC, TimeInForce: types.TimeInForceGTC,
}) })
} else if ewo.Last() < 0 { } else if ewo.Last() < 0 {
log.Infof("long at %v, amount: %v, timestamp: %s", lastPrice, lastPrice.Mul(totalQuantity), kline.StartTime) log.Infof("long at %v, timestamp: %s", price, kline.StartTime)
// Long // Long
// TODO: smaller quantity? // TODO: smaller quantity?
@ -218,8 +219,8 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
orders = append(orders, types.SubmitOrder{ orders = append(orders, types.SubmitOrder{
Symbol: s.Symbol, Symbol: s.Symbol,
Side: types.SideTypeBuy, Side: types.SideTypeBuy,
Type: types.OrderTypeLimit, Type: types.OrderTypeMarket,
Price: lastPrice, Price: price,
Quantity: totalQuantity, Quantity: totalQuantity,
Market: market, Market: market,
TimeInForce: types.TimeInForceGTC, TimeInForce: types.TimeInForceGTC,
@ -227,8 +228,8 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
} }
} else if shortSignal.Index(1) && !longSignal.Last() && !IsBull { } else if shortSignal.Index(1) && !longSignal.Last() && !IsBull {
balances := session.Account.Balances() balances := session.Account.Balances()
baseBalance := balances[market.BaseCurrency].Available baseBalance := balances[market.BaseCurrency].Available.Mul(modifier).Div(types.Two)
baseAmount := baseBalance.Mul(lastPrice) baseAmount := baseBalance.Mul(price)
if baseBalance.Sign() <= 0 || if baseBalance.Sign() <= 0 ||
baseBalance.Compare(market.MinQuantity) < 0 || baseBalance.Compare(market.MinQuantity) < 0 ||
baseAmount.Compare(market.MinNotional) < 0 { baseAmount.Compare(market.MinNotional) < 0 {
@ -237,27 +238,27 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
} }
if ewo.Last() > s.Threshold { if ewo.Last() > s.Threshold {
// Strong short // Strong short
log.Infof("strong short at %v, timestamp: %s", lastPrice, kline.StartTime) log.Infof("strong short at %v, timestamp: %s", price, kline.StartTime)
orders = append(orders, types.SubmitOrder{ orders = append(orders, types.SubmitOrder{
Symbol: s.Symbol, Symbol: s.Symbol,
Side: types.SideTypeSell, Side: types.SideTypeSell,
Type: types.OrderTypeLimit, Type: types.OrderTypeMarket,
Market: market, Market: market,
Quantity: baseBalance, Quantity: baseBalance.Mul(types.Two),
Price: lastPrice, Price: price,
TimeInForce: types.TimeInForceGTC, TimeInForce: types.TimeInForceGTC,
}) })
} else if ewo.Last() > 0 { } else if ewo.Last() > 0 {
// short // short
log.Infof("short at %v, timestamp: %s", lastPrice, kline.StartTime) log.Infof("short at %v, timestamp: %s", price, kline.StartTime)
// TODO: smaller quantity? // TODO: smaller quantity?
orders = append(orders, types.SubmitOrder{ orders = append(orders, types.SubmitOrder{
Symbol: s.Symbol, Symbol: s.Symbol,
Side: types.SideTypeSell, Side: types.SideTypeSell,
Type: types.OrderTypeLimit, Type: types.OrderTypeMarket,
Market: market, Market: market,
Quantity: baseBalance, Quantity: baseBalance,
Price: lastPrice, Price: price,
TimeInForce: types.TimeInForceGTC, TimeInForce: types.TimeInForceGTC,
}) })
} }
@ -269,14 +270,13 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
return return
} }
entryPrice = lastPrice entryPrice = lastPrice
inTrade = true
tradeDirectionLong = IsBull tradeDirectionLong = IsBull
if tradeDirectionLong { if tradeDirectionLong {
stopPrice = entryPrice.Mul(fixedpoint.One.Sub(s.StopLoss)) stopPrice = entryPrice.Mul(fixedpoint.One.Sub(s.StopLoss))
} else { } else {
stopPrice = entryPrice.Mul(fixedpoint.One.Add(s.StopLoss)) stopPrice = entryPrice.Mul(fixedpoint.One.Add(s.StopLoss))
} }
log.Infof("Place orders %v", createdOrders) log.Infof("Place orders %v stop @ %v", createdOrders, stopPrice)
} }
}) })
return nil return nil