Skip to content

Commit

Permalink
backtest: add gross profit and gross loss fields
Browse files Browse the repository at this point in the history
  • Loading branch information
c9s committed Jul 12, 2022
1 parent 7d232f8 commit a51f26e
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 12 deletions.
18 changes: 15 additions & 3 deletions pkg/accounting/pnl/avg_cost.go
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@ func (c *AverageCostCalculator) Calculate(symbol string, trades []types.Trade, c
var bidVolume = fixedpoint.Zero
var askVolume = fixedpoint.Zero
var feeUSD = fixedpoint.Zero
var grossProfit = fixedpoint.Zero
var grossLoss = fixedpoint.Zero

if len(trades) == 0 {
return &AverageCostPnlReport{
Expand Down Expand Up @@ -64,6 +66,12 @@ func (c *AverageCostCalculator) Calculate(symbol string, trades []types.Trade, c
totalNetProfit = totalNetProfit.Add(netProfit)
}

if profit.Sign() > 0 {
grossProfit = grossProfit.Add(profit)
} else if profit.Sign() < 0 {
grossLoss = grossLoss.Add(profit)
}

if trade.IsBuyer {
bidVolume = bidVolume.Add(trade.Quantity)
} else {
Expand Down Expand Up @@ -96,8 +104,12 @@ func (c *AverageCostCalculator) Calculate(symbol string, trades []types.Trade, c
Profit: totalProfit,
NetProfit: totalNetProfit,
UnrealizedProfit: unrealizedProfit,
AverageCost: position.AverageCost,
FeeInUSD: totalProfit.Sub(totalNetProfit),
CurrencyFees: currencyFees,

GrossProfit: grossProfit,
GrossLoss: grossLoss,

AverageCost: position.AverageCost,
FeeInUSD: totalProfit.Sub(totalNetProfit),
CurrencyFees: currencyFees,
}
}
12 changes: 8 additions & 4 deletions pkg/accounting/pnl/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@ type AverageCostPnlReport struct {
Symbol string `json:"symbol"`
Market types.Market `json:"market"`

NumTrades int `json:"numTrades"`
Profit fixedpoint.Value `json:"profit"`
NetProfit fixedpoint.Value `json:"netProfit"`
UnrealizedProfit fixedpoint.Value `json:"unrealizedProfit"`
NumTrades int `json:"numTrades"`
Profit fixedpoint.Value `json:"profit"`
UnrealizedProfit fixedpoint.Value `json:"unrealizedProfit"`

NetProfit fixedpoint.Value `json:"netProfit"`
GrossProfit fixedpoint.Value `json:"grossProfit"`
GrossLoss fixedpoint.Value `json:"grossLoss"`

AverageCost fixedpoint.Value `json:"averageCost"`
BuyVolume fixedpoint.Value `json:"buyVolume,omitempty"`
SellVolume fixedpoint.Value `json:"sellVolume,omitempty"`
Expand Down
22 changes: 18 additions & 4 deletions pkg/backtest/report.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,16 @@ type SummaryReport struct {
InitialTotalBalances types.BalanceMap `json:"initialTotalBalances"`
FinalTotalBalances types.BalanceMap `json:"finalTotalBalances"`

InitialEquityValue fixedpoint.Value `json:"initialEquityValue"`
FinalEquityValue fixedpoint.Value `json:"finalEquityValue"`

// TotalProfit is the profit aggregated from the symbol reports
TotalProfit fixedpoint.Value `json:"totalProfit,omitempty"`
TotalUnrealizedProfit fixedpoint.Value `json:"totalUnrealizedProfit,omitempty"`

TotalGrossProfit fixedpoint.Value `json:"totalGrossProfit,omitempty"`
TotalGrossLoss fixedpoint.Value `json:"totalGrossLoss,omitempty"`

SymbolReports []SessionSymbolReport `json:"symbolReports,omitempty"`

Manifests Manifests `json:"manifests,omitempty"`
Expand Down Expand Up @@ -75,13 +81,21 @@ type SessionSymbolReport struct {
Manifests Manifests `json:"manifests,omitempty"`
}

func (r *SessionSymbolReport) InitialEquityValue() fixedpoint.Value {
return InQuoteAsset(r.InitialBalances, r.Market, r.StartPrice)
}

func (r *SessionSymbolReport) FinalEquityValue() fixedpoint.Value {
return InQuoteAsset(r.FinalBalances, r.Market, r.StartPrice)
}

func (r *SessionSymbolReport) Print(wantBaseAssetBaseline bool) {
color.Green("%s %s PROFIT AND LOSS REPORT", r.Exchange, r.Symbol)
color.Green("===============================================")
r.PnL.Print()

initQuoteAsset := inQuoteAsset(r.InitialBalances, r.Market, r.StartPrice)
finalQuoteAsset := inQuoteAsset(r.FinalBalances, r.Market, r.LastPrice)
initQuoteAsset := r.InitialEquityValue()
finalQuoteAsset := r.FinalEquityValue()
color.Green("INITIAL ASSET IN %s ~= %s %s (1 %s = %v)", r.Market.QuoteCurrency, r.Market.FormatQuantity(initQuoteAsset), r.Market.QuoteCurrency, r.Market.BaseCurrency, r.StartPrice)
color.Green("FINAL ASSET IN %s ~= %s %s (1 %s = %v)", r.Market.QuoteCurrency, r.Market.FormatQuantity(finalQuoteAsset), r.Market.QuoteCurrency, r.Market.BaseCurrency, r.LastPrice)

Expand Down Expand Up @@ -186,8 +200,8 @@ func AddReportIndexRun(outputDirectory string, run Run) error {
return WriteReportIndex(outputDirectory, reportIndex)
}

// inQuoteAsset converts all balances in quote asset
func inQuoteAsset(balances types.BalanceMap, market types.Market, price fixedpoint.Value) fixedpoint.Value {
// InQuoteAsset converts all balances in quote asset
func InQuoteAsset(balances types.BalanceMap, market types.Market, price fixedpoint.Value) fixedpoint.Value {
quote := balances[market.QuoteCurrency]
base := balances[market.BaseCurrency]
return base.Total().Mul(price).Add(quote.Total())
Expand Down
5 changes: 4 additions & 1 deletion pkg/cmd/backtest.go
Original file line number Diff line number Diff line change
Expand Up @@ -493,7 +493,6 @@ var BacktestCmd = &cobra.Command{
}

for _, session := range environ.Sessions() {

for symbol, trades := range session.Trades {
symbolReport, err := createSymbolReport(userConfig, session, symbol, trades.Trades)
if err != nil {
Expand All @@ -504,6 +503,10 @@ var BacktestCmd = &cobra.Command{
summaryReport.SymbolReports = append(summaryReport.SymbolReports, *symbolReport)
summaryReport.TotalProfit = symbolReport.PnL.Profit
summaryReport.TotalUnrealizedProfit = symbolReport.PnL.UnrealizedProfit
summaryReport.InitialEquityValue = summaryReport.InitialEquityValue.Add(symbolReport.InitialEquityValue())
summaryReport.FinalEquityValue = summaryReport.FinalEquityValue.Add(symbolReport.FinalEquityValue())
summaryReport.TotalGrossProfit.Add(symbolReport.PnL.GrossProfit)
summaryReport.TotalGrossLoss.Add(symbolReport.PnL.GrossLoss)

// write report to a file
if generatingReport {
Expand Down

0 comments on commit a51f26e

Please sign in to comment.