Merge pull request #1547 from c9s/refactor/tradingutil

REFACTOR: move trading related utility functions to the tradingutil package
This commit is contained in:
c9s 2024-02-23 19:25:03 +08:00 committed by GitHub
commit b72a176b91
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 32 additions and 57 deletions

View File

@ -35,8 +35,8 @@ type Grid struct {
type Pin fixedpoint.Value
// filterPrice filters price with the given precision
func filterPrice(p fixedpoint.Value, prec int) fixedpoint.Value {
// roundAndTruncatePrice rounds the given price at prec-1 and then truncate the price at prec
func roundAndTruncatePrice(p fixedpoint.Value, prec int) fixedpoint.Value {
var pow10 = math.Pow10(prec)
pp := math.Round(p.Float64()*pow10*10.0) / 10.0
pp = math.Trunc(pp) / pow10
@ -71,12 +71,12 @@ func calculateArithmeticPins(lower, upper, spread, tickSize fixedpoint.Value) []
var ts = tickSize.Float64()
var prec = int(math.Round(math.Log10(ts) * -1.0))
for p := lower; p.Compare(upper.Sub(spread)) <= 0; p = p.Add(spread) {
price := filterPrice(p, prec)
price := roundAndTruncatePrice(p, prec)
pins = append(pins, Pin(price))
}
// this makes sure there is no error at the upper price
upperPrice := filterPrice(upper, prec)
upperPrice := roundAndTruncatePrice(upper, prec)
pins = append(pins, Pin(upperPrice))
return pins

View File

@ -243,8 +243,8 @@ func Test_filterPrice1(t *testing.T) {
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
rst := filterPrice(tt.args.p, tt.args.prec)
assert.Equalf(t, tt.want, rst.String(), "filterPrice(%v, %v)", tt.args.p, tt.args.prec)
rst := roundAndTruncatePrice(tt.args.p, tt.args.prec)
assert.Equalf(t, tt.want, rst.String(), "roundAndTruncatePrice(%v, %v)", tt.args.p, tt.args.prec)
})
}
}

View File

@ -22,6 +22,7 @@ import (
"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types"
"github.com/c9s/bbgo/pkg/util"
"github.com/c9s/bbgo/pkg/util/tradingutil"
)
const ID = "grid2"
@ -351,7 +352,7 @@ func (s *Strategy) calculateProfit(o types.Order, buyPrice, buyQuantity fixedpoi
}
func (s *Strategy) verifyOrderTrades(o types.Order, trades []types.Trade) bool {
tq := aggregateTradesQuantity(trades)
tq := tradingutil.AggregateTradesQuantity(trades)
// on MAX: if order.status == filled, it does not mean order.executedQuantity == order.quantity
// order.executedQuantity can be less than order.quantity
@ -400,8 +401,8 @@ func (s *Strategy) aggregateOrderQuoteAmountAndFee(o types.Order) (fixedpoint.Va
// if one of the trades is missing, we need to query the trades from the RESTful API
if s.verifyOrderTrades(o, orderTrades) {
// if trades are verified
quoteAmount := aggregateTradesQuoteQuantity(orderTrades)
fees := collectTradeFee(orderTrades)
quoteAmount := tradingutil.AggregateTradesQuoteQuantity(orderTrades)
fees := tradingutil.CollectTradeFee(orderTrades)
if fee, ok := fees[feeCurrency]; ok {
return quoteAmount, fee, feeCurrency
}
@ -428,9 +429,9 @@ func (s *Strategy) aggregateOrderQuoteAmountAndFee(o types.Order) (fixedpoint.Va
}
}
quoteAmount := aggregateTradesQuoteQuantity(orderTrades)
quoteAmount := tradingutil.AggregateTradesQuoteQuantity(orderTrades)
// still try to aggregate the trades quantity if we can:
fees := collectTradeFee(orderTrades)
fees := tradingutil.CollectTradeFee(orderTrades)
if fee, ok := fees[feeCurrency]; ok {
return quoteAmount, fee, feeCurrency
}

View File

@ -1,45 +0,0 @@
package grid2
import (
"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/c9s/bbgo/pkg/types"
)
// collectTradeFee collects the fee from the given trade slice
func collectTradeFee(trades []types.Trade) map[string]fixedpoint.Value {
fees := make(map[string]fixedpoint.Value)
for _, t := range trades {
if t.FeeDiscounted {
continue
}
if fee, ok := fees[t.FeeCurrency]; ok {
fees[t.FeeCurrency] = fee.Add(t.Fee)
} else {
fees[t.FeeCurrency] = t.Fee
}
}
return fees
}
func aggregateTradesQuantity(trades []types.Trade) fixedpoint.Value {
tq := fixedpoint.Zero
for _, t := range trades {
tq = tq.Add(t.Quantity)
}
return tq
}
// aggregateTradesQuoteQuantity aggregates the quote quantity from the given trade slice
func aggregateTradesQuoteQuantity(trades []types.Trade) fixedpoint.Value {
quoteQuantity := fixedpoint.Zero
for _, t := range trades {
if t.QuoteQuantity.IsZero() {
quoteQuantity = quoteQuantity.Add(t.Price.Mul(t.Quantity))
} else {
quoteQuantity = quoteQuantity.Add(t.QuoteQuantity)
}
}
return quoteQuantity
}

View File

@ -9,16 +9,21 @@ import (
func CollectTradeFee(trades []types.Trade) map[string]fixedpoint.Value {
fees := make(map[string]fixedpoint.Value)
for _, t := range trades {
if t.FeeDiscounted {
continue
}
if fee, ok := fees[t.FeeCurrency]; ok {
fees[t.FeeCurrency] = fee.Add(t.Fee)
} else {
fees[t.FeeCurrency] = t.Fee
}
}
return fees
}
// AggregateTradesQuantity sums up the quantity from the given trades
// totalQuantity = SUM(trade1.Quantity, trade2.Quantity, ...)
func AggregateTradesQuantity(trades []types.Trade) fixedpoint.Value {
tq := fixedpoint.Zero
for _, t := range trades {
@ -26,3 +31,17 @@ func AggregateTradesQuantity(trades []types.Trade) fixedpoint.Value {
}
return tq
}
// AggregateTradesQuoteQuantity aggregates the quote quantity from the given trade slice
func AggregateTradesQuoteQuantity(trades []types.Trade) fixedpoint.Value {
quoteQuantity := fixedpoint.Zero
for _, t := range trades {
if t.QuoteQuantity.IsZero() {
quoteQuantity = quoteQuantity.Add(t.Price.Mul(t.Quantity))
} else {
quoteQuantity = quoteQuantity.Add(t.QuoteQuantity)
}
}
return quoteQuantity
}