diff --git a/pkg/fixedpoint/convert.go b/pkg/fixedpoint/convert.go index d000603a81..0de164d3cf 100644 --- a/pkg/fixedpoint/convert.go +++ b/pkg/fixedpoint/convert.go @@ -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 { diff --git a/pkg/strategy/xmaker/strategy.go b/pkg/strategy/xmaker/strategy.go index 03a4d4dfba..79d914a7cd 100644 --- a/pkg/strategy/xmaker/strategy.go +++ b/pkg/strategy/xmaker/strategy.go @@ -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 @@ -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)) diff --git a/pkg/strategy/xmaker/strategy_test.go b/pkg/strategy/xmaker/strategy_test.go index 7688e08727..02e9624486 100644 --- a/pkg/strategy/xmaker/strategy_test.go +++ b/pkg/strategy/xmaker/strategy_test.go @@ -7,6 +7,7 @@ import ( "testing" "time" + "github.com/sirupsen/logrus" "github.com/stretchr/testify/assert" "github.com/c9s/bbgo/pkg/bbgo" @@ -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)) @@ -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()) } }) @@ -110,6 +114,7 @@ func TestStrategy_allowMarginHedge(t *testing.T) { sourceMarket: market, sourceSession: session, accountValueCalculator: accountValueCalc, + logger: logger, } s.lastPrice.Set(Number(98000.0))