strategy/linregmaker: dynamic exposure works on both direction

This commit is contained in:
Andy Cheng 2022-11-23 17:23:18 +08:00
parent fbc949a133
commit 0f0549fa42
3 changed files with 15 additions and 14 deletions

View File

@ -110,7 +110,7 @@ exchangeStrategies:
domain: [ -1, 1 ]
# when in down band, holds 1.0 by maximum
# when in up band, holds 0.05 by maximum
range: [ 1.0, 1.0 ]
range: [ 0.1, 10 ]
# quantity is the base order quantity for your buy/sell order.
quantity: 0.1

View File

@ -28,10 +28,10 @@ func (d *DynamicExposure) IsEnabled() bool {
}
// GetMaxExposure returns the max exposure
func (d *DynamicExposure) GetMaxExposure(price float64) (maxExposure fixedpoint.Value, err error) {
func (d *DynamicExposure) GetMaxExposure(price float64, trend types.Direction) (maxExposure fixedpoint.Value, err error) {
switch {
case d.BollBandExposure != nil:
return d.BollBandExposure.getMaxExposure(price)
return d.BollBandExposure.getMaxExposure(price, trend)
default:
return fixedpoint.Zero, errors.New("dynamic exposure is not enabled")
}
@ -58,7 +58,7 @@ func (d *DynamicExposureBollBand) initialize(symbol string, session *bbgo.Exchan
}
// getMaxExposure returns the max exposure
func (d *DynamicExposureBollBand) getMaxExposure(price float64) (fixedpoint.Value, error) {
func (d *DynamicExposureBollBand) getMaxExposure(price float64, trend types.Direction) (fixedpoint.Value, error) {
downBand := d.dynamicExposureBollBand.DownBand.Last()
upBand := d.dynamicExposureBollBand.UpBand.Last()
sma := d.dynamicExposureBollBand.SMA.Last()
@ -73,6 +73,11 @@ func (d *DynamicExposureBollBand) getMaxExposure(price float64) (fixedpoint.Valu
bandPercentage = (price - sma) / math.Abs(upBand-sma)
}
// Reverse if downtrend
if trend == types.DirectionDown {
bandPercentage = 0 - bandPercentage
}
v, err := d.DynamicExposureBollBandScale.Scale(bandPercentage)
if err != nil {
return fixedpoint.Zero, err

View File

@ -24,8 +24,7 @@ var two = fixedpoint.NewFromInt(2)
var log = logrus.WithField("strategy", ID)
//TODO: Logic for backtest
// TODO: Dynamic exposure should work on both side
// TODO: Logic for backtest
func init() {
bbgo.RegisterStrategy(ID, &Strategy{})
@ -81,7 +80,7 @@ type Strategy struct {
// When this is on, places orders only when the current price is in the bollinger band.
TradeInBand bool `json:"tradeInBand"`
// useTickerPrice use the ticker api to get the mid price instead of the closed kline price.
// useTickerPrice use the ticker api to get the mid-price instead of the closed kline price.
// The back-test engine is kline-based, so the ticker price api is not supported.
// Turn this on if you want to do real trading.
useTickerPrice bool
@ -146,7 +145,8 @@ func (s *Strategy) InstanceID() string {
return fmt.Sprintf("%s:%s", ID, s.Symbol)
}
// Validate basic config parameters. TODO LATER: Validate more
// Validate basic config parameters
// TODO LATER: Validate more
func (s *Strategy) Validate() error {
if len(s.Symbol) == 0 {
return errors.New("symbol is required")
@ -156,10 +156,6 @@ func (s *Strategy) Validate() error {
return errors.New("interval is required")
}
if s.Window <= 0 {
return errors.New("window must be more than 0")
}
if s.ReverseEMA == nil {
return errors.New("reverseEMA must be set")
}
@ -270,7 +266,7 @@ func (s *Strategy) updateMaxExposure(midPrice fixedpoint.Value) {
// Calculate max exposure
if s.DynamicExposure.IsEnabled() {
var err error
maxExposurePosition, err := s.DynamicExposure.GetMaxExposure(midPrice.Float64())
maxExposurePosition, err := s.DynamicExposure.GetMaxExposure(midPrice.Float64(), s.mainTrendCurrent)
if err != nil {
log.WithError(err).Errorf("can not calculate DynamicExposure of %s, use previous MaxExposurePosition instead", s.Symbol)
} else {
@ -560,7 +556,7 @@ func (s *Strategy) Run(ctx context.Context, orderExecutor bbgo.OrderExecutor, se
return nil
}
// TODO adjustOrderQuantity()
// adjustOrderQuantity to meet the min notional and qty requirement
func adjustOrderQuantity(submitOrder types.SubmitOrder, market types.Market) types.SubmitOrder {
if submitOrder.Quantity.Mul(submitOrder.Price).Compare(market.MinNotional) < 0 {
submitOrder.Quantity = bbgo.AdjustFloatQuantityByMinAmount(submitOrder.Quantity, submitOrder.Price, market.MinNotional.Mul(notionModifier))