mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-22 14:55:16 +00:00
optimize single exchange back-test
This commit is contained in:
parent
e527dd8dde
commit
6f16f32e16
8
pkg/backtest/exchange_klinec.go
Normal file
8
pkg/backtest/exchange_klinec.go
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
package backtest
|
||||||
|
|
||||||
|
import "github.com/c9s/bbgo/pkg/types"
|
||||||
|
|
||||||
|
type ExchangeDataSource struct {
|
||||||
|
C chan types.KLine
|
||||||
|
Exchange *Exchange
|
||||||
|
}
|
16
pkg/backtest/report.go
Normal file
16
pkg/backtest/report.go
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
package backtest
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/c9s/bbgo/pkg/accounting/pnl"
|
||||||
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
|
)
|
||||||
|
|
||||||
|
type BackTestReport struct {
|
||||||
|
Symbol string `json:"symbol,omitempty"`
|
||||||
|
LastPrice fixedpoint.Value `json:"lastPrice,omitempty"`
|
||||||
|
StartPrice fixedpoint.Value `json:"startPrice,omitempty"`
|
||||||
|
PnLReport *pnl.AverageCostPnlReport `json:"pnlReport,omitempty"`
|
||||||
|
InitialBalances types.BalanceMap `json:"initialBalances,omitempty"`
|
||||||
|
FinalBalances types.BalanceMap `json:"finalBalances,omitempty"`
|
||||||
|
}
|
|
@ -22,20 +22,10 @@ import (
|
||||||
"github.com/c9s/bbgo/pkg/backtest"
|
"github.com/c9s/bbgo/pkg/backtest"
|
||||||
"github.com/c9s/bbgo/pkg/bbgo"
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
"github.com/c9s/bbgo/pkg/cmd/cmdutil"
|
"github.com/c9s/bbgo/pkg/cmd/cmdutil"
|
||||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
|
||||||
"github.com/c9s/bbgo/pkg/service"
|
"github.com/c9s/bbgo/pkg/service"
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type BackTestReport struct {
|
|
||||||
Symbol string `json:"symbol,omitempty"`
|
|
||||||
LastPrice fixedpoint.Value `json:"lastPrice,omitempty"`
|
|
||||||
StartPrice fixedpoint.Value `json:"startPrice,omitempty"`
|
|
||||||
PnLReport *pnl.AverageCostPnlReport `json:"pnlReport,omitempty"`
|
|
||||||
InitialBalances types.BalanceMap `json:"initialBalances,omitempty"`
|
|
||||||
FinalBalances types.BalanceMap `json:"finalBalances,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
BacktestCmd.Flags().Bool("sync", false, "sync backtest data")
|
BacktestCmd.Flags().Bool("sync", false, "sync backtest data")
|
||||||
BacktestCmd.Flags().Bool("sync-only", false, "sync backtest data only, do not run backtest")
|
BacktestCmd.Flags().Bool("sync-only", false, "sync backtest data only, do not run backtest")
|
||||||
|
@ -53,7 +43,7 @@ func init() {
|
||||||
|
|
||||||
var BacktestCmd = &cobra.Command{
|
var BacktestCmd = &cobra.Command{
|
||||||
Use: "backtest",
|
Use: "backtest",
|
||||||
Short: "backtest your strategies",
|
Short: "run backtest with strategies",
|
||||||
SilenceUsage: true,
|
SilenceUsage: true,
|
||||||
RunE: func(cmd *cobra.Command, args []string) error {
|
RunE: func(cmd *cobra.Command, args []string) error {
|
||||||
verboseCnt, err := cmd.Flags().GetCount("verbose")
|
verboseCnt, err := cmd.Flags().GetCount("verbose")
|
||||||
|
@ -99,6 +89,9 @@ var BacktestCmd = &cobra.Command{
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
kLineDirectory := filepath.Join(outputDirectory, "klines")
|
||||||
|
_ = kLineDirectory
|
||||||
|
|
||||||
jsonOutputEnabled := len(outputDirectory) > 0
|
jsonOutputEnabled := len(outputDirectory) > 0
|
||||||
|
|
||||||
syncOnly, err := cmd.Flags().GetBool("sync-only")
|
syncOnly, err := cmd.Flags().GetBool("sync-only")
|
||||||
|
@ -317,37 +310,47 @@ var BacktestCmd = &cobra.Command{
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
type KChanEx struct {
|
|
||||||
KChan chan types.KLine
|
|
||||||
Exchange *backtest.Exchange
|
|
||||||
}
|
|
||||||
for _, session := range environ.Sessions() {
|
for _, session := range environ.Sessions() {
|
||||||
backtestExchange := session.Exchange.(*backtest.Exchange)
|
backtestExchange := session.Exchange.(*backtest.Exchange)
|
||||||
backtestExchange.InitMarketData()
|
backtestExchange.InitMarketData()
|
||||||
}
|
}
|
||||||
|
|
||||||
var klineChans []KChanEx
|
var exchangeSources []backtest.ExchangeDataSource
|
||||||
for _, session := range environ.Sessions() {
|
for _, session := range environ.Sessions() {
|
||||||
exchange := session.Exchange.(*backtest.Exchange)
|
exchange := session.Exchange.(*backtest.Exchange)
|
||||||
c, err := exchange.GetMarketData()
|
c, err := exchange.GetMarketData()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
klineChans = append(klineChans, KChanEx{KChan: c, Exchange: exchange})
|
exchangeSources = append(exchangeSources, backtest.ExchangeDataSource{C: c, Exchange: exchange})
|
||||||
}
|
}
|
||||||
|
|
||||||
runCtx, cancelRun := context.WithCancel(ctx)
|
runCtx, cancelRun := context.WithCancel(ctx)
|
||||||
go func() {
|
go func() {
|
||||||
defer cancelRun()
|
defer cancelRun()
|
||||||
|
|
||||||
|
// Optimize back-test speed for single exchange source
|
||||||
|
var count = len(exchangeSources)
|
||||||
|
if count == 1 {
|
||||||
|
exSource := exchangeSources[0]
|
||||||
|
for k := range exSource.C {
|
||||||
|
exSource.Exchange.ConsumeKLine(k)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := exSource.Exchange.CloseMarketData(); err != nil {
|
||||||
|
log.WithError(err).Errorf("close market data error")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
count := len(klineChans)
|
for _, exK := range exchangeSources {
|
||||||
for _, kchanex := range klineChans {
|
kLine, more := <-exK.C
|
||||||
kLine, more := <-kchanex.KChan
|
|
||||||
if more {
|
if more {
|
||||||
kchanex.Exchange.ConsumeKLine(kLine)
|
exK.Exchange.ConsumeKLine(kLine)
|
||||||
} else {
|
} else {
|
||||||
if err := kchanex.Exchange.CloseMarketData(); err != nil {
|
if err := exK.Exchange.CloseMarketData(); err != nil {
|
||||||
log.Errorf("%v", err)
|
log.WithError(err).Errorf("close market data error")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
count--
|
count--
|
||||||
|
@ -397,7 +400,7 @@ var BacktestCmd = &cobra.Command{
|
||||||
|
|
||||||
report := calculator.Calculate(symbol, trades.Trades, lastPrice)
|
report := calculator.Calculate(symbol, trades.Trades, lastPrice)
|
||||||
report.Print()
|
report.Print()
|
||||||
|
|
||||||
accountConfig, ok := userConfig.Backtest.Accounts[exchangeName]
|
accountConfig, ok := userConfig.Backtest.Accounts[exchangeName]
|
||||||
if !ok {
|
if !ok {
|
||||||
accountConfig = userConfig.Backtest.Account[exchangeName]
|
accountConfig = userConfig.Backtest.Account[exchangeName]
|
||||||
|
@ -413,7 +416,7 @@ var BacktestCmd = &cobra.Command{
|
||||||
finalBalances.Print()
|
finalBalances.Print()
|
||||||
|
|
||||||
if jsonOutputEnabled {
|
if jsonOutputEnabled {
|
||||||
result := BackTestReport{
|
result := backtest.BackTestReport{
|
||||||
Symbol: symbol,
|
Symbol: symbol,
|
||||||
LastPrice: lastPrice,
|
LastPrice: lastPrice,
|
||||||
StartPrice: startPrice,
|
StartPrice: startPrice,
|
||||||
|
|
Loading…
Reference in New Issue
Block a user