mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-10 09:11:55 +00:00
strategy/linregmaker: dynamic exposure works on both direction
This commit is contained in:
parent
fbc949a133
commit
0f0549fa42
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue
Block a user