package dca2 import ( "fmt" "strings" "github.com/c9s/bbgo/pkg/fixedpoint" "github.com/c9s/bbgo/pkg/types" ) type ProfitStats struct { Symbol string `json:"symbol"` Market types.Market `json:"market,omitempty"` FromOrderID uint64 `json:"fromOrderID,omitempty"` Round int64 `json:"round,omitempty"` QuoteInvestment fixedpoint.Value `json:"quoteInvestment,omitempty"` CurrentRoundProfit fixedpoint.Value `json:"currentRoundProfit,omitempty"` CurrentRoundFee map[string]fixedpoint.Value `json:"currentRoundFee,omitempty"` TotalProfit fixedpoint.Value `json:"totalProfit,omitempty"` TotalFee map[string]fixedpoint.Value `json:"totalFee,omitempty"` // used to flexible recovery OpenPositionPVs []types.PriceVolume `json:"openPositionPVs,omitempty"` types.PersistenceTTL } func newProfitStats(market types.Market, quoteInvestment fixedpoint.Value) *ProfitStats { return &ProfitStats{ Symbol: market.Symbol, Market: market, Round: 1, QuoteInvestment: quoteInvestment, CurrentRoundFee: make(map[string]fixedpoint.Value), TotalFee: make(map[string]fixedpoint.Value), } } func (s *ProfitStats) AddTrade(trade types.Trade) { if s.CurrentRoundFee == nil { s.CurrentRoundFee = make(map[string]fixedpoint.Value) } if fee, ok := s.CurrentRoundFee[trade.FeeCurrency]; ok { s.CurrentRoundFee[trade.FeeCurrency] = fee.Add(trade.Fee) } else { s.CurrentRoundFee[trade.FeeCurrency] = trade.Fee } if s.TotalFee == nil { s.TotalFee = make(map[string]fixedpoint.Value) } if fee, ok := s.TotalFee[trade.FeeCurrency]; ok { s.TotalFee[trade.FeeCurrency] = fee.Add(trade.Fee) } else { s.TotalFee[trade.FeeCurrency] = trade.Fee } quoteQuantity := trade.QuoteQuantity if trade.Side == types.SideTypeBuy { quoteQuantity = quoteQuantity.Neg() } s.CurrentRoundProfit = s.CurrentRoundProfit.Add(quoteQuantity) s.TotalProfit = s.TotalProfit.Add(quoteQuantity) if s.Market.QuoteCurrency == trade.FeeCurrency { s.CurrentRoundProfit = s.CurrentRoundProfit.Sub(trade.Fee) s.TotalProfit = s.TotalProfit.Sub(trade.Fee) } } func (s *ProfitStats) NewRound() { s.Round++ s.CurrentRoundProfit = fixedpoint.Zero s.CurrentRoundFee = make(map[string]fixedpoint.Value) } func (s *ProfitStats) String() string { var sb strings.Builder sb.WriteString("[------------------ Profit Stats ------------------]\n") sb.WriteString(fmt.Sprintf("Round: %d\n", s.Round)) sb.WriteString(fmt.Sprintf("From Order ID: %d\n", s.FromOrderID)) sb.WriteString(fmt.Sprintf("Quote Investment: %s\n", s.QuoteInvestment)) sb.WriteString(fmt.Sprintf("Current Round Profit: %s\n", s.CurrentRoundProfit)) sb.WriteString(fmt.Sprintf("Total Profit: %s\n", s.TotalProfit)) for currency, fee := range s.CurrentRoundFee { sb.WriteString(fmt.Sprintf("FEE (%s): %s\n", currency, fee)) } sb.WriteString("[------------------ Profit Stats ------------------]\n") return sb.String() }