mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-10 09:11:55 +00:00
bollmaker: add Test_calculateBandPercentage test
This commit is contained in:
parent
f9d650cd23
commit
aea8f97ab9
|
@ -287,6 +287,18 @@ func (s *Strategy) LoadState() error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (s *Strategy) getCurrentAllowedExposurePosition(bandPercentage float64) (fixedpoint.Value, error) {
|
||||
if s.DynamicExposurePositionScale != nil {
|
||||
v, err := s.DynamicExposurePositionScale.Scale(bandPercentage)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return fixedpoint.NewFromFloat(v), nil
|
||||
}
|
||||
|
||||
return s.MaxExposurePosition, nil
|
||||
}
|
||||
|
||||
func (s *Strategy) placeOrders(ctx context.Context, orderExecutor bbgo.OrderExecutor, midPrice fixedpoint.Value, kline *types.KLine) {
|
||||
askPrice := midPrice.Mul(one + s.Spread)
|
||||
bidPrice := midPrice.Mul(one - s.Spread)
|
||||
|
@ -301,7 +313,6 @@ func (s *Strategy) placeOrders(ctx context.Context, orderExecutor bbgo.OrderExec
|
|||
s.state.Position.String(),
|
||||
)
|
||||
|
||||
quantity := s.CalculateQuantity(midPrice)
|
||||
sellQuantity := s.CalculateQuantity(askPrice)
|
||||
buyQuantity := s.CalculateQuantity(bidPrice)
|
||||
|
||||
|
@ -326,14 +337,25 @@ func (s *Strategy) placeOrders(ctx context.Context, orderExecutor bbgo.OrderExec
|
|||
|
||||
var submitOrders []types.SubmitOrder
|
||||
|
||||
minQuantity := fixedpoint.NewFromFloat(s.market.MinQuantity)
|
||||
baseBalance, hasBaseBalance := balances[s.market.BaseCurrency]
|
||||
quoteBalance, hasQuoteBalance := balances[s.market.QuoteCurrency]
|
||||
canBuy := hasQuoteBalance && quoteBalance.Available > s.Quantity.Mul(midPrice) && (s.MaxExposurePosition > 0 && base < s.MaxExposurePosition)
|
||||
canSell := hasBaseBalance && baseBalance.Available > s.Quantity && (s.MaxExposurePosition > 0 && base > -s.MaxExposurePosition)
|
||||
|
||||
downBand := s.defaultBoll.LastDownBand()
|
||||
upBand := s.defaultBoll.LastUpBand()
|
||||
sma := s.defaultBoll.LastSMA()
|
||||
log.Infof("bollinger band: up %f sma %f down %f", upBand, sma, downBand)
|
||||
|
||||
bandPercentage := calculateBandPercentage(upBand, downBand, sma, midPrice.Float64())
|
||||
maxExposurePosition, err := s.getCurrentAllowedExposurePosition(bandPercentage)
|
||||
if err != nil {
|
||||
log.WithError(err).Errorf("can not calculate CurrentAllowedExposurePosition")
|
||||
return
|
||||
}
|
||||
|
||||
canBuy := hasQuoteBalance && quoteBalance.Available > s.Quantity.Mul(midPrice) && (maxExposurePosition > 0 && base < maxExposurePosition)
|
||||
canSell := hasBaseBalance && baseBalance.Available > s.Quantity && (maxExposurePosition > 0 && base > -maxExposurePosition)
|
||||
|
||||
if s.ShadowProtection && kline != nil {
|
||||
|
||||
switch kline.Direction() {
|
||||
case types.DirectionDown:
|
||||
shadowHeight := kline.GetLowerShadowHeight()
|
||||
|
@ -352,26 +374,6 @@ func (s *Strategy) placeOrders(ctx context.Context, orderExecutor bbgo.OrderExec
|
|||
}
|
||||
}
|
||||
|
||||
// adjust quantity for closing position if we over sold or over bought
|
||||
if s.MaxExposurePosition > 0 && base.Abs() > s.MaxExposurePosition {
|
||||
scale := &bbgo.ExponentialScale{
|
||||
Domain: [2]float64{0, s.MaxExposurePosition.Float64()},
|
||||
Range: [2]float64{quantity.Float64(), base.Abs().Float64()},
|
||||
}
|
||||
if err := scale.Solve(); err != nil {
|
||||
log.WithError(err).Errorf("scale solving error")
|
||||
return
|
||||
}
|
||||
|
||||
qf := scale.Call(base.Abs().Float64())
|
||||
_ = qf
|
||||
if base > minQuantity {
|
||||
// sellOrder.Quantity = qf
|
||||
} else if base < -minQuantity {
|
||||
// buyOrder.Quantity = qf
|
||||
}
|
||||
}
|
||||
|
||||
if midPrice.Float64() > s.neutralBoll.LastDownBand() && midPrice.Float64() < s.neutralBoll.LastUpBand() {
|
||||
// we don't have position yet
|
||||
// place orders on both side if it's in oscillating band
|
||||
|
@ -587,3 +589,15 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
|
|||
|
||||
return nil
|
||||
}
|
||||
|
||||
func calculateBandPercentage(up, down, sma, midPrice float64) float64 {
|
||||
if midPrice < sma {
|
||||
// should be negative percentage
|
||||
return (midPrice - sma) / math.Abs(sma-down)
|
||||
} else if midPrice > sma {
|
||||
// should be positive percentage
|
||||
return (midPrice - sma) / math.Abs(up-sma)
|
||||
}
|
||||
|
||||
return 0.0
|
||||
}
|
||||
|
|
69
pkg/strategy/bollmaker/strategy_test.go
Normal file
69
pkg/strategy/bollmaker/strategy_test.go
Normal file
|
@ -0,0 +1,69 @@
|
|||
package bollmaker
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
)
|
||||
|
||||
func Test_calculateBandPercentage(t *testing.T) {
|
||||
type args struct {
|
||||
up float64
|
||||
down float64
|
||||
sma float64
|
||||
midPrice float64
|
||||
}
|
||||
tests := []struct {
|
||||
name string
|
||||
args args
|
||||
want fixedpoint.Value
|
||||
}{
|
||||
{
|
||||
name: "positive boundary",
|
||||
args: args{
|
||||
up: 2000.0,
|
||||
sma: 1500.0,
|
||||
down: 1000.0,
|
||||
midPrice: 2000.0,
|
||||
},
|
||||
want: fixedpoint.NewFromFloat(1.0),
|
||||
},
|
||||
{
|
||||
name: "inside positive boundary",
|
||||
args: args{
|
||||
up: 2000.0,
|
||||
sma: 1500.0,
|
||||
down: 1000.0,
|
||||
midPrice: 1600.0,
|
||||
},
|
||||
want: fixedpoint.NewFromFloat(0.2), // 20%
|
||||
},
|
||||
{
|
||||
name: "negative boundary",
|
||||
args: args{
|
||||
up: 2000.0,
|
||||
sma: 1500.0,
|
||||
down: 1000.0,
|
||||
midPrice: 1000.0,
|
||||
},
|
||||
want: fixedpoint.NewFromFloat(-1.0),
|
||||
},
|
||||
{
|
||||
name: "out of negative boundary",
|
||||
args: args{
|
||||
up: 2000.0,
|
||||
sma: 1500.0,
|
||||
down: 1000.0,
|
||||
midPrice: 800.0,
|
||||
},
|
||||
want: fixedpoint.NewFromFloat(-1.4),
|
||||
},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := calculateBandPercentage(tt.args.up, tt.args.down, tt.args.sma, tt.args.midPrice); fixedpoint.NewFromFloat(got) != tt.want {
|
||||
t.Errorf("calculateBandPercentage() = %v, want %v", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user