mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-21 22:43:52 +00:00
Merge pull request #700 from c9s/strategy/pivot
pivotshort: add breakLow.bounceRatio option
This commit is contained in:
commit
a4e3fd5c41
|
@ -16,9 +16,26 @@ exchangeStrategies:
|
||||||
|
|
||||||
# breakLow settings are used for shorting when the current price break the previous low
|
# breakLow settings are used for shorting when the current price break the previous low
|
||||||
breakLow:
|
breakLow:
|
||||||
|
# ratio is how much the price breaks the previous low to trigger the short.
|
||||||
ratio: 0.1%
|
ratio: 0.1%
|
||||||
|
|
||||||
|
# quantity is used for submitting the sell order
|
||||||
|
# if quantity is not set, all base balance will be used for selling the short.
|
||||||
quantity: 10.0
|
quantity: 10.0
|
||||||
stopEMARange: 5%
|
|
||||||
|
# marketOrder submits the market sell order when the closed price is lower than the previous pivot low.
|
||||||
|
marketOrder: true
|
||||||
|
|
||||||
|
# bounceRatio is used for calculating the price of the limit sell order.
|
||||||
|
# it's ratio of pivot low bounce when a new pivot low is detected.
|
||||||
|
# Sometimes when the price breaks the previous low, the price might be pulled back to a higher price.
|
||||||
|
# The bounceRatio is useful for such case, however, you might also miss the chance to short at the price if there is no pull back.
|
||||||
|
# Notice: When marketOrder is set, bounceRatio will not be used.
|
||||||
|
# bounceRatio: 0.1%
|
||||||
|
|
||||||
|
# stopEMARange is the price range we allow short.
|
||||||
|
# Short-allowed price range = [current price] > [EMA] * (1 - [stopEMARange])
|
||||||
|
stopEMARange: 0%
|
||||||
stopEMA:
|
stopEMA:
|
||||||
interval: 1h
|
interval: 1h
|
||||||
window: 99
|
window: 99
|
||||||
|
@ -36,7 +53,7 @@ exchangeStrategies:
|
||||||
|
|
||||||
# roiTakeProfitPercentage is used to force taking profit by percentage of the position ROI (currently the price change)
|
# roiTakeProfitPercentage is used to force taking profit by percentage of the position ROI (currently the price change)
|
||||||
# force to take the profit ROI exceeded the percentage.
|
# force to take the profit ROI exceeded the percentage.
|
||||||
roiTakeProfitPercentage: 25%
|
roiTakeProfitPercentage: 10%
|
||||||
|
|
||||||
# roiMinTakeProfitPercentage applies to lowerShadowRatio and cumulatedVolume exit options
|
# roiMinTakeProfitPercentage applies to lowerShadowRatio and cumulatedVolume exit options
|
||||||
roiMinTakeProfitPercentage: 10%
|
roiMinTakeProfitPercentage: 10%
|
||||||
|
|
|
@ -67,6 +67,8 @@ type IntervalWindowSetting struct {
|
||||||
// BreakLow -- when price breaks the previous pivot low, we set a trade entry
|
// BreakLow -- when price breaks the previous pivot low, we set a trade entry
|
||||||
type BreakLow struct {
|
type BreakLow struct {
|
||||||
Ratio fixedpoint.Value `json:"ratio"`
|
Ratio fixedpoint.Value `json:"ratio"`
|
||||||
|
MarketOrder bool `json:"marketOrder"`
|
||||||
|
BounceRatio fixedpoint.Value `json:"bounceRatio"`
|
||||||
Quantity fixedpoint.Value `json:"quantity"`
|
Quantity fixedpoint.Value `json:"quantity"`
|
||||||
StopEMARange fixedpoint.Value `json:"stopEMARange"`
|
StopEMARange fixedpoint.Value `json:"stopEMARange"`
|
||||||
StopEMA *types.IntervalWindow `json:"stopEMA"`
|
StopEMA *types.IntervalWindow `json:"stopEMA"`
|
||||||
|
@ -156,7 +158,7 @@ func (s *Strategy) submitOrders(ctx context.Context, orderExecutor bbgo.OrderExe
|
||||||
s.tradeCollector.Process()
|
s.tradeCollector.Process()
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) placeMarketSell(ctx context.Context, orderExecutor bbgo.OrderExecutor, quantity fixedpoint.Value) {
|
func (s *Strategy) useQuantityOrBaseBalance(quantity fixedpoint.Value) fixedpoint.Value {
|
||||||
if quantity.IsZero() {
|
if quantity.IsZero() {
|
||||||
if balance, ok := s.session.Account.Balance(s.Market.BaseCurrency); ok {
|
if balance, ok := s.session.Account.Balance(s.Market.BaseCurrency); ok {
|
||||||
s.Notify("sell quantity is not set, submitting sell with all base balance: %s", balance.Available.String())
|
s.Notify("sell quantity is not set, submitting sell with all base balance: %s", balance.Available.String())
|
||||||
|
@ -166,18 +168,30 @@ func (s *Strategy) placeMarketSell(ctx context.Context, orderExecutor bbgo.Order
|
||||||
|
|
||||||
if quantity.IsZero() {
|
if quantity.IsZero() {
|
||||||
log.Errorf("quantity is zero, can not submit sell order, please check settings")
|
log.Errorf("quantity is zero, can not submit sell order, please check settings")
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
submitOrder := types.SubmitOrder{
|
return quantity
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Strategy) placeLimitSell(ctx context.Context, orderExecutor bbgo.OrderExecutor, price, quantity fixedpoint.Value) {
|
||||||
|
s.submitOrders(ctx, orderExecutor, types.SubmitOrder{
|
||||||
|
Symbol: s.Symbol,
|
||||||
|
Price: price,
|
||||||
|
Side: types.SideTypeSell,
|
||||||
|
Type: types.OrderTypeLimit,
|
||||||
|
Quantity: quantity,
|
||||||
|
MarginSideEffect: types.SideEffectTypeMarginBuy,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Strategy) placeMarketSell(ctx context.Context, orderExecutor bbgo.OrderExecutor, quantity fixedpoint.Value) {
|
||||||
|
s.submitOrders(ctx, orderExecutor, types.SubmitOrder{
|
||||||
Symbol: s.Symbol,
|
Symbol: s.Symbol,
|
||||||
Side: types.SideTypeSell,
|
Side: types.SideTypeSell,
|
||||||
Type: types.OrderTypeMarket,
|
Type: types.OrderTypeMarket,
|
||||||
Quantity: quantity,
|
Quantity: quantity,
|
||||||
MarginSideEffect: types.SideEffectTypeMarginBuy,
|
MarginSideEffect: types.SideEffectTypeMarginBuy,
|
||||||
}
|
})
|
||||||
|
|
||||||
s.submitOrders(ctx, orderExecutor, submitOrder)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Strategy) ClosePosition(ctx context.Context, percentage fixedpoint.Value) error {
|
func (s *Strategy) ClosePosition(ctx context.Context, percentage fixedpoint.Value) error {
|
||||||
|
@ -379,13 +393,18 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
s.Notify("%s price %f breaks the previous low %f with ratio %f, submitting market sell to open a short position", s.Symbol, kline.Close.Float64(), previousLow.Float64(), s.BreakLow.Ratio.Float64())
|
|
||||||
|
|
||||||
if err := s.activeMakerOrders.GracefulCancel(ctx, s.session.Exchange); err != nil {
|
if err := s.activeMakerOrders.GracefulCancel(ctx, s.session.Exchange); err != nil {
|
||||||
log.WithError(err).Errorf("graceful cancel order error")
|
log.WithError(err).Errorf("graceful cancel order error")
|
||||||
}
|
}
|
||||||
|
|
||||||
s.placeMarketSell(ctx, orderExecutor, s.BreakLow.Quantity)
|
quantity := s.useQuantityOrBaseBalance(s.BreakLow.Quantity)
|
||||||
|
if s.BreakLow.MarketOrder {
|
||||||
|
s.Notify("%s price %f breaks the previous low %f with ratio %f, submitting market sell to open a short position", s.Symbol, kline.Close.Float64(), previousLow.Float64(), s.BreakLow.Ratio.Float64())
|
||||||
|
s.placeMarketSell(ctx, orderExecutor, quantity)
|
||||||
|
} else {
|
||||||
|
sellPrice := kline.Close.Mul(fixedpoint.One.Add(s.BreakLow.BounceRatio))
|
||||||
|
s.placeLimitSell(ctx, orderExecutor, sellPrice, quantity)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
session.MarketDataStream.OnKLineClosed(func(kline types.KLine) {
|
session.MarketDataStream.OnKLineClosed(func(kline types.KLine) {
|
||||||
|
@ -394,12 +413,10 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
}
|
}
|
||||||
|
|
||||||
if s.pivot.LastLow() > 0.0 {
|
if s.pivot.LastLow() > 0.0 {
|
||||||
log.Infof("pivot low detected: %f %s", s.pivot.LastLow(), kline.EndTime.Time())
|
log.Debugf("pivot low detected: %f %s", s.pivot.LastLow(), kline.EndTime.Time())
|
||||||
lastLow := fixedpoint.NewFromFloat(s.pivot.LastLow())
|
lastLow := fixedpoint.NewFromFloat(s.pivot.LastLow())
|
||||||
if lastLow.Compare(s.lastLow) != 0 {
|
s.lastLow = lastLow
|
||||||
s.lastLow = lastLow
|
s.pivotLowPrices = append(s.pivotLowPrices, s.lastLow)
|
||||||
s.pivotLowPrices = append(s.pivotLowPrices, s.lastLow)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue
Block a user