Skip to content

Commit

Permalink
Merge pull request #1856 from c9s/c9s/xmaker/improve-quota-calc
Browse files Browse the repository at this point in the history
IMPROVE: [xmaker] improve quota calculation
  • Loading branch information
c9s authored Dec 6, 2024
2 parents 215e5b1 + 79328db commit df241ec
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 12 deletions.
4 changes: 3 additions & 1 deletion pkg/fixedpoint/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -170,7 +170,9 @@ func (v Value) Percentage() string {
} else if v == NegInf {
return "-inf%"
}
return strconv.FormatFloat(float64(v)/DefaultPow*100., 'f', -1, 64) + "%"

trcv := math.Trunc(float64(v)/DefaultPow*100.*1e4) / 1e4
return strconv.FormatFloat(trcv, 'f', -1, 64) + "%"
}

func (v Value) FormatPercentage(prec int) string {
Expand Down
29 changes: 20 additions & 9 deletions pkg/strategy/xmaker/strategy.go
Original file line number Diff line number Diff line change
Expand Up @@ -720,18 +720,36 @@ func (s *Strategy) allowMarginHedge(side types.SideType) (bool, fixedpoint.Value
return false, zero
}

bufMinMarginLevel := s.MinMarginLevel.Mul(fixedpoint.NewFromFloat(1.005))
marketValue := s.accountValueCalculator.MarketValue()
debtValue := s.accountValueCalculator.DebtValue()
netValueInUsd := s.accountValueCalculator.NetValue()
s.logger.Infof("hedge account net value in usd: %f, debt value in usd: %f",
netValueInUsd.Float64(),
debtValue.Float64())

// if the margin level is higher than the minimal margin level,
// we can hedge the position, but we need to check the debt quota
if hedgeAccount.MarginLevel.Compare(s.MinMarginLevel) > 0 {
debtQuota := calculateDebtQuota(marketValue, debtValue, s.MinMarginLevel)

// debtQuota is the quota with minimal margin level
debtQuota := calculateDebtQuota(marketValue, debtValue, bufMinMarginLevel)
if debtQuota.Sign() <= 0 {
return false, zero
}

// if MaxHedgeAccountLeverage is set, we need to calculate credit buffer
if s.MaxHedgeAccountLeverage.Sign() > 0 {
maximumValueInUsd := netValueInUsd.Mul(s.MaxHedgeAccountLeverage)
leverageQuotaInUsd := maximumValueInUsd.Sub(debtValue)
s.logger.Infof("hedge account maximum leveraged value in usd: %f (%f x), quota in usd: %f",
maximumValueInUsd.Float64(),
s.MaxHedgeAccountLeverage.Float64(),
leverageQuotaInUsd.Float64(),
)

debtQuota = fixedpoint.Min(debtQuota, leverageQuotaInUsd)
}

switch side {
case types.SideTypeBuy:
return true, debtQuota
Expand Down Expand Up @@ -957,13 +975,6 @@ func (s *Strategy) updateQuote(ctx context.Context) error {
s.MinMarginLevel.String())
}

// calculate credit buffer
netValueInUsd := s.accountValueCalculator.NetValue()
s.logger.Infof("hedge account net value in usd: %f", netValueInUsd.Float64())

maximumValueInUsd := netValueInUsd.Mul(s.MaxHedgeAccountLeverage)
s.logger.Infof("hedge account maximum leveraged value in usd: %f (%f x)", maximumValueInUsd.Float64(), s.MaxHedgeAccountLeverage.Float64())

allowMarginBuy, bidQuota := s.allowMarginHedge(types.SideTypeBuy)
if allowMarginBuy {
hedgeQuota.BaseAsset.Add(bidQuota.Div(bestBid.Price))
Expand Down
9 changes: 7 additions & 2 deletions pkg/strategy/xmaker/strategy_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"testing"
"time"

"github.com/sirupsen/logrus"
"github.com/stretchr/testify/assert"

"github.com/c9s/bbgo/pkg/bbgo"
Expand All @@ -20,6 +21,8 @@ import (
func TestStrategy_allowMarginHedge(t *testing.T) {
symbol := "BTCUSDT"
market := Market(symbol)
logger := logrus.New()
logger.SetLevel(logrus.ErrorLevel)
priceSolver := pricesolver.NewSimplePriceResolver(AllMarkets())
priceSolver.Update("BTCUSDT", Number(98000.0))
priceSolver.Update("ETHUSDT", Number(3800.0))
Expand Down Expand Up @@ -58,17 +61,18 @@ func TestStrategy_allowMarginHedge(t *testing.T) {
sourceMarket: market,
sourceSession: session,
accountValueCalculator: accountValueCalc,
logger: logger,
}
s.lastPrice.Set(Number(98000.0))

allowed, quota := s.allowMarginHedge(types.SideTypeBuy)
if assert.True(t, allowed) {
assert.InDelta(t, 134941.176470588, quota.Float64(), 1.0, "should be able to borrow %f USDT", quota.Float64())
assert.InDelta(t, 133782.26785814, quota.Float64(), 1.0, "should be able to borrow %f USDT", quota.Float64())
}

allowed, quota = s.allowMarginHedge(types.SideTypeSell)
if assert.True(t, allowed) {
assert.InDelta(t, 1.376951, quota.Float64(), 0.0001, "should be able to borrow %f BTC", quota.Float64())
assert.InDelta(t, 1.36512518, quota.Float64(), 0.0001, "should be able to borrow %f BTC", quota.Float64())
}
})

Expand Down Expand Up @@ -110,6 +114,7 @@ func TestStrategy_allowMarginHedge(t *testing.T) {
sourceMarket: market,
sourceSession: session,
accountValueCalculator: accountValueCalc,
logger: logger,
}
s.lastPrice.Set(Number(98000.0))

Expand Down

0 comments on commit df241ec

Please sign in to comment.