bbgo_origin/pkg/accounting/pnl/avg_cost.go

113 lines
2.4 KiB
Go
Raw Normal View History

package pnl
import (
"strings"
2021-02-06 04:32:21 +00:00
"time"
"github.com/c9s/bbgo/pkg/types"
)
type AverageCostCalculator struct {
TradingFeeCurrency string
}
2020-10-22 07:57:50 +00:00
func (c *AverageCostCalculator) Calculate(symbol string, trades []types.Trade, currentPrice float64) *AverageCostPnlReport {
// copy trades, so that we can truncate it.
var bidVolume = 0.0
var bidAmount = 0.0
var askVolume = 0.0
var feeUSD = 0.0
var bidFeeUSD = 0.0
var feeRate = 0.0015
2020-10-24 08:32:54 +00:00
if len(trades) == 0 {
return &AverageCostPnlReport{
Symbol: symbol,
CurrentPrice: currentPrice,
NumTrades: 0,
2020-11-10 06:18:27 +00:00
BuyVolume: bidVolume,
SellVolume: askVolume,
FeeInUSD: feeUSD,
2020-10-24 08:32:54 +00:00
}
}
var currencyFees = map[string]float64{}
for _, trade := range trades {
2020-10-22 07:57:50 +00:00
if trade.Symbol == symbol {
if trade.Side == types.SideTypeBuy {
bidVolume += trade.Quantity
bidAmount += trade.Price * trade.Quantity
}
// since we use USDT as the quote currency, we simply check if it matches the currency symbol
if strings.HasPrefix(trade.Symbol, trade.FeeCurrency) {
bidVolume -= trade.Fee
feeUSD += trade.Price * trade.Fee
if trade.IsBuyer {
bidFeeUSD += trade.Price * trade.Fee
}
} else if trade.FeeCurrency == "USDT" {
feeUSD += trade.Fee
if trade.IsBuyer {
bidFeeUSD += trade.Fee
}
}
} else {
if trade.FeeCurrency == c.TradingFeeCurrency {
bidVolume -= trade.Fee
}
}
if _, ok := currencyFees[trade.FeeCurrency]; !ok {
currencyFees[trade.FeeCurrency] = 0.0
}
currencyFees[trade.FeeCurrency] += trade.Fee
}
profit := 0.0
averageCost := (bidAmount + bidFeeUSD) / bidVolume
for _, t := range trades {
2020-10-22 07:57:50 +00:00
if t.Symbol != symbol {
continue
}
if t.Side == types.SideTypeBuy {
continue
}
profit += (t.Price - averageCost) * t.Quantity
askVolume += t.Quantity
}
profit -= feeUSD
unrealizedProfit := profit
stock := bidVolume - askVolume
if stock > 0 {
2020-10-16 02:19:53 +00:00
stockFee := currentPrice * stock * feeRate
unrealizedProfit += (currentPrice-averageCost)*stock - stockFee
}
2020-10-16 02:21:37 +00:00
return &AverageCostPnlReport{
2020-10-22 07:57:50 +00:00
Symbol: symbol,
2020-10-16 02:19:53 +00:00
CurrentPrice: currentPrice,
NumTrades: len(trades),
2021-02-06 04:32:21 +00:00
StartTime: time.Time(trades[0].Time),
2020-11-10 06:18:27 +00:00
BuyVolume: bidVolume,
SellVolume: askVolume,
Stock: stock,
Profit: profit,
UnrealizedProfit: unrealizedProfit,
AverageBidCost: averageCost,
2020-11-10 06:18:27 +00:00
FeeInUSD: feeUSD,
CurrencyFees: currencyFees,
}
}