xmaker: check hedge balance only when it's spot account

This commit is contained in:
c9s 2024-08-28 14:48:38 +08:00
parent 1e2f086643
commit 108fb6138a
No known key found for this signature in database
GPG Key ID: 7385E7E464CB0A54

View File

@ -63,6 +63,9 @@ type Strategy struct {
BollBandMargin fixedpoint.Value `json:"bollBandMargin"` BollBandMargin fixedpoint.Value `json:"bollBandMargin"`
BollBandMarginFactor fixedpoint.Value `json:"bollBandMarginFactor"` BollBandMarginFactor fixedpoint.Value `json:"bollBandMarginFactor"`
// MinMarginLevel is the minimum margin level to trigger the hedge
MinMarginLevel fixedpoint.Value `json:"minMarginLevel"`
StopHedgeQuoteBalance fixedpoint.Value `json:"stopHedgeQuoteBalance"` StopHedgeQuoteBalance fixedpoint.Value `json:"stopHedgeQuoteBalance"`
StopHedgeBaseBalance fixedpoint.Value `json:"stopHedgeBaseBalance"` StopHedgeBaseBalance fixedpoint.Value `json:"stopHedgeBaseBalance"`
@ -650,6 +653,36 @@ func (s *Strategy) updateQuote(ctx context.Context) {
_ = createdOrders _ = createdOrders
} }
func (s *Strategy) adjustHedgeQuantityWithAvailableBalance(side types.SideType, quantity, lastPrice fixedpoint.Value) fixedpoint.Value {
// adjust quantity according to the balances
account := s.sourceSession.GetAccount()
switch side {
case types.SideTypeBuy:
// check quote quantity
if quote, ok := account.Balance(s.sourceMarket.QuoteCurrency); ok {
if quote.Available.Compare(s.sourceMarket.MinNotional) < 0 {
// adjust price to higher 0.1%, so that we can ensure that the order can be executed
availableQuote := s.sourceMarket.TruncateQuoteQuantity(quote.Available)
quantity = bbgo.AdjustQuantityByMaxAmount(quantity, lastPrice, availableQuote)
}
}
case types.SideTypeSell:
// check quote quantity
if base, ok := account.Balance(s.sourceMarket.BaseCurrency); ok {
if base.Available.Compare(quantity) < 0 {
quantity = base.Available
}
}
}
// truncate the quantity to the supported precision
return s.sourceMarket.TruncateQuantity(quantity)
}
func (s *Strategy) Hedge(ctx context.Context, pos fixedpoint.Value) { func (s *Strategy) Hedge(ctx context.Context, pos fixedpoint.Value) {
side := types.SideTypeBuy side := types.SideTypeBuy
if pos.IsZero() { if pos.IsZero() {
@ -677,36 +710,27 @@ func (s *Strategy) Hedge(ctx context.Context, pos fixedpoint.Value) {
} }
} }
notional := quantity.Mul(lastPrice) if s.sourceSession.Margin {
// check the margin level
// adjust quantity according to the balances account, err := s.sourceSession.UpdateAccount(ctx)
account := s.sourceSession.GetAccount() if err != nil {
switch side { log.WithError(err).Errorf("unable to update account")
return
case types.SideTypeBuy:
// check quote quantity
if quote, ok := account.Balance(s.sourceMarket.QuoteCurrency); ok {
if quote.Available.Compare(notional) < 0 {
// adjust price to higher 0.1%, so that we can ensure that the order can be executed
quantity = bbgo.AdjustQuantityByMaxAmount(quantity, lastPrice.Mul(lastPriceModifier), quote.Available)
quantity = s.sourceMarket.TruncateQuantity(quantity)
}
} }
case types.SideTypeSell: if !s.MinMarginLevel.IsZero() && !account.MarginLevel.IsZero() && account.MarginLevel.Compare(s.MinMarginLevel) < 0 {
// check quote quantity log.Errorf("margin level %f is too low (< %f), skip hedge", account.MarginLevel.Float64(), s.MinMarginLevel.Float64())
if base, ok := account.Balance(s.sourceMarket.BaseCurrency); ok { return
if base.Available.Compare(quantity) < 0 {
quantity = base.Available
}
} }
} else {
quantity = s.adjustHedgeQuantityWithAvailableBalance(side, quantity, lastPrice)
} }
// truncate quantity for the supported precision // truncate quantity for the supported precision
quantity = s.sourceMarket.TruncateQuantity(quantity) quantity = s.sourceMarket.TruncateQuantity(quantity)
if s.sourceMarket.IsDustQuantity(quantity, lastPrice) { if s.sourceMarket.IsDustQuantity(quantity, lastPrice) {
log.Warnf("skip dust quantity: %s", quantity.String()) log.Warnf("skip dust quantity: %s @ price %f", quantity.String(), lastPrice.Float64())
return return
} }
@ -821,6 +845,10 @@ func (s *Strategy) Defaults() error {
s.NumLayers = 1 s.NumLayers = 1
} }
if s.MinMarginLevel.IsZero() {
s.MinMarginLevel = fixedpoint.NewFromFloat(3.0)
}
if s.BidMargin.IsZero() { if s.BidMargin.IsZero() {
if !s.Margin.IsZero() { if !s.Margin.IsZero() {
s.BidMargin = s.Margin s.BidMargin = s.Margin