xmaker: truncate quantity when hedging

This commit is contained in:
c9s 2021-12-26 15:44:41 +08:00
parent 05a0745d08
commit 902e27ede4
2 changed files with 15 additions and 6 deletions

View File

@ -501,6 +501,7 @@ func (s *Strategy) Hedge(ctx context.Context, pos fixedpoint.Value) {
}
quantity := fixedpoint.Abs(pos)
quantity = s.sourceMarket.TruncateQuantity(quantity)
if pos < 0 {
side = types.SideTypeSell

View File

@ -8,6 +8,8 @@ import (
"time"
"github.com/leekchan/accounting"
"github.com/c9s/bbgo/pkg/fixedpoint"
)
type Duration time.Duration
@ -49,7 +51,7 @@ func (d *Duration) UnmarshalJSON(data []byte) error {
}
type Market struct {
Symbol string `json:"symbol"`
Symbol string `json:"symbol"`
// LocalSymbol is used for exchange's API (exchange package internal)
LocalSymbol string `json:"localSymbol,omitempty"`
@ -57,7 +59,7 @@ type Market struct {
// PricePrecision is the precision used for formatting price, 8 = 8 decimals
// can be converted from price tick step size, e.g.
// int(math.Log10(price step size))
PricePrecision int `json:"pricePrecision"`
PricePrecision int `json:"pricePrecision"`
// VolumePrecision is the precision used for formatting quantity and volume, 8 = 8 decimals
// can be converted from step size, e.g.
@ -65,10 +67,10 @@ type Market struct {
VolumePrecision int `json:"volumePrecision"`
// QuoteCurrency is the currency name for quote, e.g. USDT in BTC/USDT, USDC in BTC/USDC
QuoteCurrency string `json:"quoteCurrency"`
QuoteCurrency string `json:"quoteCurrency"`
// BaseCurrency is the current name for base, e.g. BTC in BTC/USDT, ETH in ETH/USDC
BaseCurrency string `json:"baseCurrency"`
BaseCurrency string `json:"baseCurrency"`
// The MIN_NOTIONAL filter defines the minimum notional value allowed for an order on a symbol.
// An order's notional value is the price * quantity
@ -84,7 +86,7 @@ type Market struct {
// StepSize is the step size of quantity
// can be converted from precision, e.g.
// 1.0 / math.Pow10(m.BaseUnitPrecision)
StepSize float64 `json:"stepSize,omitempty"`
StepSize float64 `json:"stepSize,omitempty"`
MinPrice float64 `json:"minPrice,omitempty"`
MaxPrice float64 `json:"maxPrice,omitempty"`
@ -93,6 +95,12 @@ type Market struct {
TickSize float64 `json:"tickSize,omitempty"`
}
// TruncateQuantity uses the step size to truncate floating number, in order to avoid the rounding issue
func (m Market) TruncateQuantity(quantity fixedpoint.Value) fixedpoint.Value {
stepRound := math.Pow10(-int(math.Log10(m.StepSize)))
return fixedpoint.NewFromFloat(math.Trunc(quantity.Float64()*stepRound) / stepRound)
}
func (m Market) BaseCurrencyFormatter() *accounting.Accounting {
a := accounting.DefaultAccounting(m.BaseCurrency, m.VolumePrecision)
a.Format = "%v %s"
@ -172,4 +180,4 @@ type MarketMap map[string]Market
func (m MarketMap) Add(market Market) {
m[market.Symbol] = market
}
}