mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-26 00:35:15 +00:00
fix: reduce Quantity precheck, drift condition, ewo refactor
This commit is contained in:
parent
7b47a51fae
commit
5086af2886
|
@ -27,29 +27,30 @@ exchangeStrategies:
|
||||||
- on: binance
|
- on: binance
|
||||||
drift:
|
drift:
|
||||||
limitOrder: false
|
limitOrder: false
|
||||||
|
quantity: 0.001
|
||||||
canvasPath: "./output.png"
|
canvasPath: "./output.png"
|
||||||
symbol: BTCUSDT
|
symbol: BTCUSDT
|
||||||
# kline interval for indicators
|
# kline interval for indicators
|
||||||
interval: 4m
|
interval: 1m
|
||||||
window: 2
|
window: 4
|
||||||
stoploss: 0.13%
|
stoploss: 0.02%
|
||||||
source: ohlc4
|
source: hl2
|
||||||
predictOffset: 2
|
predictOffset: 2
|
||||||
noTrailingStopLoss: false
|
noTrailingStopLoss: false
|
||||||
trailingStopLossType: kline
|
trailingStopLossType: realtime
|
||||||
# stddev on high/low-source
|
# stddev on high/low-source
|
||||||
hlVarianceMultiplier: 0.22
|
hlVarianceMultiplier: 0.2
|
||||||
hlRangeWindow: 4
|
hlRangeWindow: 4
|
||||||
smootherWindow: 1
|
smootherWindow: 31
|
||||||
fisherTransformWindow: 96
|
fisherTransformWindow: 80
|
||||||
window1m: 8
|
window1m: 8
|
||||||
smootherWindow1m: 4
|
smootherWindow1m: 4
|
||||||
fisherTransformWindow1m: 320
|
fisherTransformWindow1m: 320
|
||||||
atrWindow: 14
|
atrWindow: 14
|
||||||
# orders not been traded will be canceled after `pendingMinutes` minutes
|
# orders not been traded will be canceled after `pendingMinutes` minutes
|
||||||
pendingMinutes: 10
|
pendingMinutes: 3
|
||||||
noRebalance: true
|
noRebalance: true
|
||||||
trendWindow: 576
|
trendWindow: 185
|
||||||
rebalanceFilter: 1.2
|
rebalanceFilter: 1.2
|
||||||
#driftFilterPos: 0.5
|
#driftFilterPos: 0.5
|
||||||
#driftFilterNeg: -0.5
|
#driftFilterNeg: -0.5
|
||||||
|
@ -60,12 +61,12 @@ exchangeStrategies:
|
||||||
# when farest price from entry goes over that ratio, start using the callback ratio accordingly to do trailingstop
|
# when farest price from entry goes over that ratio, start using the callback ratio accordingly to do trailingstop
|
||||||
#trailingActivationRatio: [0.01, 0.016, 0.05]
|
#trailingActivationRatio: [0.01, 0.016, 0.05]
|
||||||
#trailingActivationRatio: [0.001, 0.0081, 0.022]
|
#trailingActivationRatio: [0.001, 0.0081, 0.022]
|
||||||
trailingActivationRatio: [0.0012, 0.0016, 0.01]
|
trailingActivationRatio: [0.0007, 0.0016, 0.008, 0.01]
|
||||||
#trailingActivationRatio: []
|
#trailingActivationRatio: []
|
||||||
#trailingCallbackRate: []
|
#trailingCallbackRate: []
|
||||||
#trailingCallbackRate: [0.002, 0.01, 0.1]
|
#trailingCallbackRate: [0.002, 0.01, 0.1]
|
||||||
#trailingCallbackRate: [0.0004, 0.0009, 0.018]
|
#trailingCallbackRate: [0.0004, 0.0009, 0.018]
|
||||||
trailingCallbackRate: [0.0003, 0.0006, 0.0019]
|
trailingCallbackRate: [0.0003, 0.0005, 0.0010, 0.0016]
|
||||||
|
|
||||||
generateGraph: true
|
generateGraph: true
|
||||||
graphPNLDeductFee: false
|
graphPNLDeductFee: false
|
||||||
|
@ -128,7 +129,7 @@ sync:
|
||||||
- BTCUSDT
|
- BTCUSDT
|
||||||
|
|
||||||
backtest:
|
backtest:
|
||||||
startTime: "2022-09-01"
|
startTime: "2022-09-26"
|
||||||
endTime: "2022-09-30"
|
endTime: "2022-09-30"
|
||||||
symbols:
|
symbols:
|
||||||
- BTCUSDT
|
- BTCUSDT
|
||||||
|
@ -139,4 +140,4 @@ backtest:
|
||||||
takerFeeRate: 0.000
|
takerFeeRate: 0.000
|
||||||
balances:
|
balances:
|
||||||
BTC: 0
|
BTC: 0
|
||||||
USDT: 1000
|
USDT: 50
|
||||||
|
|
|
@ -24,12 +24,14 @@ exchangeStrategies:
|
||||||
- on: binance
|
- on: binance
|
||||||
elliottwave:
|
elliottwave:
|
||||||
symbol: BNBBUSD
|
symbol: BNBBUSD
|
||||||
|
limitOrder: true
|
||||||
|
quantity: 0.16
|
||||||
# kline interval for indicators
|
# kline interval for indicators
|
||||||
interval: 3m
|
interval: 1m
|
||||||
stoploss: 0.2%
|
stoploss: 0.01%
|
||||||
windowATR: 14
|
windowATR: 14
|
||||||
windowQuick: 5
|
windowQuick: 5
|
||||||
windowSlow: 19
|
windowSlow: 9
|
||||||
source: hl2
|
source: hl2
|
||||||
pendingMinutes: 10
|
pendingMinutes: 10
|
||||||
useHeikinAshi: true
|
useHeikinAshi: true
|
||||||
|
@ -49,7 +51,7 @@ exchangeStrategies:
|
||||||
#trailingCallbackRate: []
|
#trailingCallbackRate: []
|
||||||
#trailingCallbackRate: [0.002, 0.01, 0.1]
|
#trailingCallbackRate: [0.002, 0.01, 0.1]
|
||||||
#trailingCallbackRate: [0.0004, 0.0009, 0.018]
|
#trailingCallbackRate: [0.0004, 0.0009, 0.018]
|
||||||
trailingCallbackRate: [0.0006, 0.0049, 0.006]
|
trailingCallbackRate: [0.0006, 0.0019, 0.006]
|
||||||
|
|
||||||
#exits:
|
#exits:
|
||||||
# - roiStopLoss:
|
# - roiStopLoss:
|
||||||
|
@ -119,4 +121,4 @@ backtest:
|
||||||
takerFeeRate: 0.000
|
takerFeeRate: 0.000
|
||||||
balances:
|
balances:
|
||||||
BNB: 0
|
BNB: 0
|
||||||
BUSD: 20
|
BUSD: 100
|
||||||
|
|
|
@ -230,7 +230,16 @@ func (e *GeneralOrderExecutor) reduceQuantityAndSubmitOrder(ctx context.Context,
|
||||||
var err error
|
var err error
|
||||||
for i := 0; i < submitOrderRetryLimit; i++ {
|
for i := 0; i < submitOrderRetryLimit; i++ {
|
||||||
q := submitOrder.Quantity.Mul(fixedpoint.One.Sub(quantityReduceDelta))
|
q := submitOrder.Quantity.Mul(fixedpoint.One.Sub(quantityReduceDelta))
|
||||||
log.Warnf("retrying order, adjusting order quantity: %f -> %f", submitOrder.Quantity.Float64(), q.Float64())
|
if submitOrder.Side == types.SideTypeSell {
|
||||||
|
if baseBalance, ok := e.session.GetAccount().Balance(e.position.Market.BaseCurrency); ok {
|
||||||
|
q = fixedpoint.Min(q, baseBalance.Available)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if quoteBalance, ok := e.session.GetAccount().Balance(e.position.Market.QuoteCurrency); ok {
|
||||||
|
q = fixedpoint.Min(q, quoteBalance.Available.Div(price))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
log.Warnf("retrying order, adjusting order quantity: %v -> %v", submitOrder.Quantity, q)
|
||||||
|
|
||||||
submitOrder.Quantity = q
|
submitOrder.Quantity = q
|
||||||
if e.position.Market.IsDustQuantity(submitOrder.Quantity, price) {
|
if e.position.Market.IsDustQuantity(submitOrder.Quantity, price) {
|
||||||
|
@ -260,7 +269,7 @@ func (e *GeneralOrderExecutor) OpenPosition(ctx context.Context, options OpenPos
|
||||||
Tag: strings.Join(options.Tags, ","),
|
Tag: strings.Join(options.Tags, ","),
|
||||||
}
|
}
|
||||||
|
|
||||||
baseBalance, _ := e.session.Account.Balance(e.position.Market.BaseCurrency)
|
baseBalance, _ := e.session.GetAccount().Balance(e.position.Market.BaseCurrency)
|
||||||
|
|
||||||
// FIXME: fix the max quote borrowing checking
|
// FIXME: fix the max quote borrowing checking
|
||||||
// quoteBalance, _ := e.session.Account.Balance(e.position.Market.QuoteCurrency)
|
// quoteBalance, _ := e.session.Account.Balance(e.position.Market.QuoteCurrency)
|
||||||
|
|
|
@ -14,9 +14,9 @@ import (
|
||||||
type Drift struct {
|
type Drift struct {
|
||||||
types.SeriesBase
|
types.SeriesBase
|
||||||
types.IntervalWindow
|
types.IntervalWindow
|
||||||
chng *types.Queue
|
chng *types.Queue
|
||||||
Values floats.Slice
|
Values floats.Slice
|
||||||
MA types.UpdatableSeriesExtend
|
MA types.UpdatableSeriesExtend
|
||||||
LastValue float64
|
LastValue float64
|
||||||
|
|
||||||
UpdateCallbacks []func(value float64)
|
UpdateCallbacks []func(value float64)
|
||||||
|
|
|
@ -13,6 +13,7 @@ import (
|
||||||
|
|
||||||
"github.com/sirupsen/logrus"
|
"github.com/sirupsen/logrus"
|
||||||
"github.com/wcharczuk/go-chart/v2"
|
"github.com/wcharczuk/go-chart/v2"
|
||||||
|
"go.uber.org/multierr"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/bbgo"
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
"github.com/c9s/bbgo/pkg/datatype/floats"
|
"github.com/c9s/bbgo/pkg/datatype/floats"
|
||||||
|
@ -37,6 +38,19 @@ func init() {
|
||||||
bbgo.RegisterStrategy(ID, &Strategy{})
|
bbgo.RegisterStrategy(ID, &Strategy{})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func filterErrors(errs []error) (es []error) {
|
||||||
|
for _, e := range errs {
|
||||||
|
if _, ok := e.(types.ZeroAssetError); ok {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if bbgo.ErrExceededSubmitOrderRetryLimit == e {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
es = append(es, e)
|
||||||
|
}
|
||||||
|
return es
|
||||||
|
}
|
||||||
|
|
||||||
type Strategy struct {
|
type Strategy struct {
|
||||||
Symbol string `json:"symbol"`
|
Symbol string `json:"symbol"`
|
||||||
|
|
||||||
|
@ -152,7 +166,6 @@ func (s *Strategy) CurrentPosition() *types.Position {
|
||||||
func (s *Strategy) ClosePosition(ctx context.Context, percentage fixedpoint.Value) error {
|
func (s *Strategy) ClosePosition(ctx context.Context, percentage fixedpoint.Value) error {
|
||||||
order := s.p.NewMarketCloseOrder(percentage)
|
order := s.p.NewMarketCloseOrder(percentage)
|
||||||
if order == nil {
|
if order == nil {
|
||||||
s.positionLock.Unlock()
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
order.Tag = "close"
|
order.Tag = "close"
|
||||||
|
@ -169,7 +182,6 @@ func (s *Strategy) ClosePosition(ctx context.Context, percentage fixedpoint.Valu
|
||||||
order.Quantity = baseBalance
|
order.Quantity = baseBalance
|
||||||
}
|
}
|
||||||
order.MarginSideEffect = types.SideEffectTypeAutoRepay
|
order.MarginSideEffect = types.SideEffectTypeAutoRepay
|
||||||
s.positionLock.Unlock()
|
|
||||||
for {
|
for {
|
||||||
if s.Market.IsDustQuantity(order.Quantity, price) {
|
if s.Market.IsDustQuantity(order.Quantity, price) {
|
||||||
return nil
|
return nil
|
||||||
|
@ -383,11 +395,11 @@ func (s *Strategy) initTickerFunctions(ctx context.Context) {
|
||||||
s.trailingCheck(pricef, "short"))
|
s.trailingCheck(pricef, "short"))
|
||||||
exitLongCondition := s.buyPrice > 0 && (s.buyPrice*(1.-stoploss) >= pricef ||
|
exitLongCondition := s.buyPrice > 0 && (s.buyPrice*(1.-stoploss) >= pricef ||
|
||||||
s.trailingCheck(pricef, "long"))
|
s.trailingCheck(pricef, "long"))
|
||||||
|
|
||||||
|
s.positionLock.Unlock()
|
||||||
if exitShortCondition || exitLongCondition {
|
if exitShortCondition || exitLongCondition {
|
||||||
s.ClosePosition(ctx, fixedpoint.One)
|
s.ClosePosition(ctx, fixedpoint.One)
|
||||||
log.Infof("close position by orderbook changes")
|
log.Infof("close position by orderbook changes")
|
||||||
} else {
|
|
||||||
s.positionLock.Unlock()
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
s.getLastPrice = func() (lastPrice fixedpoint.Value) {
|
s.getLastPrice = func() (lastPrice fixedpoint.Value) {
|
||||||
|
@ -621,10 +633,9 @@ func (s *Strategy) klineHandler1m(ctx context.Context, kline types.KLine) {
|
||||||
s.trailingCheck(highf, "short") /* || s.drift1m.Last() > 0*/)
|
s.trailingCheck(highf, "short") /* || s.drift1m.Last() > 0*/)
|
||||||
exitLongCondition := s.buyPrice > 0 && (s.buyPrice*(1.-stoploss) >= lowf ||
|
exitLongCondition := s.buyPrice > 0 && (s.buyPrice*(1.-stoploss) >= lowf ||
|
||||||
s.trailingCheck(lowf, "long") /* || s.drift1m.Last() < 0*/)
|
s.trailingCheck(lowf, "long") /* || s.drift1m.Last() < 0*/)
|
||||||
|
s.positionLock.Unlock()
|
||||||
if exitShortCondition || exitLongCondition {
|
if exitShortCondition || exitLongCondition {
|
||||||
_ = s.ClosePosition(ctx, fixedpoint.One)
|
_ = s.ClosePosition(ctx, fixedpoint.One)
|
||||||
} else {
|
|
||||||
s.positionLock.Unlock()
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -706,8 +717,8 @@ func (s *Strategy) klineHandler(ctx context.Context, kline types.KLine) {
|
||||||
return v <= 0
|
return v <= 0
|
||||||
}, 50).Mean(50)
|
}, 50).Mean(50)
|
||||||
|
|
||||||
shortCondition := (drift[1] >= s.DriftFilterNeg || ddrift[1] >= 0) && (driftPred <= s.DDriftFilterNeg || ddriftPred <= 0) || drift[1] < 0 && drift[0] < 0
|
shortCondition := drift[1] >= 0 && drift[0] <= 0 || (drift[1] >= drift[0] && drift[1] <= 0) || ddrift[1] >= 0 && ddrift[0] <= 0 || (ddrift[1] >= ddrift[0] && ddrift[1] <= 0)
|
||||||
longCondition := (drift[1] <= s.DriftFilterPos || ddrift[1] <= 0) && (driftPred >= s.DDriftFilterPos || ddriftPred >= 0) || drift[1] > 0 && drift[0] > 0
|
longCondition := drift[1] <= 0 && drift[0] >= 0 || (drift[1] <= drift[0] && drift[1] >= 0) || ddrift[1] <= 0 && ddrift[0] >= 0 || (ddrift[1] <= ddrift[0] && ddrift[1] >= 0)
|
||||||
if shortCondition && longCondition {
|
if shortCondition && longCondition {
|
||||||
if drift[1] > drift[0] {
|
if drift[1] > drift[0] {
|
||||||
longCondition = false
|
longCondition = false
|
||||||
|
@ -721,14 +732,16 @@ func (s *Strategy) klineHandler(ctx context.Context, kline types.KLine) {
|
||||||
s.trailingCheck(pricef, "long"))
|
s.trailingCheck(pricef, "long"))
|
||||||
|
|
||||||
if exitShortCondition || exitLongCondition {
|
if exitShortCondition || exitLongCondition {
|
||||||
|
s.positionLock.Unlock()
|
||||||
if err := s.GeneralOrderExecutor.GracefulCancel(ctx); err != nil {
|
if err := s.GeneralOrderExecutor.GracefulCancel(ctx); err != nil {
|
||||||
log.WithError(err).Errorf("cannot cancel orders")
|
log.WithError(err).Errorf("cannot cancel orders")
|
||||||
s.positionLock.Unlock()
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
_ = s.ClosePosition(ctx, fixedpoint.One)
|
_ = s.ClosePosition(ctx, fixedpoint.One)
|
||||||
if longCondition || shortCondition {
|
if shortCondition || longCondition {
|
||||||
s.positionLock.Lock()
|
s.positionLock.Lock()
|
||||||
|
} else {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -756,10 +769,11 @@ func (s *Strategy) klineHandler(ctx context.Context, kline types.KLine) {
|
||||||
opt.Tags = []string{"long"}
|
opt.Tags = []string{"long"}
|
||||||
createdOrders, err := s.GeneralOrderExecutor.OpenPosition(ctx, opt)
|
createdOrders, err := s.GeneralOrderExecutor.OpenPosition(ctx, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if _, ok := err.(types.ZeroAssetError); ok {
|
errs := filterErrors(multierr.Errors(err))
|
||||||
return
|
if len(errs) > 0 {
|
||||||
|
log.Errorf("%v", errs)
|
||||||
|
log.WithError(err).Errorf("cannot place buy order")
|
||||||
}
|
}
|
||||||
log.WithError(err).Errorf("cannot place buy order")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Infof("orders %v", createdOrders)
|
log.Infof("orders %v", createdOrders)
|
||||||
|
@ -774,6 +788,7 @@ func (s *Strategy) klineHandler(ctx context.Context, kline types.KLine) {
|
||||||
s.positionLock.Unlock()
|
s.positionLock.Unlock()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
/*source = source.Add(fixedpoint.NewFromFloat(s.stdevHigh.Last() * s.HighLowVarianceMultiplier))
|
/*source = source.Add(fixedpoint.NewFromFloat(s.stdevHigh.Last() * s.HighLowVarianceMultiplier))
|
||||||
if source.Compare(price) < 0 {
|
if source.Compare(price) < 0 {
|
||||||
source = price
|
source = price
|
||||||
|
@ -793,10 +808,10 @@ func (s *Strategy) klineHandler(ctx context.Context, kline types.KLine) {
|
||||||
opt.Tags = []string{"short"}
|
opt.Tags = []string{"short"}
|
||||||
createdOrders, err := s.GeneralOrderExecutor.OpenPosition(ctx, opt)
|
createdOrders, err := s.GeneralOrderExecutor.OpenPosition(ctx, opt)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if _, ok := err.(types.ZeroAssetError); ok {
|
errs := filterErrors(multierr.Errors(err))
|
||||||
return
|
if len(errs) > 0 {
|
||||||
|
log.WithError(err).Errorf("cannot place sell order")
|
||||||
}
|
}
|
||||||
log.WithError(err).Errorf("cannot place buy order")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
log.Infof("orders %v", createdOrders)
|
log.Infof("orders %v", createdOrders)
|
||||||
|
@ -889,46 +904,21 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
}
|
}
|
||||||
s.positionLock.Lock()
|
s.positionLock.Lock()
|
||||||
defer s.positionLock.Unlock()
|
defer s.positionLock.Unlock()
|
||||||
// tag == "" is for exits trades
|
if s.p.IsDust(trade.Price) {
|
||||||
if tag == "close" || tag == "" {
|
s.buyPrice = 0
|
||||||
if s.p.IsDust(trade.Price) {
|
s.sellPrice = 0
|
||||||
s.buyPrice = 0
|
s.highestPrice = 0
|
||||||
s.sellPrice = 0
|
s.lowestPrice = 0
|
||||||
s.highestPrice = 0
|
} else if s.p.IsLong() {
|
||||||
s.lowestPrice = 0
|
s.buyPrice = s.p.ApproximateAverageCost.Float64() //trade.Price.Float64()
|
||||||
} else if s.p.IsLong() {
|
s.sellPrice = 0
|
||||||
s.sellPrice = 0
|
s.highestPrice = math.Max(s.buyPrice, s.highestPrice)
|
||||||
s.lowestPrice = 0
|
s.lowestPrice = 0
|
||||||
} else {
|
} else if s.p.IsShort() {
|
||||||
s.buyPrice = 0
|
s.sellPrice = s.p.ApproximateAverageCost.Float64() //trade.Price.Float64()
|
||||||
s.highestPrice = 0
|
s.buyPrice = 0
|
||||||
}
|
s.highestPrice = 0
|
||||||
} else if tag == "long" {
|
s.lowestPrice = math.Min(s.lowestPrice, s.sellPrice)
|
||||||
if s.p.IsDust(trade.Price) {
|
|
||||||
s.buyPrice = 0
|
|
||||||
s.sellPrice = 0
|
|
||||||
s.highestPrice = 0
|
|
||||||
s.lowestPrice = 0
|
|
||||||
} else if s.p.IsLong() {
|
|
||||||
s.buyPrice = trade.Price.Float64()
|
|
||||||
s.sellPrice = 0
|
|
||||||
s.highestPrice = s.buyPrice
|
|
||||||
s.lowestPrice = 0
|
|
||||||
}
|
|
||||||
} else if tag == "short" {
|
|
||||||
if s.p.IsDust(trade.Price) {
|
|
||||||
s.sellPrice = 0
|
|
||||||
s.buyPrice = 0
|
|
||||||
s.highestPrice = 0
|
|
||||||
s.lowestPrice = 0
|
|
||||||
} else if s.p.IsShort() {
|
|
||||||
s.sellPrice = trade.Price.Float64()
|
|
||||||
s.buyPrice = 0
|
|
||||||
s.highestPrice = 0
|
|
||||||
s.lowestPrice = s.sellPrice
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
panic("tag unknown")
|
|
||||||
}
|
}
|
||||||
bbgo.Notify("tag: %s, sp: %.4f bp: %.4f hp: %.4f lp: %.4f, trade: %s, pos: %s", tag, s.sellPrice, s.buyPrice, s.highestPrice, s.lowestPrice, trade.String(), s.p.String())
|
bbgo.Notify("tag: %s, sp: %.4f bp: %.4f hp: %.4f lp: %.4f, trade: %s, pos: %s", tag, s.sellPrice, s.buyPrice, s.highestPrice, s.lowestPrice, trade.String(), s.p.String())
|
||||||
})
|
})
|
||||||
|
|
|
@ -152,7 +152,8 @@ func (s *Strategy) initIndicators(store *bbgo.SerialMarketDataStore) error {
|
||||||
maSlow := &indicator.SMA{IntervalWindow: types.IntervalWindow{Interval: s.Interval, Window: s.WindowSlow}}
|
maSlow := &indicator.SMA{IntervalWindow: types.IntervalWindow{Interval: s.Interval, Window: s.WindowSlow}}
|
||||||
maQuick := &indicator.SMA{IntervalWindow: types.IntervalWindow{Interval: s.Interval, Window: s.WindowQuick}}
|
maQuick := &indicator.SMA{IntervalWindow: types.IntervalWindow{Interval: s.Interval, Window: s.WindowQuick}}
|
||||||
s.ewo = &ElliottWave{
|
s.ewo = &ElliottWave{
|
||||||
maSlow, maQuick,
|
maSlow: maSlow,
|
||||||
|
maQuick: maQuick,
|
||||||
}
|
}
|
||||||
s.atr = &indicator.ATR{IntervalWindow: types.IntervalWindow{Interval: s.Interval, Window: s.WindowATR}}
|
s.atr = &indicator.ATR{IntervalWindow: types.IntervalWindow{Interval: s.Interval, Window: s.WindowATR}}
|
||||||
klines, ok := store.KLinesOfInterval(s.Interval)
|
klines, ok := store.KLinesOfInterval(s.Interval)
|
||||||
|
@ -371,10 +372,10 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
s.InitDrawCommands(store, &profit, &cumProfit)
|
s.InitDrawCommands(store, &profit, &cumProfit)
|
||||||
store.OnKLineClosed(func(kline types.KLine) {
|
store.OnKLineClosed(func(kline types.KLine) {
|
||||||
s.minutesCounter = int(kline.StartTime.Time().Add(kline.Interval.Duration()).Sub(s.startTime).Minutes())
|
s.minutesCounter = int(kline.StartTime.Time().Add(kline.Interval.Duration()).Sub(s.startTime).Minutes())
|
||||||
if kline.Interval == types.Interval1m {
|
if kline.Interval == s.Interval {
|
||||||
s.klineHandler1m(ctx, kline)
|
|
||||||
} else if kline.Interval == s.Interval {
|
|
||||||
s.klineHandler(ctx, kline)
|
s.klineHandler(ctx, kline)
|
||||||
|
} else if kline.Interval == types.Interval1m {
|
||||||
|
s.klineHandler1m(ctx, kline)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
|
@ -213,9 +213,9 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
|
|
||||||
// use kline direction to prevent reversing position too soon
|
// use kline direction to prevent reversing position too soon
|
||||||
if diffQty.Sign() > 0 { // && kline.Direction() >= 0
|
if diffQty.Sign() > 0 { // && kline.Direction() >= 0
|
||||||
s.orderExecutor.OpenPosition(context.Background(), bbgo.OpenPositionOptions{Quantity: diffQty.Abs(), Long: true, MarketOrder: true})
|
s.orderExecutor.OpenPosition(context.Background(), bbgo.OpenPositionOptions{Quantity: diffQty.Abs(), Long: true, LimitOrder: false})
|
||||||
} else if diffQty.Sign() < 0 { // && kline.Direction() <= 0
|
} else if diffQty.Sign() < 0 { // && kline.Direction() <= 0
|
||||||
s.orderExecutor.OpenPosition(context.Background(), bbgo.OpenPositionOptions{Quantity: diffQty.Abs(), Short: true, MarketOrder: true})
|
s.orderExecutor.OpenPosition(context.Background(), bbgo.OpenPositionOptions{Quantity: diffQty.Abs(), Short: true, LimitOrder: false})
|
||||||
}
|
}
|
||||||
|
|
||||||
}))
|
}))
|
||||||
|
|
Loading…
Reference in New Issue
Block a user