Compare commits

...

4 Commits

Author SHA1 Message Date
c9s
294e529a98
xmaker: add more logs 2024-09-02 16:08:51 +08:00
c9s
f30aca1b5a
xmaker: update position metrics when restored 2024-09-02 15:51:31 +08:00
c9s
f9b9832fff
add more logs 2024-09-02 15:51:31 +08:00
c9s
2bf1072977
Merge pull request #1725 from c9s/c9s/xmaker/stb-improvements
IMPROVE: [xmaker] improve hedge margin account leverage calculation
2024-09-02 15:29:53 +08:00
2 changed files with 29 additions and 7 deletions

View File

@ -426,10 +426,10 @@ func (s *Strategy) updateQuote(ctx context.Context) {
if s.CircuitBreaker != nil { if s.CircuitBreaker != nil {
now := time.Now() now := time.Now()
if reason, halted := s.CircuitBreaker.IsHalted(now); halted { if reason, halted := s.CircuitBreaker.IsHalted(now); halted {
s.logger.Warnf("[arbWorker] strategy is halted, reason: %s", reason) s.logger.Warnf("strategy %s is halted, reason: %s", ID, reason)
if s.circuitBreakerAlertLimiter.AllowN(now, 1) { if s.circuitBreakerAlertLimiter.AllowN(now, 1) {
bbgo.Notify("Strategy is halted, reason: %s", reason) bbgo.Notify("Strategy %s is halted, reason: %s", ID, reason)
} }
return return
@ -438,6 +438,7 @@ func (s *Strategy) updateQuote(ctx context.Context) {
bestBid, bestAsk, hasPrice := s.book.BestBidAndAsk() bestBid, bestAsk, hasPrice := s.book.BestBidAndAsk()
if !hasPrice { if !hasPrice {
s.logger.Warnf("no valid price, skip quoting")
return return
} }
@ -474,15 +475,21 @@ func (s *Strategy) updateQuote(ctx context.Context) {
// check maker's balance quota // check maker's balance quota
// we load the balances from the account while we're generating the orders, // we load the balances from the account while we're generating the orders,
// the balance may have a chance to be deducted by other strategies or manual orders submitted by the user // the balance may have a chance to be deducted by other strategies or manual orders submitted by the user
makerBalances := s.makerSession.GetAccount().Balances() makerBalances := s.makerSession.GetAccount().Balances().NotZero()
s.logger.Infof("maker balances: %+v", makerBalances)
makerQuota := &bbgo.QuotaTransaction{} makerQuota := &bbgo.QuotaTransaction{}
if b, ok := makerBalances[s.makerMarket.BaseCurrency]; ok { if b, ok := makerBalances[s.makerMarket.BaseCurrency]; ok {
if b.Available.Compare(s.makerMarket.MinQuantity) > 0 { if s.makerMarket.IsDustQuantity(b.Available, s.lastPrice) {
makerQuota.BaseAsset.Add(b.Available)
} else {
disableMakerAsk = true disableMakerAsk = true
s.logger.Infof("%s maker ask disabled: insufficient base balance %s", s.Symbol, b.String()) s.logger.Infof("%s maker ask disabled: insufficient base balance %s", s.Symbol, b.String())
} else {
makerQuota.BaseAsset.Add(b.Available)
} }
} else {
disableMakerAsk = true
s.logger.Infof("%s maker ask disabled: base balance %s not found", s.Symbol, b.String())
} }
if b, ok := makerBalances[s.makerMarket.QuoteCurrency]; ok { if b, ok := makerBalances[s.makerMarket.QuoteCurrency]; ok {
@ -492,6 +499,9 @@ func (s *Strategy) updateQuote(ctx context.Context) {
disableMakerBid = true disableMakerBid = true
s.logger.Infof("%s maker bid disabled: insufficient quote balance %s", s.Symbol, b.String()) s.logger.Infof("%s maker bid disabled: insufficient quote balance %s", s.Symbol, b.String())
} }
} else {
disableMakerBid = true
s.logger.Infof("%s maker bid disabled: quote balance %s not found", s.Symbol, b.String())
} }
// if // if
@ -511,6 +521,7 @@ func (s *Strategy) updateQuote(ctx context.Context) {
hedgeAccount.MarginLevel.String(), hedgeAccount.MarginLevel.String(),
s.MinMarginLevel.String()) s.MinMarginLevel.String())
// TODO: should consider base asset debt as well.
if quote, ok := hedgeAccount.Balance(s.sourceMarket.QuoteCurrency); ok { if quote, ok := hedgeAccount.Balance(s.sourceMarket.QuoteCurrency); ok {
quoteDebt := quote.Debt() quoteDebt := quote.Debt()
if quoteDebt.Sign() > 0 { if quoteDebt.Sign() > 0 {
@ -840,6 +851,7 @@ func (s *Strategy) updateQuote(ctx context.Context) {
createdOrders, errIdx, err := bbgo.BatchPlaceOrder(ctx, s.makerSession.Exchange, orderCreateCallback, formattedOrders...) createdOrders, errIdx, err := bbgo.BatchPlaceOrder(ctx, s.makerSession.Exchange, orderCreateCallback, formattedOrders...)
if err != nil { if err != nil {
log.WithError(err).Errorf("unable to place maker orders: %+v", formattedOrders) log.WithError(err).Errorf("unable to place maker orders: %+v", formattedOrders)
return
} }
openOrderBidExposureInUsdMetrics.With(s.metricsLabels).Set(bidExposureInUsd.Float64()) openOrderBidExposureInUsdMetrics.With(s.metricsLabels).Set(bidExposureInUsd.Float64())
@ -1240,7 +1252,7 @@ func (s *Strategy) CrossRun(
// restore state // restore state
s.groupID = util.FNV32(instanceID) s.groupID = util.FNV32(instanceID)
log.Infof("using group id %d from fnv(%s)", s.groupID, instanceID) s.logger.Infof("using group id %d from fnv(%s)", s.groupID, instanceID)
configLabels := prometheus.Labels{"strategy_id": s.InstanceID(), "strategy_type": ID, "symbol": s.Symbol} configLabels := prometheus.Labels{"strategy_id": s.InstanceID(), "strategy_type": ID, "symbol": s.Symbol}
configNumOfLayersMetrics.With(configLabels).Set(float64(s.NumLayers)) configNumOfLayersMetrics.With(configLabels).Set(float64(s.NumLayers))
@ -1252,8 +1264,12 @@ func (s *Strategy) CrossRun(
s.Position = types.NewPositionFromMarket(s.makerMarket) s.Position = types.NewPositionFromMarket(s.makerMarket)
s.Position.Strategy = ID s.Position.Strategy = ID
s.Position.StrategyInstanceID = instanceID s.Position.StrategyInstanceID = instanceID
} else {
s.Position.Strategy = ID
s.Position.StrategyInstanceID = instanceID
} }
s.Position.UpdateMetrics()
bbgo.Notify("xmaker: %s position is restored", s.Symbol, s.Position) bbgo.Notify("xmaker: %s position is restored", s.Symbol, s.Position)
if s.ProfitStats == nil { if s.ProfitStats == nil {

View File

@ -656,6 +656,12 @@ func (p *Position) AddTrade(td Trade) (profit fixedpoint.Value, netProfit fixedp
return fixedpoint.Zero, fixedpoint.Zero, false return fixedpoint.Zero, fixedpoint.Zero, false
} }
func (p *Position) UpdateMetrics() {
p.Lock()
p.updateMetrics()
p.Unlock()
}
func (p *Position) updateMetrics() { func (p *Position) updateMetrics() {
// update the position metrics only if the position defines the strategy ID // update the position metrics only if the position defines the strategy ID
if p.StrategyInstanceID == "" || p.Strategy == "" { if p.StrategyInstanceID == "" || p.Strategy == "" {