diff --git a/config/linregmaker.yaml b/config/linregmaker.yaml index 63c1a224e..80d5b1f5b 100644 --- a/config/linregmaker.yaml +++ b/config/linregmaker.yaml @@ -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: [ 10.0, 1.0 ] + range: [ 1.0, 1.0 ] # quantity is the base order quantity for your buy/sell order. quantity: 0.1 diff --git a/pkg/dynamicmetric/bollsetting.go b/pkg/dynamicmetric/bollsetting.go deleted file mode 100644 index 79bff4ef1..000000000 --- a/pkg/dynamicmetric/bollsetting.go +++ /dev/null @@ -1,9 +0,0 @@ -package dynamicmetric - -import "github.com/c9s/bbgo/pkg/types" - -// BollingerSetting is for Bollinger Band settings -type BollingerSetting struct { - types.IntervalWindow - BandWidth float64 `json:"bandWidth"` -} diff --git a/pkg/dynamicmetric/dynamic_spread.go b/pkg/dynamicmetric/dynamic_spread.go index 6c0391c33..905f49bc3 100644 --- a/pkg/dynamicmetric/dynamic_spread.go +++ b/pkg/dynamicmetric/dynamic_spread.go @@ -16,18 +16,6 @@ type DynamicSpread struct { // WeightedBollWidthRatioSpread calculates spreads based on two Bollinger Bands WeightedBollWidthRatioSpread *DynamicSpreadBollWidthRatio `json:"weightedBollWidth"` - - // deprecated - Enabled *bool `json:"enabled"` - - // deprecated - types.IntervalWindow - - // deprecated. AskSpreadScale is used to define the ask spread range with the given percentage. - AskSpreadScale *bbgo.PercentageScale `json:"askSpreadScale"` - - // deprecated. BidSpreadScale is used to define the bid spread range with the given percentage. - BidSpreadScale *bbgo.PercentageScale `json:"bidSpreadScale"` } // Initialize dynamic spread @@ -37,14 +25,6 @@ func (ds *DynamicSpread) Initialize(symbol string, session *bbgo.ExchangeSession ds.AmpSpread.initialize(symbol, session) case ds.WeightedBollWidthRatioSpread != nil: ds.WeightedBollWidthRatioSpread.initialize(symbol, session) - case ds.Enabled != nil && *ds.Enabled: - // backward compatibility - ds.AmpSpread = &DynamicSpreadAmp{ - IntervalWindow: ds.IntervalWindow, - AskSpreadScale: ds.AskSpreadScale, - BidSpreadScale: ds.BidSpreadScale, - } - ds.AmpSpread.initialize(symbol, session) } } @@ -171,8 +151,8 @@ type DynamicSpreadBollWidthRatio struct { // A positive number. The greater factor, the sharper weighting function. Default set to 1.0 . Sensitivity float64 `json:"sensitivity"` - DefaultBollinger *BollingerSetting `json:"defaultBollinger"` - NeutralBollinger *BollingerSetting `json:"neutralBollinger"` + DefaultBollinger types.IntervalWindowBandWidth `json:"defaultBollinger"` + NeutralBollinger types.IntervalWindowBandWidth `json:"neutralBollinger"` neutralBoll *indicator.BOLL defaultBoll *indicator.BOLL @@ -232,7 +212,7 @@ func (ds *DynamicSpreadBollWidthRatio) getWeightedBBWidthRatio(positiveSigmoid b // - To bid spread, the weighting density function d_weight(x) is sigmoid((default_BB_mid - x) / (w / alpha)) // - The higher sensitivity factor alpha, the sharper weighting function. // - // Then calculate the weighted band width ratio by taking integral of d_weight(x) from neutral_BB_lower to neutral_BB_upper: + // Then calculate the weighted bandwidth ratio by taking integral of d_weight(x) from neutral_BB_lower to neutral_BB_upper: // infinite integral of ask spread sigmoid weighting density function F(x) = (w / alpha) * ln(exp(x / (w / alpha)) + exp(default_BB_mid / (w / alpha))) // infinite integral of bid spread sigmoid weighting density function F(x) = x - (w / alpha) * ln(exp(x / (w / alpha)) + exp(default_BB_mid / (w / alpha))) // Note that we've rescaled the sigmoid function to fit default BB, diff --git a/pkg/strategy/linregmaker/strategy.go b/pkg/strategy/linregmaker/strategy.go index 0d84ba031..5e4ba99e6 100644 --- a/pkg/strategy/linregmaker/strategy.go +++ b/pkg/strategy/linregmaker/strategy.go @@ -25,17 +25,12 @@ var two = fixedpoint.NewFromInt(2) var log = logrus.WithField("strategy", ID) //TODO: Logic for backtest +// TODO: Dynamic exposure should work on both side func init() { bbgo.RegisterStrategy(ID, &Strategy{}) } -// TODO: Remove BollingerSetting and bollsetting.go -type BollingerSetting struct { - types.IntervalWindow - BandWidth float64 `json:"bandWidth"` -} - type Strategy struct { Environment *bbgo.Environment StandardIndicatorSet *bbgo.StandardIndicatorSet @@ -77,7 +72,10 @@ type Strategy struct { // NeutralBollinger is the smaller range of the bollinger band // If price is in this band, it usually means the price is oscillating. // If price goes out of this band, we tend to not place sell orders or buy orders - NeutralBollinger *BollingerSetting `json:"neutralBollinger"` + NeutralBollinger types.IntervalWindowBandWidth `json:"neutralBollinger"` + + // neutralBoll is the neutral price section for TradeInBand + neutralBoll *indicator.BOLL // TradeInBand // When this is on, places orders only when the current price is in the bollinger band. @@ -113,7 +111,7 @@ type Strategy struct { DynamicExposure dynamicmetric.DynamicExposure `json:"dynamicExposure"` bbgo.QuantityOrAmount - // TODO: Should work w/o dynamic qty + // DynamicQuantityIncrease calculates the increase position order quantity dynamically DynamicQuantityIncrease dynamicmetric.DynamicQuantitySet `json:"dynamicQuantityIncrease"` @@ -134,9 +132,6 @@ type Strategy struct { groupID uint32 - // neutralBoll is the neutral price section - neutralBoll *indicator.BOLL - // StrategyController bbgo.StrategyController } @@ -176,7 +171,7 @@ func (s *Strategy) Subscribe(session *bbgo.ExchangeSession) { } // Subscribe for BBs - if s.NeutralBollinger != nil && s.NeutralBollinger.Interval != "" { + if s.NeutralBollinger.Interval != "" { session.Subscribe(types.KLineChannel, s.Symbol, types.SubscribeOptions{ Interval: s.NeutralBollinger.Interval, }) @@ -276,39 +271,38 @@ func (s *Strategy) getOrderPrices(midPrice fixedpoint.Value) (askPrice fixedpoin func (s *Strategy) getOrderQuantities(askPrice fixedpoint.Value, bidPrice fixedpoint.Value) (sellQuantity fixedpoint.Value, buyQuantity fixedpoint.Value) { // TODO: spot, margin, and futures + // Default + sellQuantity = s.QuantityOrAmount.CalculateQuantity(askPrice) + buyQuantity = s.QuantityOrAmount.CalculateQuantity(bidPrice) + // Dynamic qty switch { case s.mainTrendCurrent == types.DirectionUp: - var err error if len(s.DynamicQuantityIncrease) > 0 { - buyQuantity, err = s.DynamicQuantityIncrease.GetQuantity() - if err != nil { - buyQuantity = s.QuantityOrAmount.CalculateQuantity(bidPrice) + qty, err := s.DynamicQuantityIncrease.GetQuantity() + if err == nil { + buyQuantity = qty } } if len(s.DynamicQuantityDecrease) > 0 { - sellQuantity, err = s.DynamicQuantityDecrease.GetQuantity() - if err != nil { - sellQuantity = s.QuantityOrAmount.CalculateQuantity(askPrice) + qty, err := s.DynamicQuantityDecrease.GetQuantity() + if err == nil { + sellQuantity = qty } } case s.mainTrendCurrent == types.DirectionDown: - var err error if len(s.DynamicQuantityIncrease) > 0 { - sellQuantity, err = s.DynamicQuantityIncrease.GetQuantity() - if err != nil { - sellQuantity = s.QuantityOrAmount.CalculateQuantity(bidPrice) + qty, err := s.DynamicQuantityIncrease.GetQuantity() + if err == nil { + sellQuantity = qty } } if len(s.DynamicQuantityDecrease) > 0 { - buyQuantity, err = s.DynamicQuantityDecrease.GetQuantity() - if err != nil { - buyQuantity = s.QuantityOrAmount.CalculateQuantity(askPrice) + qty, err := s.DynamicQuantityDecrease.GetQuantity() + if err == nil { + buyQuantity = qty } } - default: - sellQuantity = s.QuantityOrAmount.CalculateQuantity(askPrice) - buyQuantity = s.QuantityOrAmount.CalculateQuantity(bidPrice) } // Faster position decrease