Skip to content

Commit a37bea8

Browse files
authored
Merge pull request #2604 from c9s/dboy/xfundingv2/revise-metrics
FIX: [xfundingv2] revise round prometheus metrics
2 parents fd901c5 + 19031e2 commit a37bea8

5 files changed

Lines changed: 150 additions & 112 deletions

File tree

pkg/strategy/xfundingv2/market_selector.go

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@ import (
77
"github.com/c9s/bbgo/pkg/exchange/binance/binanceapi"
88
"github.com/c9s/bbgo/pkg/fixedpoint"
99
"github.com/c9s/bbgo/pkg/types"
10-
"github.com/prometheus/client_golang/prometheus"
1110
"github.com/sirupsen/logrus"
1211
)
1312

@@ -184,11 +183,6 @@ func (s *MarketSelector) SelectMarkets(ctx context.Context, symbols []string) ([
184183
annualized := AnnualizedRate(idx.LastFundingRate, info.FundingIntervalHours)
185184
numActiveRounds := fixedpoint.NewFromInt(int64(len(s.activeRounds)))
186185
requiredAnnualizedRate := s.MinAnnualizedRate.Add(s.AnnualizedRateStep.Mul(numActiveRounds))
187-
labels := prometheus.Labels{
188-
"symbol": idx.Symbol,
189-
}
190-
annualizedFundingRateMetrics.With(labels).Set(annualized.Float64())
191-
fundingRateMetrics.With(labels).Set(idx.LastFundingRate.Float64())
192186

193187
if annualized.Abs().Compare(requiredAnnualizedRate) < 0 {
194188
continue

pkg/strategy/xfundingv2/metrics.go

Lines changed: 4 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -24,26 +24,10 @@ var annualizedFundingRateMetrics = promauto.NewGaugeVec(
2424
[]string{"symbol"},
2525
)
2626

27-
var roundAnnualizedTriggerRateMetrics = promauto.NewGaugeVec(
27+
var roundTotalPnLMetrics = promauto.NewGaugeVec(
2828
prometheus.GaugeOpts{
29-
Name: "xfundingv2_round_annualized_trigger_rate",
30-
Help: "Annualized triggering funding rate of the arbitrage round",
31-
},
32-
[]string{"strategy_id", "symbol"},
33-
)
34-
35-
var roundHoldingIntervalMetrics = promauto.NewGaugeVec(
36-
prometheus.GaugeOpts{
37-
Name: "xfundingv2_round_holding_interval",
38-
Help: "Holding interval of the arbitrage round in seconds",
39-
},
40-
[]string{"strategy_id", "symbol"},
41-
)
42-
43-
var roundNetPnLMetrics = promauto.NewGaugeVec(
44-
prometheus.GaugeOpts{
45-
Name: "xfundingv2_round_net_pnl",
46-
Help: "Net PnL of the arbitrage round",
29+
Name: "xfundingv2_round_total_pnl",
30+
Help: "Total PnL of the arbitrage round",
4731
},
4832
[]string{"strategy_id", "symbol"},
4933
)
@@ -59,7 +43,7 @@ var roundPositionFilledRatioMetrics = promauto.NewGaugeVec(
5943
var roundPositionMetrics = promauto.NewGaugeVec(
6044
prometheus.GaugeOpts{
6145
Name: "xfundingv2_round_position",
62-
Help: "Spot position of the arbitrage round",
46+
Help: "position of the arbitrage round",
6347
},
6448
[]string{"strategy_id", "symbol", "accountType"},
6549
)

pkg/strategy/xfundingv2/round.go

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88
"time"
99

1010
"github.com/google/uuid"
11+
"github.com/prometheus/client_golang/prometheus"
1112
"github.com/sirupsen/logrus"
1213
"github.com/slack-go/slack"
1314

@@ -57,6 +58,7 @@ type ArbitrageRound struct {
5758
lastRebalanceTime time.Time
5859
rebalanceInterval time.Duration
5960

61+
lastFundingRate fixedpoint.Value
6062
lastFundingIncomeSyncTime time.Time
6163

6264
futuresService FuturesService
@@ -65,6 +67,14 @@ type ArbitrageRound struct {
6567
spotSession, futuresSession *bbgo.ExchangeSession
6668
retryTransferTickC chan time.Time
6769

70+
// metrics
71+
fundingRateMetric prometheus.Gauge
72+
annualizedFundingRateMetric prometheus.Gauge
73+
totalPnLMetric prometheus.Gauge
74+
spotPositionMetric, futuresPositionMetric prometheus.Gauge
75+
spotFilledRatioMetric, futuresFilledRatioMetric prometheus.Gauge
76+
quantityDeviationMetric prometheus.Gauge
77+
6878
logger logrus.FieldLogger
6979
slackAlert slackalert.SlackAlert
7080
}
@@ -115,6 +125,100 @@ func NewArbitrageRound(
115125
}
116126
}
117127

128+
func (r *ArbitrageRound) SetupMetrics(s *Strategy) {
129+
id := s.InstanceID()
130+
symbol := r.SpotSymbol()
131+
132+
r.fundingRateMetric = fundingRateMetrics.With(
133+
prometheus.Labels{
134+
"symbol": symbol,
135+
},
136+
)
137+
r.annualizedFundingRateMetric = annualizedFundingRateMetrics.With(
138+
prometheus.Labels{
139+
"symbol": symbol,
140+
},
141+
)
142+
143+
r.totalPnLMetric = roundTotalPnLMetrics.With(
144+
prometheus.Labels{
145+
"strategy_id": id,
146+
"symbol": symbol,
147+
},
148+
)
149+
150+
r.spotPositionMetric = roundPositionMetrics.With(
151+
prometheus.Labels{
152+
"strategy_id": id,
153+
"symbol": symbol,
154+
"accountType": "spot",
155+
},
156+
)
157+
r.futuresPositionMetric = roundPositionMetrics.With(
158+
prometheus.Labels{
159+
"strategy_id": id,
160+
"symbol": symbol,
161+
"accountType": "futures",
162+
},
163+
)
164+
r.spotFilledRatioMetric = roundPositionFilledRatioMetrics.With(
165+
prometheus.Labels{
166+
"strategy_id": id,
167+
"symbol": symbol,
168+
"accountType": "spot",
169+
},
170+
)
171+
r.futuresFilledRatioMetric = roundPositionFilledRatioMetrics.With(
172+
prometheus.Labels{
173+
"strategy_id": id,
174+
"symbol": symbol,
175+
"accountType": "futures",
176+
},
177+
)
178+
179+
r.quantityDeviationMetric = roundQuantityDeviationMetrics.With(
180+
prometheus.Labels{
181+
"strategy_id": id,
182+
"symbol": symbol,
183+
},
184+
)
185+
}
186+
187+
func (r *ArbitrageRound) RecordMetrics(posDeviation PositionDeviation, spotPrice, futuresPrice fixedpoint.Value) {
188+
if r.totalPnLMetric != nil {
189+
unrealizedPnL := r.UnrealizedPnL(spotPrice, futuresPrice)
190+
r.totalPnLMetric.Set(unrealizedPnL.TotalPnL().Float64())
191+
}
192+
193+
if !r.lastFundingRate.IsZero() && r.fundingRateMetric != nil && r.annualizedFundingRateMetric != nil {
194+
annualizedRate := AnnualizedRate(r.lastFundingRate, r.syncState.FundingIntervalHours)
195+
r.fundingRateMetric.Set(r.lastFundingRate.Float64())
196+
r.annualizedFundingRateMetric.Set(annualizedRate.Float64())
197+
}
198+
199+
if r.spotPositionMetric != nil && r.futuresPositionMetric != nil {
200+
r.spotPositionMetric.Set(posDeviation.SpotFilled.Float64())
201+
r.futuresPositionMetric.Set(posDeviation.FuturesFilled.Float64())
202+
}
203+
204+
if r.spotFilledRatioMetric != nil && r.futuresFilledRatioMetric != nil {
205+
spotFilledPosition := r.SpotWorker().FilledPosition()
206+
spotFilledRatio := spotFilledPosition.Div(r.TriggeredTargetPosition()).Abs()
207+
futuresFilledPosition := r.FuturesWorker().FilledPosition()
208+
futuresFilledRatio := futuresFilledPosition.Div(r.TriggeredTargetPosition()).Abs()
209+
if r.State() == RoundClosing {
210+
spotFilledRatio = fixedpoint.One.Sub(spotFilledRatio)
211+
futuresFilledRatio = fixedpoint.One.Sub(futuresFilledRatio)
212+
}
213+
r.spotFilledRatioMetric.Set(spotFilledRatio.Float64())
214+
r.futuresFilledRatioMetric.Set(futuresFilledRatio.Float64())
215+
}
216+
217+
if r.quantityDeviationMetric != nil {
218+
r.quantityDeviationMetric.Set(posDeviation.DeviatedQuantity.Float64())
219+
}
220+
}
221+
118222
func (r *ArbitrageRound) Halt(currentTime time.Time) {
119223
r.mu.Lock()
120224
defer r.mu.Unlock()
@@ -192,6 +296,13 @@ func (r *ArbitrageRound) FuturesFeeAssetAmount() fixedpoint.Value {
192296
return r.syncState.FuturesFeeAssetAmount
193297
}
194298

299+
func (r *ArbitrageRound) SetLastFundingRate(rate fixedpoint.Value) {
300+
r.mu.Lock()
301+
defer r.mu.Unlock()
302+
303+
r.lastFundingRate = rate
304+
}
305+
195306
// RequiredFeeAssetAmount returns the required fee asset amount for the round based on its current state and position.
196307
// The first return value is for the spot leg and the second return value is for the futures leg.
197308
func (r *ArbitrageRound) RequiredFeeAssetAmounts() (fixedpoint.Value, fixedpoint.Value) {

pkg/strategy/xfundingv2/round_sync.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ import (
1313

1414
func (r *ArbitrageRound) Initialize(ctx context.Context, s *Strategy) error {
1515
r.SetLogger(s.logger)
16+
r.SetupMetrics(s)
1617
if s.futuresSession.Exchange.Name() != r.syncState.FuturesExchangeName {
1718
return fmt.Errorf("[ArbitrageRound] futures exchange name mismatch: expected %s, got %s",
1819
r.syncState.FuturesExchangeName, s.futuresSession.Exchange.Name())

0 commit comments

Comments
 (0)