diff --git a/pkg/strategy/xmaker/metrics.go b/pkg/strategy/xmaker/metrics.go index b61c6fc85..a05743d19 100644 --- a/pkg/strategy/xmaker/metrics.go +++ b/pkg/strategy/xmaker/metrics.go @@ -26,18 +26,53 @@ var makerBestAskPriceMetrics = prometheus.NewGaugeVec( Help: "", }, []string{"strategy_type", "strategy_id", "exchange", "symbol"}) -var numOfLayersMetrics = prometheus.NewGaugeVec( +var bidMarginMetrics = prometheus.NewGaugeVec( prometheus.GaugeOpts{ - Name: "xmaker_num_of_layers", - Help: "", + Name: "xmaker_bid_margin", + Help: "the current bid margin (dynamic)", }, []string{"strategy_type", "strategy_id", "exchange", "symbol"}) +var askMarginMetrics = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "xmaker_ask_margin", + Help: "the current ask margin (dynamic)", + }, []string{"strategy_type", "strategy_id", "exchange", "symbol"}) + +var configNumOfLayersMetrics = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "xmaker_config_num_of_layers", + Help: "", + }, []string{"strategy_type", "strategy_id", "symbol"}) + +var configMaxExposureMetrics = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "xmaker_config_max_exposure", + Help: "", + }, []string{"strategy_type", "strategy_id", "symbol"}) + +var configBidMarginMetrics = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "xmaker_config_bid_margin", + Help: "", + }, []string{"strategy_type", "strategy_id", "symbol"}) + +var configAskMarginMetrics = prometheus.NewGaugeVec( + prometheus.GaugeOpts{ + Name: "xmaker_config_ask_margin", + Help: "", + }, []string{"strategy_type", "strategy_id", "symbol"}) + func init() { prometheus.MustRegister( openOrderBidExposureInUsdMetrics, openOrderAskExposureInUsdMetrics, makerBestBidPriceMetrics, makerBestAskPriceMetrics, - numOfLayersMetrics, + bidMarginMetrics, + askMarginMetrics, + configNumOfLayersMetrics, + configMaxExposureMetrics, + configBidMarginMetrics, + configAskMarginMetrics, ) } diff --git a/pkg/strategy/xmaker/strategy.go b/pkg/strategy/xmaker/strategy.go index b8b8c5c8e..6354bedc3 100644 --- a/pkg/strategy/xmaker/strategy.go +++ b/pkg/strategy/xmaker/strategy.go @@ -401,9 +401,12 @@ func (s *Strategy) updateQuote(ctx context.Context) { bidExposureInUsd := fixedpoint.Zero askExposureInUsd := fixedpoint.Zero - bidPrice := bestBidPrice askPrice := bestAskPrice + + bidMarginMetrics.With(labels).Set(bidMargin.Float64()) + askMarginMetrics.With(labels).Set(askMargin.Float64()) + for i := 0; i < s.NumLayers; i++ { // for maker bid orders if !disableMakerBid { @@ -430,13 +433,13 @@ func (s *Strategy) updateQuote(ctx context.Context) { } bidPrice = bidPrice.Mul(fixedpoint.One.Sub(bidMargin)) - if i > 0 && pips.Sign() > 0 { + if i == 0 { + makerBestBidPriceMetrics.With(labels).Set(bidPrice.Float64()) + } else if i > 0 && pips.Sign() > 0 { bidPrice = bidPrice.Sub(pips.Mul(fixedpoint.NewFromInt(int64(i)). Mul(s.makerMarket.TickSize))) } - makerBestBidPriceMetrics.With(labels).Set(bidPrice.Float64()) - if makerQuota.QuoteAsset.Lock(bidQuantity.Mul(bidPrice)) && hedgeQuota.BaseAsset.Lock(bidQuantity) { // if we bought, then we need to sell the base from the hedge session submitOrders = append(submitOrders, types.SubmitOrder{ @@ -487,12 +490,12 @@ func (s *Strategy) updateQuote(ctx context.Context) { } askPrice = askPrice.Mul(fixedpoint.One.Add(askMargin)) - if i > 0 && pips.Sign() > 0 { + if i == 0 { + makerBestAskPriceMetrics.With(labels).Set(askPrice.Float64()) + } else if i > 0 && pips.Sign() > 0 { askPrice = askPrice.Add(pips.Mul(fixedpoint.NewFromInt(int64(i)).Mul(s.makerMarket.TickSize))) } - makerBestAskPriceMetrics.With(labels).Set(askPrice.Float64()) - if makerQuota.BaseAsset.Lock(askQuantity) && hedgeQuota.QuoteAsset.Lock(askQuantity.Mul(askPrice)) { // if we bought, then we need to sell the base from the hedge session @@ -753,6 +756,7 @@ func (s *Strategy) Defaults() error { // circuitBreakerAlertLimiter is for CircuitBreaker alerts s.circuitBreakerAlertLimiter = rate.NewLimiter(rate.Every(3*time.Minute), 2) s.reportProfitStatsRateLimiter = rate.NewLimiter(rate.Every(5*time.Minute), 1) + s.hedgeErrorLimiter = rate.NewLimiter(rate.Every(1*time.Minute), 1) return nil } @@ -773,8 +777,8 @@ func (s *Strategy) Validate() error { } func (s *Strategy) quoteWorker(ctx context.Context) { - quoteTicker := time.NewTicker(util.MillisecondsJitter(s.UpdateInterval.Duration(), 200)) - defer quoteTicker.Stop() + ticker := time.NewTicker(util.MillisecondsJitter(s.UpdateInterval.Duration(), 200)) + defer ticker.Stop() defer func() { if err := s.activeMakerOrders.GracefulCancel(context.Background(), s.makerSession.Exchange); err != nil { @@ -793,7 +797,7 @@ func (s *Strategy) quoteWorker(ctx context.Context) { log.Warnf("%s maker goroutine stopped, due to the cancelled context", s.Symbol) return - case <-quoteTicker.C: + case <-ticker.C: s.updateQuote(ctx) } @@ -848,7 +852,7 @@ func (s *Strategy) CrossRun( ctx context.Context, orderExecutionRouter bbgo.OrderExecutionRouter, sessions map[string]*bbgo.ExchangeSession, ) error { - s.hedgeErrorLimiter = rate.NewLimiter(rate.Every(1*time.Minute), 1) + instanceID := s.InstanceID() // configure sessions sourceSession, ok := sessions[s.SourceExchange] @@ -880,9 +884,6 @@ func (s *Strategy) CrossRun( } indicators := s.sourceSession.Indicators(s.Symbol) - if !ok { - return fmt.Errorf("%s standard indicator set not found", s.Symbol) - } s.boll = indicators.BOLL(types.IntervalWindow{ Interval: s.BollBandInterval, @@ -890,10 +891,15 @@ func (s *Strategy) CrossRun( }, 1.0) // restore state - instanceID := s.InstanceID() s.groupID = util.FNV32(instanceID) log.Infof("using group id %d from fnv(%s)", s.groupID, instanceID) + configLabels := prometheus.Labels{"strategy_id": s.InstanceID(), "strategy_type": ID, "symbol": s.Symbol} + configNumOfLayersMetrics.With(configLabels).Set(float64(s.NumLayers)) + configMaxExposureMetrics.With(configLabels).Set(s.MaxExposurePosition.Float64()) + configBidMarginMetrics.With(configLabels).Set(s.BidMargin.Float64()) + configAskMarginMetrics.With(configLabels).Set(s.AskMargin.Float64()) + if s.Position == nil { s.Position = types.NewPositionFromMarket(s.makerMarket) s.Position.Strategy = ID @@ -1037,8 +1043,12 @@ func (s *Strategy) CrossRun( go s.quoteWorker(ctx) bbgo.OnShutdown(ctx, func(ctx context.Context, wg *sync.WaitGroup) { + // the ctx here is the shutdown context (not the strategy context) + + // defer work group done to mark the strategy as stopped defer wg.Done() + // send stop signal to the quoteWorker close(s.stopC) // wait for the quoter to stop @@ -1048,7 +1058,7 @@ func (s *Strategy) CrossRun( log.WithError(err).Errorf("graceful cancel error") } - bbgo.Notify("%s: %s position", ID, s.Symbol, s.Position) + bbgo.Notify("Shutting down %s %s", ID, s.Symbol, s.Position) }) return nil