mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-26 00:35:15 +00:00
refactor pnl calculator
This commit is contained in:
parent
a177e55172
commit
19b225737f
|
@ -1,18 +1,23 @@
|
|||
package bbgo
|
||||
|
||||
import "time"
|
||||
|
||||
type TradingContext struct {
|
||||
KLineWindowSize int
|
||||
KLineWindows map[string]KLineWindow
|
||||
AverageBidPrice float64
|
||||
Stock float64
|
||||
Profit float64
|
||||
CurrentPrice float64
|
||||
Trades []Trade
|
||||
TradeStartTime time.Time
|
||||
|
||||
Symbol string
|
||||
|
||||
// Market is the market configuration of a symbol
|
||||
Market Market
|
||||
|
||||
AverageBidPrice float64
|
||||
CurrentPrice float64
|
||||
|
||||
ProfitAndLossCalculator *ProfitAndLossCalculator
|
||||
}
|
||||
|
||||
func (c *TradingContext) SetCurrentPrice(price float64) {
|
||||
c.CurrentPrice = price
|
||||
c.ProfitAndLossCalculator.SetCurrentPrice(price)
|
||||
}
|
||||
|
||||
func (c *TradingContext) AddKLine(kline KLine) KLineWindow {
|
||||
|
@ -26,7 +31,4 @@ func (c *TradingContext) AddKLine(kline KLine) KLineWindow {
|
|||
return klineWindow
|
||||
}
|
||||
|
||||
func (c *TradingContext) UpdatePnL() {
|
||||
c.AverageBidPrice, c.Stock, c.Profit, _ = CalculateCostAndProfit(c.Trades, c.CurrentPrice)
|
||||
}
|
||||
|
||||
|
|
72
bbgo/pnl.go
72
bbgo/pnl.go
|
@ -1,6 +1,9 @@
|
|||
package bbgo
|
||||
|
||||
import log "github.com/sirupsen/logrus"
|
||||
import (
|
||||
log "github.com/sirupsen/logrus"
|
||||
"time"
|
||||
)
|
||||
|
||||
func CalculateAverageCost(trades []Trade) (averageCost float64) {
|
||||
var totalCost = 0.0
|
||||
|
@ -19,7 +22,25 @@ func CalculateAverageCost(trades []Trade) (averageCost float64) {
|
|||
return
|
||||
}
|
||||
|
||||
func CalculateCostAndProfit(trades []Trade, currentPrice float64) (averageBidPrice, stock, profit, fee float64) {
|
||||
type ProfitAndLossCalculator struct {
|
||||
Symbol string
|
||||
StartTime time.Time
|
||||
CurrentPrice float64
|
||||
Trades []Trade
|
||||
}
|
||||
|
||||
func (c *ProfitAndLossCalculator) AddTrade(trade 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 bidFee = 0.0
|
||||
|
@ -48,7 +69,8 @@ func CalculateCostAndProfit(trades []Trade, currentPrice float64) (averageBidPri
|
|||
}
|
||||
|
||||
log.Infof("average bid price = (total amount %f + total fee %f) / volume %f", bidAmount, bidFee, bidVolume)
|
||||
averageBidPrice = (bidAmount + bidFee) / bidVolume
|
||||
profit := 0.0
|
||||
averageBidPrice := (bidAmount + bidFee) / bidVolume
|
||||
|
||||
var feeRate = 0.001
|
||||
var askVolume = 0.0
|
||||
|
@ -66,14 +88,46 @@ func CalculateCostAndProfit(trades []Trade, currentPrice float64) (averageBidPri
|
|||
|
||||
profit -= askFee
|
||||
|
||||
stock = bidVolume - askVolume
|
||||
stock := bidVolume - askVolume
|
||||
futureFee := 0.0
|
||||
if stock > 0 {
|
||||
stockfee := currentPrice * feeRate * stock
|
||||
profit += (currentPrice-averageBidPrice)*stock - stockfee
|
||||
futureFee += stockfee
|
||||
stockFee := c.CurrentPrice * feeRate * stock
|
||||
profit += (c.CurrentPrice-averageBidPrice)*stock - stockFee
|
||||
futureFee += stockFee
|
||||
}
|
||||
|
||||
fee = bidFee + askFee + futureFee
|
||||
return
|
||||
fee := bidFee + askFee + futureFee
|
||||
|
||||
return &ProfitAndLossReport{
|
||||
CurrentPrice: c.CurrentPrice,
|
||||
StartTime: c.StartTime,
|
||||
NumTrades: len(trades),
|
||||
|
||||
Profit: profit,
|
||||
AverageBidPrice: averageBidPrice,
|
||||
Stock: stock,
|
||||
Fee: fee,
|
||||
}
|
||||
}
|
||||
|
||||
type ProfitAndLossReport struct {
|
||||
CurrentPrice float64
|
||||
StartTime time.Time
|
||||
|
||||
NumTrades int
|
||||
Profit float64
|
||||
AverageBidPrice float64
|
||||
Stock float64
|
||||
Fee float64
|
||||
}
|
||||
|
||||
func (report ProfitAndLossReport) Print() {
|
||||
log.Infof("trades since: %v", report.StartTime)
|
||||
log.Infof("average bid price: %s", USD.FormatMoneyFloat64(report.AverageBidPrice))
|
||||
log.Infof("Stock volume: %f", report.Stock)
|
||||
log.Infof("current price: %s", USD.FormatMoneyFloat64(report.CurrentPrice))
|
||||
log.Infof("overall profit: %s", USD.FormatMoneyFloat64(report.Profit))
|
||||
}
|
||||
|
||||
func CalculateCostAndProfit(trades []Trade, currentPrice float64, startTime time.Time) (report *ProfitAndLossReport) {
|
||||
}
|
||||
|
|
|
@ -105,16 +105,12 @@ func (t *Trader) ReportTrade(e *BinanceExecutionReportEvent, trade *Trade) {
|
|||
}
|
||||
|
||||
func (t *Trader) ReportPnL() {
|
||||
t.Context.UpdatePnL()
|
||||
|
||||
tradingCtx := t.Context
|
||||
logrus.Infof("current price: %s", USD.FormatMoneyFloat64(tradingCtx.CurrentPrice))
|
||||
logrus.Infof("average bid price: %s", USD.FormatMoneyFloat64(tradingCtx.AverageBidPrice))
|
||||
logrus.Infof("Stock volume: %f", tradingCtx.Stock)
|
||||
logrus.Infof("overall Profit: %s", USD.FormatMoneyFloat64(tradingCtx.Profit))
|
||||
report := tradingCtx.ProfitAndLossCalculator.Calculate()
|
||||
report.Print()
|
||||
|
||||
var color = ""
|
||||
if tradingCtx.Profit > 0 {
|
||||
if report.Profit > 0 {
|
||||
color = slackstyle.Green
|
||||
} else {
|
||||
color = slackstyle.Red
|
||||
|
@ -122,10 +118,10 @@ func (t *Trader) ReportPnL() {
|
|||
|
||||
_, _, err := t.Slack.PostMessageContext(context.Background(), t.TradingChannel,
|
||||
slack.MsgOptionText(util.Render(
|
||||
`:heavy_dollar_sign: Here is your *{{ .Symbol }}* PnL report collected since *{{ .startTime }}*`,
|
||||
`:heavy_dollar_sign: Here is your *{{ .symbol }}* PnL report collected since *{{ .startTime }}*`,
|
||||
map[string]interface{}{
|
||||
"Symbol": tradingCtx.Symbol,
|
||||
"startTime": tradingCtx.TradeStartTime.Format(time.RFC822),
|
||||
"symbol": tradingCtx.Symbol,
|
||||
"startTime": report.StartTime.Format(time.RFC822),
|
||||
}), true),
|
||||
slack.MsgOptionAttachments(slack.Attachment{
|
||||
Title: "Profit and Loss report",
|
||||
|
@ -140,31 +136,31 @@ func (t *Trader) ReportPnL() {
|
|||
},
|
||||
{
|
||||
Title: "Profit",
|
||||
Value: USD.FormatMoney(tradingCtx.Profit),
|
||||
Value: USD.FormatMoney(report.Profit),
|
||||
Short: true,
|
||||
},
|
||||
{
|
||||
Title: "Current Price",
|
||||
Value: USD.FormatMoney(tradingCtx.CurrentPrice),
|
||||
Value: USD.FormatMoney(report.CurrentPrice),
|
||||
Short: true,
|
||||
},
|
||||
{
|
||||
Title: "Average Bid Price",
|
||||
Value: USD.FormatMoney(tradingCtx.AverageBidPrice),
|
||||
Value: USD.FormatMoney(report.AverageBidPrice),
|
||||
Short: true,
|
||||
},
|
||||
{
|
||||
Title: "Current Stock",
|
||||
Value: tradingCtx.Market.FormatVolume(tradingCtx.Stock),
|
||||
Value: tradingCtx.Market.FormatVolume(report.Stock),
|
||||
Short: true,
|
||||
},
|
||||
{
|
||||
Title: "Number of Trades",
|
||||
Value: strconv.Itoa(len(tradingCtx.Trades)),
|
||||
Value: strconv.Itoa(report.NumTrades),
|
||||
Short: true,
|
||||
},
|
||||
},
|
||||
Footer: tradingCtx.TradeStartTime.Format(time.RFC822),
|
||||
Footer: report.StartTime.Format(time.RFC822),
|
||||
FooterIcon: "",
|
||||
}))
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user