mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-25 00:05:15 +00:00
backtest,accounting: add position info to the average cost pnl report
This commit is contained in:
parent
45fb87f2b8
commit
d2f9a352a2
|
@ -14,7 +14,7 @@ type AverageCostCalculator struct {
|
||||||
Market types.Market
|
Market types.Market
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *AverageCostCalculator) Calculate(symbol string, trades []types.Trade, currentPrice fixedpoint.Value) *AverageCostPnlReport {
|
func (c *AverageCostCalculator) Calculate(symbol string, trades []types.Trade, currentPrice fixedpoint.Value) *AverageCostPnLReport {
|
||||||
// copy trades, so that we can truncate it.
|
// copy trades, so that we can truncate it.
|
||||||
var bidVolume = fixedpoint.Zero
|
var bidVolume = fixedpoint.Zero
|
||||||
var askVolume = fixedpoint.Zero
|
var askVolume = fixedpoint.Zero
|
||||||
|
@ -23,7 +23,7 @@ func (c *AverageCostCalculator) Calculate(symbol string, trades []types.Trade, c
|
||||||
var grossLoss = fixedpoint.Zero
|
var grossLoss = fixedpoint.Zero
|
||||||
|
|
||||||
if len(trades) == 0 {
|
if len(trades) == 0 {
|
||||||
return &AverageCostPnlReport{
|
return &AverageCostPnLReport{
|
||||||
Symbol: symbol,
|
Symbol: symbol,
|
||||||
Market: c.Market,
|
Market: c.Market,
|
||||||
LastPrice: currentPrice,
|
LastPrice: currentPrice,
|
||||||
|
@ -90,12 +90,13 @@ func (c *AverageCostCalculator) Calculate(symbol string, trades []types.Trade, c
|
||||||
unrealizedProfit := currentPrice.Sub(position.AverageCost).
|
unrealizedProfit := currentPrice.Sub(position.AverageCost).
|
||||||
Mul(position.GetBase())
|
Mul(position.GetBase())
|
||||||
|
|
||||||
return &AverageCostPnlReport{
|
return &AverageCostPnLReport{
|
||||||
Symbol: symbol,
|
Symbol: symbol,
|
||||||
Market: c.Market,
|
Market: c.Market,
|
||||||
LastPrice: currentPrice,
|
LastPrice: currentPrice,
|
||||||
NumTrades: len(trades),
|
NumTrades: len(trades),
|
||||||
StartTime: time.Time(trades[0].Time),
|
StartTime: time.Time(trades[0].Time),
|
||||||
|
Position: position,
|
||||||
|
|
||||||
BuyVolume: bidVolume,
|
BuyVolume: bidVolume,
|
||||||
SellVolume: askVolume,
|
SellVolume: askVolume,
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type AverageCostPnlReport struct {
|
type AverageCostPnLReport struct {
|
||||||
LastPrice fixedpoint.Value `json:"lastPrice"`
|
LastPrice fixedpoint.Value `json:"lastPrice"`
|
||||||
StartTime time.Time `json:"startTime"`
|
StartTime time.Time `json:"startTime"`
|
||||||
Symbol string `json:"symbol"`
|
Symbol string `json:"symbol"`
|
||||||
|
@ -27,6 +27,7 @@ type AverageCostPnlReport struct {
|
||||||
NetProfit fixedpoint.Value `json:"netProfit"`
|
NetProfit fixedpoint.Value `json:"netProfit"`
|
||||||
GrossProfit fixedpoint.Value `json:"grossProfit"`
|
GrossProfit fixedpoint.Value `json:"grossProfit"`
|
||||||
GrossLoss fixedpoint.Value `json:"grossLoss"`
|
GrossLoss fixedpoint.Value `json:"grossLoss"`
|
||||||
|
Position *types.Position `json:"position,omitempty"`
|
||||||
|
|
||||||
AverageCost fixedpoint.Value `json:"averageCost"`
|
AverageCost fixedpoint.Value `json:"averageCost"`
|
||||||
BuyVolume fixedpoint.Value `json:"buyVolume,omitempty"`
|
BuyVolume fixedpoint.Value `json:"buyVolume,omitempty"`
|
||||||
|
@ -36,14 +37,14 @@ type AverageCostPnlReport struct {
|
||||||
CurrencyFees map[string]fixedpoint.Value `json:"currencyFees"`
|
CurrencyFees map[string]fixedpoint.Value `json:"currencyFees"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (report *AverageCostPnlReport) JSON() ([]byte, error) {
|
func (report *AverageCostPnLReport) JSON() ([]byte, error) {
|
||||||
return json.MarshalIndent(report, "", " ")
|
return json.MarshalIndent(report, "", " ")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (report AverageCostPnlReport) Print() {
|
func (report AverageCostPnLReport) Print() {
|
||||||
color.Green("TRADES SINCE: %v", report.StartTime)
|
color.Green("TRADES SINCE: %v", report.StartTime)
|
||||||
color.Green("NUMBER OF TRADES: %d", report.NumTrades)
|
color.Green("NUMBER OF TRADES: %d", report.NumTrades)
|
||||||
|
color.Green(report.Position.String())
|
||||||
color.Green("AVERAGE COST: %s", types.USD.FormatMoney(report.AverageCost))
|
color.Green("AVERAGE COST: %s", types.USD.FormatMoney(report.AverageCost))
|
||||||
color.Green("BASE ASSET POSITION: %s", report.BaseAssetPosition.String())
|
color.Green("BASE ASSET POSITION: %s", report.BaseAssetPosition.String())
|
||||||
|
|
||||||
|
@ -69,7 +70,7 @@ func (report AverageCostPnlReport) Print() {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (report AverageCostPnlReport) SlackAttachment() slack.Attachment {
|
func (report AverageCostPnLReport) SlackAttachment() slack.Attachment {
|
||||||
var color = slackstyle.Red
|
var color = slackstyle.Red
|
||||||
|
|
||||||
if report.UnrealizedProfit.Sign() > 0 {
|
if report.UnrealizedProfit.Sign() > 0 {
|
||||||
|
|
|
@ -277,9 +277,15 @@ func (m *SimplePriceMatching) executeTrade(trade types.Trade) {
|
||||||
if trade.IsBuyer {
|
if trade.IsBuyer {
|
||||||
err = m.account.UseLockedBalance(m.Market.QuoteCurrency, trade.QuoteQuantity)
|
err = m.account.UseLockedBalance(m.Market.QuoteCurrency, trade.QuoteQuantity)
|
||||||
|
|
||||||
// here the fee currency is the base currency
|
// all-in buy trade, we can only deduct the fee from the quote quantity and re-calculate the base quantity
|
||||||
q := trade.Quantity
|
q := trade.Quantity
|
||||||
if trade.FeeCurrency == m.Market.BaseCurrency {
|
qq := trade.QuoteQuantity
|
||||||
|
switch trade.FeeCurrency {
|
||||||
|
case m.Market.QuoteCurrency:
|
||||||
|
quoteFee := trade.Fee
|
||||||
|
qq = qq.Sub(quoteFee)
|
||||||
|
q = qq.Div(trade.Price) // re-calculate the base quantity according to the quote quantity and fee.
|
||||||
|
case m.Market.BaseCurrency:
|
||||||
q = q.Sub(trade.Fee)
|
q = q.Sub(trade.Fee)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -287,11 +293,17 @@ func (m *SimplePriceMatching) executeTrade(trade types.Trade) {
|
||||||
} else {
|
} else {
|
||||||
err = m.account.UseLockedBalance(m.Market.BaseCurrency, trade.Quantity)
|
err = m.account.UseLockedBalance(m.Market.BaseCurrency, trade.Quantity)
|
||||||
|
|
||||||
// here the fee currency is the quote currency
|
// all-in sell trade
|
||||||
|
q := trade.Quantity
|
||||||
qq := trade.QuoteQuantity
|
qq := trade.QuoteQuantity
|
||||||
if trade.FeeCurrency == m.Market.QuoteCurrency {
|
switch trade.FeeCurrency {
|
||||||
|
case m.Market.QuoteCurrency:
|
||||||
qq = qq.Sub(trade.Fee)
|
qq = qq.Sub(trade.Fee)
|
||||||
|
case m.Market.BaseCurrency:
|
||||||
|
q = q.Sub(trade.Fee)
|
||||||
|
qq = q.Div(trade.Price)
|
||||||
}
|
}
|
||||||
|
|
||||||
m.account.AddBalance(m.Market.QuoteCurrency, qq)
|
m.account.AddBalance(m.Market.QuoteCurrency, qq)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -75,7 +75,7 @@ type SessionSymbolReport struct {
|
||||||
Market types.Market `json:"market"`
|
Market types.Market `json:"market"`
|
||||||
LastPrice fixedpoint.Value `json:"lastPrice,omitempty"`
|
LastPrice fixedpoint.Value `json:"lastPrice,omitempty"`
|
||||||
StartPrice fixedpoint.Value `json:"startPrice,omitempty"`
|
StartPrice fixedpoint.Value `json:"startPrice,omitempty"`
|
||||||
PnL *pnl.AverageCostPnlReport `json:"pnl,omitempty"`
|
PnL *pnl.AverageCostPnLReport `json:"pnl,omitempty"`
|
||||||
InitialBalances types.BalanceMap `json:"initialBalances,omitempty"`
|
InitialBalances types.BalanceMap `json:"initialBalances,omitempty"`
|
||||||
FinalBalances types.BalanceMap `json:"finalBalances,omitempty"`
|
FinalBalances types.BalanceMap `json:"finalBalances,omitempty"`
|
||||||
Manifests Manifests `json:"manifests,omitempty"`
|
Manifests Manifests `json:"manifests,omitempty"`
|
||||||
|
|
|
@ -583,7 +583,6 @@ var BacktestCmd = &cobra.Command{
|
||||||
color.Green("END TIME: %s\n", endTime.Format(time.RFC1123))
|
color.Green("END TIME: %s\n", endTime.Format(time.RFC1123))
|
||||||
color.Green("INITIAL TOTAL BALANCE: %v\n", initTotalBalances)
|
color.Green("INITIAL TOTAL BALANCE: %v\n", initTotalBalances)
|
||||||
color.Green("FINAL TOTAL BALANCE: %v\n", finalTotalBalances)
|
color.Green("FINAL TOTAL BALANCE: %v\n", finalTotalBalances)
|
||||||
|
|
||||||
for _, symbolReport := range summaryReport.SymbolReports {
|
for _, symbolReport := range summaryReport.SymbolReports {
|
||||||
symbolReport.Print(wantBaseAssetBaseline)
|
symbolReport.Print(wantBaseAssetBaseline)
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user