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
|
||||
}
|
||||
|
||||
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.
|
||||
var bidVolume = fixedpoint.Zero
|
||||
var askVolume = fixedpoint.Zero
|
||||
|
@ -23,7 +23,7 @@ func (c *AverageCostCalculator) Calculate(symbol string, trades []types.Trade, c
|
|||
var grossLoss = fixedpoint.Zero
|
||||
|
||||
if len(trades) == 0 {
|
||||
return &AverageCostPnlReport{
|
||||
return &AverageCostPnLReport{
|
||||
Symbol: symbol,
|
||||
Market: c.Market,
|
||||
LastPrice: currentPrice,
|
||||
|
@ -90,12 +90,13 @@ func (c *AverageCostCalculator) Calculate(symbol string, trades []types.Trade, c
|
|||
unrealizedProfit := currentPrice.Sub(position.AverageCost).
|
||||
Mul(position.GetBase())
|
||||
|
||||
return &AverageCostPnlReport{
|
||||
return &AverageCostPnLReport{
|
||||
Symbol: symbol,
|
||||
Market: c.Market,
|
||||
LastPrice: currentPrice,
|
||||
NumTrades: len(trades),
|
||||
StartTime: time.Time(trades[0].Time),
|
||||
Position: position,
|
||||
|
||||
BuyVolume: bidVolume,
|
||||
SellVolume: askVolume,
|
||||
|
|
|
@ -14,7 +14,7 @@ import (
|
|||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
type AverageCostPnlReport struct {
|
||||
type AverageCostPnLReport struct {
|
||||
LastPrice fixedpoint.Value `json:"lastPrice"`
|
||||
StartTime time.Time `json:"startTime"`
|
||||
Symbol string `json:"symbol"`
|
||||
|
@ -27,6 +27,7 @@ type AverageCostPnlReport struct {
|
|||
NetProfit fixedpoint.Value `json:"netProfit"`
|
||||
GrossProfit fixedpoint.Value `json:"grossProfit"`
|
||||
GrossLoss fixedpoint.Value `json:"grossLoss"`
|
||||
Position *types.Position `json:"position,omitempty"`
|
||||
|
||||
AverageCost fixedpoint.Value `json:"averageCost"`
|
||||
BuyVolume fixedpoint.Value `json:"buyVolume,omitempty"`
|
||||
|
@ -36,14 +37,14 @@ type AverageCostPnlReport struct {
|
|||
CurrencyFees map[string]fixedpoint.Value `json:"currencyFees"`
|
||||
}
|
||||
|
||||
func (report *AverageCostPnlReport) JSON() ([]byte, error) {
|
||||
func (report *AverageCostPnLReport) JSON() ([]byte, error) {
|
||||
return json.MarshalIndent(report, "", " ")
|
||||
}
|
||||
|
||||
func (report AverageCostPnlReport) Print() {
|
||||
func (report AverageCostPnLReport) Print() {
|
||||
color.Green("TRADES SINCE: %v", report.StartTime)
|
||||
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("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
|
||||
|
||||
if report.UnrealizedProfit.Sign() > 0 {
|
||||
|
|
|
@ -277,9 +277,15 @@ func (m *SimplePriceMatching) executeTrade(trade types.Trade) {
|
|||
if trade.IsBuyer {
|
||||
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
|
||||
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)
|
||||
}
|
||||
|
||||
|
@ -287,11 +293,17 @@ func (m *SimplePriceMatching) executeTrade(trade types.Trade) {
|
|||
} else {
|
||||
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
|
||||
if trade.FeeCurrency == m.Market.QuoteCurrency {
|
||||
switch trade.FeeCurrency {
|
||||
case m.Market.QuoteCurrency:
|
||||
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)
|
||||
}
|
||||
|
||||
|
|
|
@ -75,7 +75,7 @@ type SessionSymbolReport struct {
|
|||
Market types.Market `json:"market"`
|
||||
LastPrice fixedpoint.Value `json:"lastPrice,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"`
|
||||
FinalBalances types.BalanceMap `json:"finalBalances,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("INITIAL TOTAL BALANCE: %v\n", initTotalBalances)
|
||||
color.Green("FINAL TOTAL BALANCE: %v\n", finalTotalBalances)
|
||||
|
||||
for _, symbolReport := range summaryReport.SymbolReports {
|
||||
symbolReport.Print(wantBaseAssetBaseline)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue
Block a user