mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-22 23:05:15 +00:00
fix: highest price and lowest price reset, condition gets crossed
This commit is contained in:
parent
2c4e03a102
commit
5be6e822e9
|
@ -880,6 +880,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
bp := buyPrice
|
bp := buyPrice
|
||||||
vol := Volume
|
vol := Volume
|
||||||
sp := sellPrice
|
sp := sellPrice
|
||||||
|
resetPrice := false
|
||||||
if tag == "close" {
|
if tag == "close" {
|
||||||
if !buyPrice.IsZero() {
|
if !buyPrice.IsZero() {
|
||||||
if trade.Side == types.SideTypeSell {
|
if trade.Side == types.SideTypeSell {
|
||||||
|
@ -898,8 +899,10 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
if Volume.Sign() < 0 {
|
if Volume.Sign() < 0 {
|
||||||
sellPrice = trade.Price
|
sellPrice = trade.Price
|
||||||
buyPrice = fixedpoint.Zero
|
buyPrice = fixedpoint.Zero
|
||||||
|
resetPrice = true
|
||||||
} else if Volume.Sign() == 0 {
|
} else if Volume.Sign() == 0 {
|
||||||
buyPrice = fixedpoint.Zero
|
buyPrice = fixedpoint.Zero
|
||||||
|
resetPrice = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
buyPrice = buyPrice.Mul(Volume).Add(trade.Price.Mul(trade.Quantity)).Div(Volume.Add(trade.Quantity))
|
buyPrice = buyPrice.Mul(Volume).Add(trade.Price.Mul(trade.Quantity)).Div(Volume.Add(trade.Quantity))
|
||||||
|
@ -923,8 +926,10 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
if Volume.Sign() > 0 {
|
if Volume.Sign() > 0 {
|
||||||
buyPrice = trade.Price
|
buyPrice = trade.Price
|
||||||
sellPrice = fixedpoint.Zero
|
sellPrice = fixedpoint.Zero
|
||||||
|
resetPrice = true
|
||||||
} else if Volume.Sign() == 0 {
|
} else if Volume.Sign() == 0 {
|
||||||
sellPrice = fixedpoint.Zero
|
sellPrice = fixedpoint.Zero
|
||||||
|
resetPrice = true
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
sellPrice = sellPrice.Mul(Volume).Sub(trade.Price.Mul(trade.Quantity)).Div(Volume.Sub(trade.Quantity))
|
sellPrice = sellPrice.Mul(Volume).Sub(trade.Price.Mul(trade.Quantity)).Div(Volume.Sub(trade.Quantity))
|
||||||
|
@ -932,17 +937,27 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// position changed by strategy
|
// position changed by strategy
|
||||||
|
oldSign := Volume.Sign()
|
||||||
if trade.Side == types.SideTypeBuy {
|
if trade.Side == types.SideTypeBuy {
|
||||||
Volume = Volume.Add(trade.Quantity)
|
Volume = Volume.Add(trade.Quantity)
|
||||||
if Volume.Sign() > 0 {
|
if Volume.Sign() > 0 {
|
||||||
buyPrice = trade.Price
|
buyPrice = trade.Price
|
||||||
sellPrice = fixedpoint.Zero
|
sellPrice = fixedpoint.Zero
|
||||||
|
if oldSign <= 0 {
|
||||||
|
resetPrice = true
|
||||||
|
}
|
||||||
} else if Volume.Sign() < 0 {
|
} else if Volume.Sign() < 0 {
|
||||||
sellPrice = trade.Price
|
sellPrice = trade.Price
|
||||||
buyPrice = fixedpoint.Zero
|
buyPrice = fixedpoint.Zero
|
||||||
|
if oldSign >= 0 {
|
||||||
|
resetPrice = true
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
buyPrice = fixedpoint.Zero
|
buyPrice = fixedpoint.Zero
|
||||||
sellPrice = fixedpoint.Zero
|
sellPrice = fixedpoint.Zero
|
||||||
|
if oldSign != 0 {
|
||||||
|
resetPrice = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else if trade.Side == types.SideTypeSell {
|
} else if trade.Side == types.SideTypeSell {
|
||||||
sellPrice = trade.Price
|
sellPrice = trade.Price
|
||||||
|
@ -950,12 +965,21 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
if Volume.Sign() > 0 {
|
if Volume.Sign() > 0 {
|
||||||
buyPrice = trade.Price
|
buyPrice = trade.Price
|
||||||
sellPrice = fixedpoint.Zero
|
sellPrice = fixedpoint.Zero
|
||||||
|
if oldSign <= 0 {
|
||||||
|
resetPrice = true
|
||||||
|
}
|
||||||
} else if Volume.Sign() < 0 {
|
} else if Volume.Sign() < 0 {
|
||||||
sellPrice = trade.Price
|
sellPrice = trade.Price
|
||||||
buyPrice = fixedpoint.Zero
|
buyPrice = fixedpoint.Zero
|
||||||
|
if oldSign >= 0 {
|
||||||
|
resetPrice = true
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
buyPrice = fixedpoint.Zero
|
buyPrice = fixedpoint.Zero
|
||||||
sellPrice = fixedpoint.Zero
|
sellPrice = fixedpoint.Zero
|
||||||
|
if oldSign != 0 {
|
||||||
|
resetPrice = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -974,6 +998,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
sellPrice = trade.Price
|
sellPrice = trade.Price
|
||||||
}
|
}
|
||||||
Volume = Volume.Sub(trade.Quantity)
|
Volume = Volume.Sub(trade.Quantity)
|
||||||
|
resetPrice = true
|
||||||
} else if tag == "long" {
|
} else if tag == "long" {
|
||||||
if sellPrice.IsZero() {
|
if sellPrice.IsZero() {
|
||||||
if !buyPrice.IsZero() {
|
if !buyPrice.IsZero() {
|
||||||
|
@ -989,12 +1014,14 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
Volume = fixedpoint.Zero
|
Volume = fixedpoint.Zero
|
||||||
}
|
}
|
||||||
Volume = Volume.Add(trade.Quantity)
|
Volume = Volume.Add(trade.Quantity)
|
||||||
|
resetPrice = true
|
||||||
} else if tag == "rebalance" {
|
} else if tag == "rebalance" {
|
||||||
if sellPrice.IsZero() {
|
if sellPrice.IsZero() {
|
||||||
profit.Update(modify(sellPrice.Div(trade.Price)).Float64())
|
profit.Update(modify(sellPrice.Div(trade.Price)).Float64())
|
||||||
} else {
|
} else {
|
||||||
profit.Update(modify(trade.Price.Div(buyPrice)).Float64())
|
profit.Update(modify(trade.Price.Div(buyPrice)).Float64())
|
||||||
}
|
}
|
||||||
|
resetPrice = true
|
||||||
cumProfit.Update(cumProfit.Last() * profit.Last())
|
cumProfit.Update(cumProfit.Last() * profit.Last())
|
||||||
sellPrice = fixedpoint.Zero
|
sellPrice = fixedpoint.Zero
|
||||||
buyPrice = fixedpoint.Zero
|
buyPrice = fixedpoint.Zero
|
||||||
|
@ -1004,9 +1031,11 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
s.p.Reset()
|
s.p.Reset()
|
||||||
}
|
}
|
||||||
s.buyPrice = buyPrice.Float64()
|
s.buyPrice = buyPrice.Float64()
|
||||||
s.highestPrice = s.buyPrice
|
|
||||||
s.sellPrice = sellPrice.Float64()
|
s.sellPrice = sellPrice.Float64()
|
||||||
|
if resetPrice {
|
||||||
|
s.highestPrice = s.buyPrice
|
||||||
s.lowestPrice = s.sellPrice
|
s.lowestPrice = s.sellPrice
|
||||||
|
}
|
||||||
bbgo.Notify("tag %s %v %s volafter: %v, quantity: %v, bp: %v, sp: %v, volbefore: %v, bpafter: %v, spafter: %v", tag, trade.Price, trade.Side, Volume, trade.Quantity, bp, sp, vol, s.buyPrice, s.sellPrice)
|
bbgo.Notify("tag %s %v %s volafter: %v, quantity: %v, bp: %v, sp: %v, volbefore: %v, bpafter: %v, spafter: %v", tag, trade.Price, trade.Side, Volume, trade.Quantity, bp, sp, vol, s.buyPrice, s.sellPrice)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1110,10 +1139,10 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
avg := s.buyPrice + s.sellPrice
|
avg := s.buyPrice + s.sellPrice
|
||||||
exitShortCondition := ( /*avg*(1.+stoploss) <= pricef || (drift > 0 || ddrift > DDriftFilterPos) ||*/ avg-atr*takeProfitFactor >= pricef ||
|
exitShortCondition := ( /*avg*(1.+stoploss) <= pricef || (drift > 0 || ddrift > DDriftFilterPos) ||*/ avg-atr*takeProfitFactor >= pricef ||
|
||||||
s.trailingCheck(highf, "short")) &&
|
s.trailingCheck(highf, "short")) &&
|
||||||
(s.Position.IsShort() && !s.Position.IsDust(price))
|
(s.p.IsShort() && !s.p.IsDust(price))
|
||||||
exitLongCondition := ( /*avg*(1.-stoploss) >= pricef || (drift < 0 || ddrift < DDriftFilterNeg) ||*/ avg+atr*takeProfitFactor <= pricef ||
|
exitLongCondition := ( /*avg*(1.-stoploss) >= pricef || (drift < 0 || ddrift < DDriftFilterNeg) ||*/ avg+atr*takeProfitFactor <= pricef ||
|
||||||
s.trailingCheck(lowf, "long")) &&
|
s.trailingCheck(lowf, "long")) &&
|
||||||
(s.Position.IsLong() && !s.Position.IsDust(price))
|
(s.p.IsLong() && !s.p.IsDust(price))
|
||||||
if exitShortCondition || exitLongCondition {
|
if exitShortCondition || exitLongCondition {
|
||||||
if exitLongCondition && s.highestPrice > avg {
|
if exitLongCondition && s.highestPrice > avg {
|
||||||
s.takeProfitFactor.Update((s.highestPrice - avg) / atr * 1.5)
|
s.takeProfitFactor.Update((s.highestPrice - avg) / atr * 1.5)
|
||||||
|
@ -1153,7 +1182,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
highdiff := highf - s.ma.Last()
|
highdiff := highf - s.ma.Last()
|
||||||
s.stdevHigh.Update(highdiff)
|
s.stdevHigh.Update(highdiff)
|
||||||
|
|
||||||
//log.Errorf("highdiff: %3.2f ma: %.2f, close: %8v, high: %8v, low: %8v, time: %v", s.stdevHigh.Last(), s.ma.Last(), kline.Close, kline.High, kline.Low, kline.StartTime)
|
log.Errorf("highdiff: %3.2f ma: %.2f, close: %8v, high: %8v, low: %8v, time: %v", s.stdevHigh.Last(), s.ma.Last(), kline.Close, kline.High, kline.Low, kline.StartTime)
|
||||||
if s.lowestPrice > 0 && lowf < s.lowestPrice {
|
if s.lowestPrice > 0 && lowf < s.lowestPrice {
|
||||||
s.lowestPrice = lowf
|
s.lowestPrice = lowf
|
||||||
}
|
}
|
||||||
|
@ -1180,16 +1209,23 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
|
|
||||||
shortCondition := (drift[1] >= DriftFilterNeg || ddrift[1] >= 0) && (driftPred <= DDriftFilterNeg || ddriftPred <= 0) || drift[1] < 0 && drift[0] < 0
|
shortCondition := (drift[1] >= DriftFilterNeg || ddrift[1] >= 0) && (driftPred <= DDriftFilterNeg || ddriftPred <= 0) || drift[1] < 0 && drift[0] < 0
|
||||||
longCondition := (drift[1] <= DriftFilterPos || ddrift[1] <= 0) && (driftPred >= DDriftFilterPos || ddriftPred >= 0) || drift[1] > 0 && drift[0] > 0
|
longCondition := (drift[1] <= DriftFilterPos || ddrift[1] <= 0) && (driftPred >= DDriftFilterPos || ddriftPred >= 0) || drift[1] > 0 && drift[0] > 0
|
||||||
exitShortCondition := ((drift[0] >= DDriftFilterPos || ddrift[0] >= 0) ||
|
exitShortCondition := ((drift[0] >= DDriftFilterPos && ddrift[0] >= 0) ||
|
||||||
avg*(1.+stoploss) <= pricef ||
|
avg*(1.+stoploss) <= pricef ||
|
||||||
avg-atr*takeProfitFactor >= pricef) &&
|
avg-atr*takeProfitFactor >= pricef) &&
|
||||||
s.Position.IsShort()
|
s.p.IsShort()
|
||||||
exitLongCondition := ((drift[0] <= DDriftFilterNeg || ddrift[0] <= 0) ||
|
exitLongCondition := ((drift[0] <= DDriftFilterNeg && ddrift[0] <= 0) ||
|
||||||
avg*(1.-stoploss) >= pricef ||
|
avg*(1.-stoploss) >= pricef ||
|
||||||
avg+atr*takeProfitFactor <= pricef) &&
|
avg+atr*takeProfitFactor <= pricef) &&
|
||||||
s.Position.IsLong()
|
s.p.IsLong()
|
||||||
|
if shortCondition && longCondition {
|
||||||
|
if drift[1] > drift[0] {
|
||||||
|
longCondition = false
|
||||||
|
} else {
|
||||||
|
shortCondition = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (exitShortCondition || exitLongCondition) && s.Position.IsOpened(price) && !shortCondition && !longCondition {
|
if (exitShortCondition || exitLongCondition) && s.p.IsOpened(price) && !shortCondition && !longCondition {
|
||||||
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")
|
||||||
return
|
return
|
||||||
|
@ -1205,6 +1241,46 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
_ = s.ClosePosition(ctx, fixedpoint.One)
|
_ = s.ClosePosition(ctx, fixedpoint.One)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
if longCondition {
|
||||||
|
if err := s.GeneralOrderExecutor.GracefulCancel(ctx); err != nil {
|
||||||
|
log.WithError(err).Errorf("cannot cancel orders")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
source = source.Sub(fixedpoint.NewFromFloat(s.stdevLow.Last() * s.HighLowVarianceMultiplier))
|
||||||
|
if source.Compare(price) > 0 {
|
||||||
|
source = price
|
||||||
|
}
|
||||||
|
sourcef = source.Float64()
|
||||||
|
|
||||||
|
quoteBalance, ok := s.Session.GetAccount().Balance(s.Market.QuoteCurrency)
|
||||||
|
if !ok {
|
||||||
|
log.Errorf("unable to get quoteCurrency")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if s.Market.IsDustQuantity(
|
||||||
|
quoteBalance.Available.Div(source), source) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if avg > s.lowestPrice && s.Position.IsShort() {
|
||||||
|
s.takeProfitFactor.Update((avg - s.lowestPrice) / atr * 1.5)
|
||||||
|
}
|
||||||
|
quantity := quoteBalance.Available.Div(source)
|
||||||
|
createdOrders, err := s.GeneralOrderExecutor.SubmitOrders(ctx, types.SubmitOrder{
|
||||||
|
Symbol: s.Symbol,
|
||||||
|
Side: types.SideTypeBuy,
|
||||||
|
Type: types.OrderTypeLimit,
|
||||||
|
Price: source,
|
||||||
|
Quantity: quantity,
|
||||||
|
Tag: "long",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
log.WithError(err).Errorf("cannot place buy order")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
orderTagHistory[createdOrders[0].OrderID] = "long"
|
||||||
|
s.orderPendingCounter[createdOrders[0].OrderID] = s.minutesCounter
|
||||||
|
return
|
||||||
|
}
|
||||||
if shortCondition {
|
if shortCondition {
|
||||||
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")
|
||||||
|
@ -1243,46 +1319,8 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
||||||
}
|
}
|
||||||
orderTagHistory[createdOrders[0].OrderID] = "short"
|
orderTagHistory[createdOrders[0].OrderID] = "short"
|
||||||
s.orderPendingCounter[createdOrders[0].OrderID] = s.minutesCounter
|
s.orderPendingCounter[createdOrders[0].OrderID] = s.minutesCounter
|
||||||
}
|
|
||||||
if longCondition {
|
|
||||||
if err := s.GeneralOrderExecutor.GracefulCancel(ctx); err != nil {
|
|
||||||
log.WithError(err).Errorf("cannot cancel orders")
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
source = source.Sub(fixedpoint.NewFromFloat(s.stdevLow.Last() * s.HighLowVarianceMultiplier))
|
|
||||||
if source.Compare(price) > 0 {
|
|
||||||
source = price
|
|
||||||
}
|
|
||||||
sourcef = source.Float64()
|
|
||||||
|
|
||||||
quoteBalance, ok := s.Session.GetAccount().Balance(s.Market.QuoteCurrency)
|
|
||||||
if !ok {
|
|
||||||
log.Errorf("unable to get quoteCurrency")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if s.Market.IsDustQuantity(
|
|
||||||
quoteBalance.Available.Div(source), source) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if avg > s.lowestPrice && s.Position.IsShort() {
|
|
||||||
s.takeProfitFactor.Update((avg - s.lowestPrice) / atr * 1.5)
|
|
||||||
}
|
|
||||||
quantity := quoteBalance.Available.Div(source)
|
|
||||||
createdOrders, err := s.GeneralOrderExecutor.SubmitOrders(ctx, types.SubmitOrder{
|
|
||||||
Symbol: s.Symbol,
|
|
||||||
Side: types.SideTypeBuy,
|
|
||||||
Type: types.OrderTypeLimit,
|
|
||||||
Price: source,
|
|
||||||
Quantity: quantity,
|
|
||||||
Tag: "long",
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
log.WithError(err).Errorf("cannot place buy order")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
orderTagHistory[createdOrders[0].OrderID] = "long"
|
|
||||||
s.orderPendingCounter[createdOrders[0].OrderID] = s.minutesCounter
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
bbgo.OnShutdown(func(ctx context.Context, wg *sync.WaitGroup) {
|
bbgo.OnShutdown(func(ctx context.Context, wg *sync.WaitGroup) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user