mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-21 22:43:52 +00:00
pull out writeJsonFile function
This commit is contained in:
parent
24464fdcb6
commit
5f68064ac6
|
@ -81,6 +81,7 @@ func (c *AverageCostCalculator) Calculate(symbol string, trades []types.Trade, c
|
|||
|
||||
unrealizedProfit := currentPrice.Sub(position.AverageCost).
|
||||
Mul(position.GetBase())
|
||||
|
||||
return &AverageCostPnlReport{
|
||||
Symbol: symbol,
|
||||
Market: c.Market,
|
||||
|
|
|
@ -5,7 +5,7 @@ import (
|
|||
"strconv"
|
||||
"time"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/fatih/color"
|
||||
"github.com/slack-go/slack"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
|
@ -15,15 +15,15 @@ import (
|
|||
)
|
||||
|
||||
type AverageCostPnlReport struct {
|
||||
LastPrice fixedpoint.Value `json:"lastPrice"`
|
||||
StartTime time.Time `json:"startTime"`
|
||||
Symbol string `json:"symbol"`
|
||||
Market types.Market `json:"market"`
|
||||
LastPrice fixedpoint.Value `json:"lastPrice"`
|
||||
StartTime time.Time `json:"startTime"`
|
||||
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"`
|
||||
NetProfit fixedpoint.Value `json:"netProfit"`
|
||||
UnrealizedProfit fixedpoint.Value `json:"unrealizedProfit"`
|
||||
AverageCost fixedpoint.Value `json:"averageCost"`
|
||||
BuyVolume fixedpoint.Value `json:"buyVolume,omitempty"`
|
||||
SellVolume fixedpoint.Value `json:"sellVolume,omitempty"`
|
||||
|
@ -37,19 +37,29 @@ func (report *AverageCostPnlReport) JSON() ([]byte, error) {
|
|||
}
|
||||
|
||||
func (report AverageCostPnlReport) Print() {
|
||||
log.Infof("TRADES SINCE: %v", report.StartTime)
|
||||
log.Infof("NUMBER OF TRADES: %d", report.NumTrades)
|
||||
log.Infof("AVERAGE COST: %s", types.USD.FormatMoney(report.AverageCost))
|
||||
log.Infof("TOTAL BUY VOLUME: %v", report.BuyVolume)
|
||||
log.Infof("TOTAL SELL VOLUME: %v", report.SellVolume)
|
||||
color.Green("TRADES SINCE: %v", report.StartTime)
|
||||
color.Green("NUMBER OF TRADES: %d", report.NumTrades)
|
||||
color.Green("AVERAGE COST: %s", types.USD.FormatMoney(report.AverageCost))
|
||||
color.Green("TOTAL BUY VOLUME: %v", report.BuyVolume)
|
||||
color.Green("TOTAL SELL VOLUME: %v", report.SellVolume)
|
||||
|
||||
log.Infof("CURRENT PRICE: %s", types.USD.FormatMoney(report.LastPrice))
|
||||
log.Infof("CURRENCY FEES:")
|
||||
color.Green("CURRENT PRICE: %s", types.USD.FormatMoney(report.LastPrice))
|
||||
color.Green("CURRENCY FEES:")
|
||||
for currency, fee := range report.CurrencyFees {
|
||||
log.Infof(" - %s: %s", currency, fee.String())
|
||||
color.Green(" - %s: %s", currency, fee.String())
|
||||
}
|
||||
|
||||
if report.Profit.Sign() > 0 {
|
||||
color.Green("PROFIT: %s", types.USD.FormatMoney(report.Profit))
|
||||
} else {
|
||||
color.Red("PROFIT: %s", types.USD.FormatMoney(report.Profit))
|
||||
}
|
||||
|
||||
if report.UnrealizedProfit.Sign() > 0 {
|
||||
color.Green("UNREALIZED PROFIT: %s", types.USD.FormatMoney(report.UnrealizedProfit))
|
||||
} else {
|
||||
color.Red("UNREALIZED PROFIT: %s", types.USD.FormatMoney(report.UnrealizedProfit))
|
||||
}
|
||||
log.Infof("PROFIT: %s", types.USD.FormatMoney(report.Profit))
|
||||
log.Infof("UNREALIZED PROFIT: %s", types.USD.FormatMoney(report.UnrealizedProfit))
|
||||
}
|
||||
|
||||
func (report AverageCostPnlReport) SlackAttachment() slack.Attachment {
|
||||
|
|
|
@ -10,7 +10,18 @@ import (
|
|||
"github.com/c9s/bbgo/pkg/types"
|
||||
)
|
||||
|
||||
type Report struct {
|
||||
// SummaryReport is the summary of the back-test session
|
||||
type SummaryReport struct {
|
||||
StartTime time.Time `json:"startTime"`
|
||||
EndTime time.Time `json:"endTime"`
|
||||
Sessions []string `json:"sessions"`
|
||||
InitialTotalBalances types.BalanceMap `json:"initialTotalBalances"`
|
||||
FinalTotalBalances types.BalanceMap `json:"finalTotalBalances"`
|
||||
}
|
||||
|
||||
// SessionSymbolReport is the report per exchange session
|
||||
// trades are merged, collected and re-calculated
|
||||
type SessionSymbolReport struct {
|
||||
StartTime time.Time `json:"startTime"`
|
||||
EndTime time.Time `json:"endTime"`
|
||||
Symbol string `json:"symbol,omitempty"`
|
||||
|
|
|
@ -104,13 +104,22 @@ type Backtest struct {
|
|||
EndTime *types.LooseFormatTime `json:"endTime,omitempty" yaml:"endTime,omitempty"`
|
||||
|
||||
// RecordTrades is an option, if set to true, back-testing should record the trades into database
|
||||
RecordTrades bool `json:"recordTrades,omitempty" yaml:"recordTrades,omitempty"`
|
||||
RecordTrades bool `json:"recordTrades,omitempty" yaml:"recordTrades,omitempty"`
|
||||
|
||||
// Account is deprecated, use Accounts instead
|
||||
Account map[string]BacktestAccount `json:"account" yaml:"account"`
|
||||
Accounts map[string]BacktestAccount `json:"accounts" yaml:"accounts"`
|
||||
Symbols []string `json:"symbols" yaml:"symbols"`
|
||||
Sessions []string `json:"sessions" yaml:"sessions"`
|
||||
Account map[string]BacktestAccount `json:"account" yaml:"account"`
|
||||
Accounts map[string]BacktestAccount `json:"accounts" yaml:"accounts"`
|
||||
Symbols []string `json:"symbols" yaml:"symbols"`
|
||||
Sessions []string `json:"sessions" yaml:"sessions"`
|
||||
}
|
||||
|
||||
func (b *Backtest) GetAccount(n string) BacktestAccount {
|
||||
accountConfig, ok := b.Accounts[n]
|
||||
if ok {
|
||||
return accountConfig
|
||||
}
|
||||
|
||||
return b.Account[n]
|
||||
}
|
||||
|
||||
type BacktestAccount struct {
|
||||
|
|
|
@ -432,12 +432,43 @@ var BacktestCmd = &cobra.Command{
|
|||
// put the logger back to print the pnl
|
||||
log.SetLevel(log.InfoLevel)
|
||||
|
||||
log.Infof("BACK-TEST REPORT")
|
||||
log.Infof("===============================================")
|
||||
log.Infof("START TIME: %s", startTime.Format(time.RFC1123))
|
||||
log.Infof("END TIME: %s", endTime.Format(time.RFC1123))
|
||||
color.Green("BACK-TEST REPORT")
|
||||
color.Green("===============================================\n")
|
||||
color.Green("START TIME: %s\n", startTime.Format(time.RFC1123))
|
||||
color.Green("END TIME: %s\n", endTime.Format(time.RFC1123))
|
||||
|
||||
// aggregate total balances
|
||||
initTotalBalances := types.BalanceMap{}
|
||||
finalTotalBalances := types.BalanceMap{}
|
||||
sessionNames := []string{}
|
||||
for _, session := range environ.Sessions() {
|
||||
backtestExchange := session.Exchange.(*backtest.Exchange)
|
||||
sessionNames = append(sessionNames, session.Name)
|
||||
accountConfig := userConfig.Backtest.GetAccount(session.Name)
|
||||
initBalances := accountConfig.Balances.BalanceMap()
|
||||
initTotalBalances = initTotalBalances.Add(initBalances)
|
||||
|
||||
finalBalances := session.GetAccount().Balances()
|
||||
finalTotalBalances = finalTotalBalances.Add(finalBalances)
|
||||
}
|
||||
color.Green("INITIAL TOTAL BALANCE: %v\n", initTotalBalances)
|
||||
color.Green("FINAL TOTAL BALANCE: %v\n", finalTotalBalances)
|
||||
|
||||
summaryReport := &backtest.SummaryReport{
|
||||
StartTime: startTime,
|
||||
EndTime: endTime,
|
||||
Sessions: sessionNames,
|
||||
InitialTotalBalances: initTotalBalances,
|
||||
FinalTotalBalances: finalTotalBalances,
|
||||
}
|
||||
_ = summaryReport
|
||||
|
||||
for _, session := range environ.Sessions() {
|
||||
backtestExchange, ok := session.Exchange.(*backtest.Exchange)
|
||||
if !ok {
|
||||
return fmt.Errorf("unexpected error, exchange instance is not a backtest exchange")
|
||||
}
|
||||
|
||||
// per symbol report
|
||||
exchangeName := session.Exchange.Name().String()
|
||||
for symbol, trades := range session.Trades {
|
||||
market, ok := session.Market(symbol)
|
||||
|
@ -466,22 +497,12 @@ var BacktestCmd = &cobra.Command{
|
|||
report := calculator.Calculate(symbol, trades.Trades, lastPrice)
|
||||
report.Print()
|
||||
|
||||
accountConfig, ok := userConfig.Backtest.Accounts[exchangeName]
|
||||
if !ok {
|
||||
accountConfig = userConfig.Backtest.Account[exchangeName]
|
||||
}
|
||||
|
||||
accountConfig := userConfig.Backtest.GetAccount(exchangeName)
|
||||
initBalances := accountConfig.Balances.BalanceMap()
|
||||
finalBalances := session.GetAccount().Balances()
|
||||
|
||||
log.Infof("INITIAL BALANCES:")
|
||||
initBalances.Print()
|
||||
|
||||
log.Infof("FINAL BALANCES:")
|
||||
finalBalances.Print()
|
||||
|
||||
if generatingReport {
|
||||
result := backtest.Report{
|
||||
result := backtest.SessionSymbolReport{
|
||||
StartTime: startTime,
|
||||
EndTime: endTime,
|
||||
Symbol: symbol,
|
||||
|
@ -493,20 +514,15 @@ var BacktestCmd = &cobra.Command{
|
|||
Manifests: manifests,
|
||||
}
|
||||
|
||||
jsonOutput, err := json.MarshalIndent(&result, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(filepath.Join(outputDirectory, symbol+".json"), jsonOutput, 0644); err != nil {
|
||||
if err := writeJsonFile(filepath.Join(outputDirectory, symbol+".json"), &result) ; err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
initQuoteAsset := inQuoteAsset(initBalances, market, startPrice)
|
||||
finalQuoteAsset := inQuoteAsset(finalBalances, market, lastPrice)
|
||||
log.Infof("INITIAL ASSET IN %s ~= %s %s (1 %s = %v)", market.QuoteCurrency, market.FormatQuantity(initQuoteAsset), market.QuoteCurrency, market.BaseCurrency, startPrice)
|
||||
log.Infof("FINAL ASSET IN %s ~= %s %s (1 %s = %v)", market.QuoteCurrency, market.FormatQuantity(finalQuoteAsset), market.QuoteCurrency, market.BaseCurrency, lastPrice)
|
||||
color.Green("INITIAL ASSET IN %s ~= %s %s (1 %s = %v)", market.QuoteCurrency, market.FormatQuantity(initQuoteAsset), market.QuoteCurrency, market.BaseCurrency, startPrice)
|
||||
color.Green("FINAL ASSET IN %s ~= %s %s (1 %s = %v)", market.QuoteCurrency, market.FormatQuantity(finalQuoteAsset), market.QuoteCurrency, market.BaseCurrency, lastPrice)
|
||||
|
||||
if report.Profit.Sign() > 0 {
|
||||
color.Green("REALIZED PROFIT: +%v %s", report.Profit, market.QuoteCurrency)
|
||||
|
@ -577,6 +593,15 @@ func confirmation(s string) bool {
|
|||
}
|
||||
}
|
||||
|
||||
func writeJsonFile(p string, obj interface{}) error {
|
||||
out, err := json.MarshalIndent(obj, "", " ")
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return ioutil.WriteFile(p, out, 0644)
|
||||
}
|
||||
|
||||
func safeMkdirAll(p string) error {
|
||||
st, err := os.Stat(p)
|
||||
if err == nil {
|
||||
|
|
|
@ -6,8 +6,6 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/sirupsen/logrus"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||
)
|
||||
|
||||
|
@ -193,11 +191,15 @@ func (m BalanceMap) Print() {
|
|||
continue
|
||||
}
|
||||
|
||||
fmt.Printf(" %s: %v", balance.Currency, balance.Available)
|
||||
if balance.Locked.Sign() > 0 {
|
||||
logrus.Infof(" %s: %v (locked %v)", balance.Currency, balance.Available, balance.Locked)
|
||||
} else {
|
||||
logrus.Infof(" %s: %v", balance.Currency, balance.Available)
|
||||
fmt.Printf(" (locked %v)", balance.Locked)
|
||||
}
|
||||
|
||||
if balance.Borrowed.Sign() > 0 {
|
||||
fmt.Printf(" (borrowed %v)", balance.Borrowed)
|
||||
}
|
||||
fmt.Println()
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user