mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-25 00:05:15 +00:00
rename ProfitAndLossCalculator to AverageCostCalculator
This commit is contained in:
parent
ee86a71ebb
commit
a6b99f6828
|
@ -9,7 +9,7 @@ import (
|
|||
"github.com/spf13/cobra"
|
||||
|
||||
"github.com/c9s/bbgo/cmd/cmdutil"
|
||||
"github.com/c9s/bbgo/pkg/accounting"
|
||||
"github.com/c9s/bbgo/pkg/accounting/pnl"
|
||||
"github.com/c9s/bbgo/pkg/bbgo"
|
||||
"github.com/c9s/bbgo/pkg/service"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
|
@ -110,7 +110,7 @@ var pnlCmd = &cobra.Command{
|
|||
|
||||
currentPrice, err := exchange.QueryAveragePrice(ctx, symbol)
|
||||
|
||||
calculator := &accounting.ProfitAndLossCalculator{
|
||||
calculator := &pnl.AverageCostCalculator{
|
||||
TradingFeeCurrency: tradingFeeCurrency,
|
||||
Symbol: symbol,
|
||||
StartTime: startTime,
|
||||
|
|
1
go.mod
1
go.mod
|
@ -30,6 +30,7 @@ require (
|
|||
github.com/sirupsen/logrus v1.4.2
|
||||
github.com/slack-go/slack v0.6.6-0.20200602212211-b04b8521281b
|
||||
github.com/spf13/cobra v1.0.0
|
||||
github.com/spf13/pflag v1.0.3
|
||||
github.com/spf13/viper v1.7.0
|
||||
github.com/stretchr/testify v1.6.1
|
||||
github.com/tebeka/strftime v0.1.3 // indirect
|
||||
|
|
|
@ -1,117 +1,2 @@
|
|||
package accounting
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
type ProfitAndLossCalculator struct {
|
||||
Symbol string
|
||||
StartTime time.Time
|
||||
CurrentPrice float64
|
||||
Trades []types.Trade
|
||||
TradingFeeCurrency string
|
||||
}
|
||||
|
||||
func (c *ProfitAndLossCalculator) AddTrade(trade types.Trade) {
|
||||
c.Trades = append(c.Trades, trade)
|
||||
}
|
||||
|
||||
func (c *ProfitAndLossCalculator) SetCurrentPrice(price float64) {
|
||||
c.CurrentPrice = price
|
||||
}
|
||||
|
||||
func (c *ProfitAndLossCalculator) Calculate() *ProfitAndLossReport {
|
||||
// copy trades, so that we can truncate it.
|
||||
var trades = c.Trades
|
||||
var bidVolume = 0.0
|
||||
var bidAmount = 0.0
|
||||
|
||||
var askVolume = 0.0
|
||||
|
||||
var feeUSD = 0.0
|
||||
var bidFeeUSD = 0.0
|
||||
var feeRate = 0.0015
|
||||
|
||||
var currencyFees = map[string]float64{}
|
||||
|
||||
for _, trade := range trades {
|
||||
if trade.Symbol == c.Symbol {
|
||||
if trade.IsBuyer {
|
||||
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
|
||||
}
|
||||
|
||||
logrus.Infof("average bid price = (total amount %f + total feeUSD %f) / volume %f", bidAmount, bidFeeUSD, bidVolume)
|
||||
profit := 0.0
|
||||
averageCost := (bidAmount + bidFeeUSD) / bidVolume
|
||||
|
||||
for _, t := range trades {
|
||||
if t.Symbol != c.Symbol {
|
||||
continue
|
||||
}
|
||||
|
||||
if t.IsBuyer {
|
||||
continue
|
||||
}
|
||||
|
||||
profit += (t.Price - averageCost) * t.Quantity
|
||||
askVolume += t.Quantity
|
||||
}
|
||||
|
||||
profit -= feeUSD
|
||||
unrealizedProfit := profit
|
||||
|
||||
stock := bidVolume - askVolume
|
||||
if stock > 0 {
|
||||
stockFee := c.CurrentPrice * stock * feeRate
|
||||
unrealizedProfit += (c.CurrentPrice-averageCost)*stock - stockFee
|
||||
}
|
||||
|
||||
return &ProfitAndLossReport{
|
||||
Symbol: c.Symbol,
|
||||
StartTime: c.StartTime,
|
||||
CurrentPrice: c.CurrentPrice,
|
||||
NumTrades: len(trades),
|
||||
|
||||
BidVolume: bidVolume,
|
||||
AskVolume: askVolume,
|
||||
|
||||
Stock: stock,
|
||||
Profit: profit,
|
||||
UnrealizedProfit: unrealizedProfit,
|
||||
AverageBidCost: averageCost,
|
||||
FeeUSD: feeUSD,
|
||||
CurrencyFees: currencyFees,
|
||||
}
|
||||
}
|
||||
|
|
118
pkg/accounting/pnl/avg_cost.go
Normal file
118
pkg/accounting/pnl/avg_cost.go
Normal file
|
@ -0,0 +1,118 @@
|
|||
package pnl
|
||||
|
||||
import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/accounting"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
type AverageCostCalculator struct {
|
||||
Symbol string
|
||||
StartTime time.Time
|
||||
CurrentPrice float64
|
||||
Trades []types.Trade
|
||||
TradingFeeCurrency string
|
||||
}
|
||||
|
||||
func (c *AverageCostCalculator) AddTrade(trade types.Trade) {
|
||||
c.Trades = append(c.Trades, trade)
|
||||
}
|
||||
|
||||
func (c *AverageCostCalculator) SetCurrentPrice(price float64) {
|
||||
c.CurrentPrice = price
|
||||
}
|
||||
|
||||
func (c *AverageCostCalculator) Calculate() *accounting.ProfitAndLossReport {
|
||||
// copy trades, so that we can truncate it.
|
||||
var trades = c.Trades
|
||||
var bidVolume = 0.0
|
||||
var bidAmount = 0.0
|
||||
|
||||
var askVolume = 0.0
|
||||
|
||||
var feeUSD = 0.0
|
||||
var bidFeeUSD = 0.0
|
||||
var feeRate = 0.0015
|
||||
|
||||
var currencyFees = map[string]float64{}
|
||||
|
||||
for _, trade := range trades {
|
||||
if trade.Symbol == c.Symbol {
|
||||
if trade.IsBuyer {
|
||||
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
|
||||
}
|
||||
|
||||
logrus.Infof("average bid price = (total amount %f + total feeUSD %f) / volume %f", bidAmount, bidFeeUSD, bidVolume)
|
||||
profit := 0.0
|
||||
averageCost := (bidAmount + bidFeeUSD) / bidVolume
|
||||
|
||||
for _, t := range trades {
|
||||
if t.Symbol != c.Symbol {
|
||||
continue
|
||||
}
|
||||
|
||||
if t.IsBuyer {
|
||||
continue
|
||||
}
|
||||
|
||||
profit += (t.Price - averageCost) * t.Quantity
|
||||
askVolume += t.Quantity
|
||||
}
|
||||
|
||||
profit -= feeUSD
|
||||
unrealizedProfit := profit
|
||||
|
||||
stock := bidVolume - askVolume
|
||||
if stock > 0 {
|
||||
stockFee := c.CurrentPrice * stock * feeRate
|
||||
unrealizedProfit += (c.CurrentPrice-averageCost)*stock - stockFee
|
||||
}
|
||||
|
||||
return &accounting.ProfitAndLossReport{
|
||||
Symbol: c.Symbol,
|
||||
StartTime: c.StartTime,
|
||||
CurrentPrice: c.CurrentPrice,
|
||||
NumTrades: len(trades),
|
||||
|
||||
BidVolume: bidVolume,
|
||||
AskVolume: askVolume,
|
||||
|
||||
Stock: stock,
|
||||
Profit: profit,
|
||||
UnrealizedProfit: unrealizedProfit,
|
||||
AverageBidCost: averageCost,
|
||||
FeeUSD: feeUSD,
|
||||
CurrencyFees: currencyFees,
|
||||
}
|
||||
}
|
|
@ -3,7 +3,7 @@ package bbgo
|
|||
import (
|
||||
"context"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/accounting"
|
||||
"github.com/c9s/bbgo/pkg/accounting/pnl"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
|
@ -23,7 +23,7 @@ type BackTestTrader struct {
|
|||
// Context is trading Context
|
||||
Context *Context
|
||||
SourceKLines []types.KLine
|
||||
ProfitAndLossCalculator *accounting.ProfitAndLossCalculator
|
||||
ProfitAndLossCalculator *pnl.AverageCostCalculator
|
||||
|
||||
doneOrders []types.SubmitOrder
|
||||
pendingOrders []types.SubmitOrder
|
||||
|
@ -125,7 +125,7 @@ func (trader *BackTestTrader) RunStrategy(ctx context.Context, strategy SingleEx
|
|||
}
|
||||
|
||||
tradeID++
|
||||
trader.ProfitAndLossCalculator.AddTrade(trade)
|
||||
trader.AverageCostCalculator.AddTrade(trade)
|
||||
|
||||
trader.doneOrders = append(trader.doneOrders, order)
|
||||
}
|
||||
|
@ -135,7 +135,7 @@ func (trader *BackTestTrader) RunStrategy(ctx context.Context, strategy SingleEx
|
|||
}
|
||||
|
||||
fmt.Print("\n")
|
||||
report := trader.ProfitAndLossCalculator.Calculate()
|
||||
report := trader.AverageCostCalculator.Calculate()
|
||||
report.Print()
|
||||
|
||||
logrus.Infof("wallet balance:")
|
||||
|
|
|
@ -3,7 +3,7 @@ package bbgo
|
|||
import (
|
||||
"sync"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/accounting"
|
||||
"github.com/c9s/bbgo/pkg/accounting/pnl"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
|
@ -19,7 +19,7 @@ type Context struct {
|
|||
CurrentPrice float64
|
||||
|
||||
Balances map[string]types.Balance
|
||||
ProfitAndLossCalculator *accounting.ProfitAndLossCalculator
|
||||
ProfitAndLossCalculator *pnl.AverageCostCalculator
|
||||
StockManager *StockDistribution
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user