mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-10 09:11:55 +00:00
emit klines and setup account balances
This commit is contained in:
parent
22a214328d
commit
b13a2deec5
|
@ -58,17 +58,9 @@ backtest:
|
||||||
USDT: 5000.0
|
USDT: 5000.0
|
||||||
|
|
||||||
exchangeStrategies:
|
exchangeStrategies:
|
||||||
- on: binance
|
- on: max
|
||||||
buyandhold:
|
buyandhold:
|
||||||
symbol: "BTCUSDT"
|
symbol: "BTCUSDT"
|
||||||
interval: "1m"
|
interval: "1m"
|
||||||
baseQuantity: 0.01
|
baseQuantity: 0.01
|
||||||
minDropPercentage: -0.02
|
minDropPercentage: -0.02
|
||||||
- on: max
|
|
||||||
xpuremaker:
|
|
||||||
symbol: MAXUSDT
|
|
||||||
numOrders: 2
|
|
||||||
side: both
|
|
||||||
behindVolume: 1000.0
|
|
||||||
priceTick: 0.01
|
|
||||||
baseQuantity: 100.0
|
|
||||||
|
|
|
@ -6,6 +6,7 @@ import (
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
|
||||||
|
"github.com/c9s/bbgo/pkg/bbgo"
|
||||||
"github.com/c9s/bbgo/pkg/exchange/binance"
|
"github.com/c9s/bbgo/pkg/exchange/binance"
|
||||||
"github.com/c9s/bbgo/pkg/exchange/max"
|
"github.com/c9s/bbgo/pkg/exchange/max"
|
||||||
"github.com/c9s/bbgo/pkg/service"
|
"github.com/c9s/bbgo/pkg/service"
|
||||||
|
@ -18,27 +19,55 @@ type Exchange struct {
|
||||||
srv *service.BacktestService
|
srv *service.BacktestService
|
||||||
startTime time.Time
|
startTime time.Time
|
||||||
|
|
||||||
|
account *types.Account
|
||||||
|
config *bbgo.Backtest
|
||||||
closedOrders []types.SubmitOrder
|
closedOrders []types.SubmitOrder
|
||||||
openOrders []types.SubmitOrder
|
openOrders []types.SubmitOrder
|
||||||
|
|
||||||
|
stream *Stream
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewExchange(sourceExchange types.ExchangeName, srv *service.BacktestService, startTime time.Time) *Exchange {
|
func NewExchange(sourceExchange types.ExchangeName, srv *service.BacktestService, config *bbgo.Backtest) *Exchange {
|
||||||
ex, err := newPublicExchange(sourceExchange)
|
ex, err := newPublicExchange(sourceExchange)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if config == nil {
|
||||||
|
panic(errors.New("backtest config can not be nil"))
|
||||||
|
}
|
||||||
|
|
||||||
|
startTime, err := config.ParseStartTime()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
balances := config.Account.Balances.BalanceMap()
|
||||||
|
|
||||||
|
account := &types.Account{
|
||||||
|
MakerCommission: config.Account.MakerCommission,
|
||||||
|
TakerCommission: config.Account.TakerCommission,
|
||||||
|
AccountType: "SPOT", // currently not used
|
||||||
|
}
|
||||||
|
account.UpdateBalances(balances)
|
||||||
|
|
||||||
return &Exchange{
|
return &Exchange{
|
||||||
sourceExchange: sourceExchange,
|
sourceExchange: sourceExchange,
|
||||||
publicExchange: ex,
|
publicExchange: ex,
|
||||||
srv: srv,
|
srv: srv,
|
||||||
|
config: config,
|
||||||
|
account: account,
|
||||||
startTime: startTime,
|
startTime: startTime,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e *Exchange) NewStream() types.Stream {
|
func (e *Exchange) NewStream() types.Stream {
|
||||||
// TODO: return the stream and feed the data
|
if e.stream != nil {
|
||||||
return &Stream{}
|
panic("backtest stream is already allocated, please check if there are extra NewStream calls")
|
||||||
|
}
|
||||||
|
|
||||||
|
e.stream = &Stream{exchange: e}
|
||||||
|
return e.stream
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder) (createdOrders types.OrderSlice, err error) {
|
func (e Exchange) SubmitOrders(ctx context.Context, orders ...types.SubmitOrder) (createdOrders types.OrderSlice, err error) {
|
||||||
|
@ -58,11 +87,11 @@ func (e Exchange) CancelOrders(ctx context.Context, orders ...types.Order) error
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e Exchange) QueryAccount(ctx context.Context) (*types.Account, error) {
|
func (e Exchange) QueryAccount(ctx context.Context) (*types.Account, error) {
|
||||||
panic("implement me")
|
return e.account, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e Exchange) QueryAccountBalances(ctx context.Context) (types.BalanceMap, error) {
|
func (e *Exchange) QueryAccountBalances(ctx context.Context) (types.BalanceMap, error) {
|
||||||
panic("implement me")
|
return e.account.Balances(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (e Exchange) QueryKLines(ctx context.Context, symbol string, interval types.Interval, options types.KLineQueryOptions) ([]types.KLine, error) {
|
func (e Exchange) QueryKLines(ctx context.Context, symbol string, interval types.Interval, options types.KLineQueryOptions) ([]types.KLine, error) {
|
||||||
|
|
|
@ -4,6 +4,7 @@ import (
|
||||||
"context"
|
"context"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
|
log "github.com/sirupsen/logrus"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/types"
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
)
|
)
|
||||||
|
@ -15,6 +16,8 @@ type Stream struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Stream) Connect(ctx context.Context) error {
|
func (s *Stream) Connect(ctx context.Context) error {
|
||||||
|
log.Infof("collecting backtest configurations...")
|
||||||
|
|
||||||
loadedSymbols := map[string]struct{}{}
|
loadedSymbols := map[string]struct{}{}
|
||||||
loadedIntervals := map[types.Interval]struct{}{}
|
loadedIntervals := map[types.Interval]struct{}{}
|
||||||
for _, sub := range s.Subscriptions {
|
for _, sub := range s.Subscriptions {
|
||||||
|
@ -39,6 +42,8 @@ func (s *Stream) Connect(ctx context.Context) error {
|
||||||
intervals = append(intervals, interval)
|
intervals = append(intervals, interval)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Infof("used symbols: %v and intervals: %v", symbols, intervals)
|
||||||
|
|
||||||
// TODO: we can sync before we connect
|
// TODO: we can sync before we connect
|
||||||
/*
|
/*
|
||||||
if err := backtestService.Sync(ctx, exchange, symbol, startTime); err != nil {
|
if err := backtestService.Sync(ctx, exchange, symbol, startTime); err != nil {
|
||||||
|
|
|
@ -4,11 +4,13 @@ import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"reflect"
|
"reflect"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"gopkg.in/yaml.v3"
|
"gopkg.in/yaml.v3"
|
||||||
|
|
||||||
"github.com/c9s/bbgo/pkg/fixedpoint"
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
||||||
|
"github.com/c9s/bbgo/pkg/types"
|
||||||
)
|
)
|
||||||
|
|
||||||
type PnLReporterConfig struct {
|
type PnLReporterConfig struct {
|
||||||
|
@ -57,6 +59,14 @@ type Backtest struct {
|
||||||
Account BacktestAccount `json:"account" yaml:"account"`
|
Account BacktestAccount `json:"account" yaml:"account"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (t Backtest) ParseStartTime() (time.Time, error) {
|
||||||
|
if len(t.StartTime) == 0 {
|
||||||
|
return time.Time{}, errors.New("backtest.startTime must be defined")
|
||||||
|
}
|
||||||
|
|
||||||
|
return time.Parse("2006-01-02", t.StartTime)
|
||||||
|
}
|
||||||
|
|
||||||
type BacktestAccount struct {
|
type BacktestAccount struct {
|
||||||
MakerCommission int `json:"makerCommission"`
|
MakerCommission int `json:"makerCommission"`
|
||||||
TakerCommission int `json:"takerCommission"`
|
TakerCommission int `json:"takerCommission"`
|
||||||
|
@ -67,6 +77,18 @@ type BacktestAccount struct {
|
||||||
|
|
||||||
type BacktestAccountBalanceMap map[string]fixedpoint.Value
|
type BacktestAccountBalanceMap map[string]fixedpoint.Value
|
||||||
|
|
||||||
|
func (m BacktestAccountBalanceMap) BalanceMap() types.BalanceMap {
|
||||||
|
balances := make(types.BalanceMap)
|
||||||
|
for currency, value := range m {
|
||||||
|
balances[currency] = types.Balance{
|
||||||
|
Currency: currency,
|
||||||
|
Available: value.Float64(),
|
||||||
|
Locked: 0.0,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return balances
|
||||||
|
}
|
||||||
|
|
||||||
type Config struct {
|
type Config struct {
|
||||||
Imports []string `json:"imports" yaml:"imports"`
|
Imports []string `json:"imports" yaml:"imports"`
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,7 @@ import (
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
BacktestCmd.Flags().String("exchange", "", "target exchange")
|
BacktestCmd.Flags().String("exchange", "", "target exchange")
|
||||||
BacktestCmd.Flags().String("start", "", "start time")
|
BacktestCmd.Flags().Bool("sync", true, "sync backtest data")
|
||||||
BacktestCmd.Flags().Bool("backtest", true, "sync backtest data")
|
|
||||||
BacktestCmd.Flags().String("config", "config/bbgo.yaml", "strategy config file")
|
BacktestCmd.Flags().String("config", "config/bbgo.yaml", "strategy config file")
|
||||||
RootCmd.AddCommand(BacktestCmd)
|
RootCmd.AddCommand(BacktestCmd)
|
||||||
}
|
}
|
||||||
|
@ -61,27 +60,29 @@ var BacktestCmd = &cobra.Command{
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if userConfig.Backtest == nil {
|
||||||
|
return errors.New("backtest config is not defined")
|
||||||
|
}
|
||||||
|
|
||||||
// set default start time to the past 6 months
|
// set default start time to the past 6 months
|
||||||
startTime := time.Now().AddDate(0, -6, 0)
|
startTime := time.Now().AddDate(0, -6, 0)
|
||||||
|
if len(userConfig.Backtest.StartTime) == 0 {
|
||||||
startTimeArg, err := cmd.Flags().GetString("start")
|
userConfig.Backtest.StartTime = startTime.Format("2006-01-02")
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(startTimeArg) > 0 {
|
|
||||||
startTime, err = time.Parse("2006-01-02", startTimeArg)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
backtestService := &service.BacktestService{DB: db}
|
backtestService := &service.BacktestService{DB: db}
|
||||||
|
|
||||||
exchange := backtest.NewExchange(exchangeName, backtestService, startTime)
|
exchange := backtest.NewExchange(exchangeName, backtestService, userConfig.Backtest)
|
||||||
|
|
||||||
environ := bbgo.NewEnvironment()
|
environ := bbgo.NewEnvironment()
|
||||||
environ.AddExchange(exchangeName.String(), exchange)
|
environ.AddExchange(exchangeName.String(), exchange)
|
||||||
|
|
||||||
|
environ.Notifiability = bbgo.Notifiability{
|
||||||
|
SymbolChannelRouter: bbgo.NewPatternChannelRouter(nil),
|
||||||
|
SessionChannelRouter: bbgo.NewPatternChannelRouter(nil),
|
||||||
|
ObjectChannelRouter: bbgo.NewObjectChannelRouter(),
|
||||||
|
}
|
||||||
|
|
||||||
trader := bbgo.NewTrader(environ)
|
trader := bbgo.NewTrader(environ)
|
||||||
if userConfig.RiskControls != nil {
|
if userConfig.RiskControls != nil {
|
||||||
trader.SetRiskControls(userConfig.RiskControls)
|
trader.SetRiskControls(userConfig.RiskControls)
|
||||||
|
@ -96,7 +97,7 @@ var BacktestCmd = &cobra.Command{
|
||||||
log.Warnf("backtest does not support CrossExchangeStrategy, strategies won't be added.")
|
log.Warnf("backtest does not support CrossExchangeStrategy, strategies won't be added.")
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := trader.Run(ctx) ; err != nil {
|
if err := trader.Run(ctx); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -262,8 +262,8 @@ func (e *Exchange) QueryAccount(ctx context.Context) (*types.Account, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
a := &types.Account{
|
a := &types.Account{
|
||||||
MakerCommission: account.MakerCommission,
|
MakerCommission: int(account.MakerCommission),
|
||||||
TakerCommission: account.TakerCommission,
|
TakerCommission: int(account.TakerCommission),
|
||||||
}
|
}
|
||||||
a.UpdateBalances(balances)
|
a.UpdateBalances(balances)
|
||||||
return a, nil
|
return a, nil
|
||||||
|
@ -537,4 +537,3 @@ func (e *Exchange) BatchQueryKLines(ctx context.Context, symbol string, interval
|
||||||
|
|
||||||
return allKLines, nil
|
return allKLines, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,9 @@ type BalanceMap map[string]Balance
|
||||||
type Account struct {
|
type Account struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
|
|
||||||
MakerCommission int64
|
MakerCommission int `json:"makerCommission"`
|
||||||
TakerCommission int64
|
TakerCommission int `json:"takerCommission"`
|
||||||
AccountType string
|
AccountType string `json:"accountType"`
|
||||||
|
|
||||||
balances BalanceMap
|
balances BalanceMap
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue
Block a user