mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-10 09:11:55 +00:00
all: use types.LooseFormatTime to parse loose format date time string
This commit is contained in:
parent
5f7676f0c1
commit
007207e24f
|
@ -30,10 +30,11 @@ package backtest
|
|||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"github.com/c9s/bbgo/pkg/cache"
|
||||
"sync"
|
||||
"time"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/cache"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/bbgo"
|
||||
|
@ -74,14 +75,12 @@ func NewExchange(sourceName types.ExchangeName, sourceExchange types.Exchange, s
|
|||
return nil, err
|
||||
}
|
||||
|
||||
startTime, err := config.ParseStartTime()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
endTime, err := config.ParseEndTime()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
var startTime, endTime time.Time
|
||||
startTime = config.StartTime.Time()
|
||||
if config.EndTime != nil {
|
||||
endTime = config.EndTime.Time()
|
||||
} else {
|
||||
endTime = time.Now()
|
||||
}
|
||||
|
||||
account := &types.Account{
|
||||
|
|
|
@ -94,16 +94,9 @@ type Session struct {
|
|||
IsolatedMarginSymbol string `json:"isolatedMarginSymbol,omitempty" yaml:"isolatedMarginSymbol,omitempty"`
|
||||
}
|
||||
|
||||
var supportedTimeFormats = []string{
|
||||
time.RFC3339,
|
||||
time.RFC822,
|
||||
"2006-01-02T15:04:05",
|
||||
"2006-01-02",
|
||||
}
|
||||
|
||||
type Backtest struct {
|
||||
StartTime string `json:"startTime" yaml:"startTime"`
|
||||
EndTime string `json:"endTime" yaml:"endTime"`
|
||||
StartTime types.LooseFormatTime `json:"startTime,omitempty" yaml:"startTime,omitempty"`
|
||||
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"`
|
||||
|
@ -112,32 +105,6 @@ type Backtest struct {
|
|||
Session string `json:"session" yaml:"session"`
|
||||
}
|
||||
|
||||
func parseTimeWithFormats(strTime string, formats []string) (time.Time, error) {
|
||||
for _, format := range formats {
|
||||
tt, err := time.Parse(format, strTime)
|
||||
if err == nil {
|
||||
return tt, nil
|
||||
}
|
||||
}
|
||||
return time.Time{}, fmt.Errorf("failed to parse time %s, valid formats are %+v", strTime, formats)
|
||||
}
|
||||
|
||||
func (t Backtest) ParseEndTime() (time.Time, error) {
|
||||
if len(t.EndTime) == 0 {
|
||||
return time.Time{}, errors.New("backtest.endTime must be defined")
|
||||
}
|
||||
|
||||
return parseTimeWithFormats(t.EndTime, supportedTimeFormats)
|
||||
}
|
||||
|
||||
func (t Backtest) ParseStartTime() (time.Time, error) {
|
||||
if len(t.StartTime) == 0 {
|
||||
return time.Time{}, errors.New("backtest.startTime must be defined")
|
||||
}
|
||||
|
||||
return parseTimeWithFormats(t.StartTime, supportedTimeFormats)
|
||||
}
|
||||
|
||||
type BacktestAccount struct {
|
||||
// TODO: MakerFeeRate should replace the commission fields
|
||||
MakerFeeRate fixedpoint.Value `json:"makerFeeRate"`
|
||||
|
|
|
@ -11,16 +11,17 @@ import (
|
|||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/accounting/pnl"
|
||||
"github.com/c9s/bbgo/pkg/backtest"
|
||||
"github.com/c9s/bbgo/pkg/bbgo"
|
||||
"github.com/c9s/bbgo/pkg/cmd/cmdutil"
|
||||
"github.com/c9s/bbgo/pkg/service"
|
||||
"github.com/c9s/bbgo/pkg/types"
|
||||
"github.com/pkg/errors"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
)
|
||||
|
||||
func init() {
|
||||
|
@ -156,24 +157,25 @@ var BacktestCmd = &cobra.Command{
|
|||
return errors.New("backtest config is not defined")
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
var now = time.Now()
|
||||
var startTime, endTime time.Time
|
||||
|
||||
startTime = userConfig.Backtest.StartTime.Time()
|
||||
|
||||
// set default start time to the past 6 months
|
||||
if len(userConfig.Backtest.StartTime) == 0 {
|
||||
userConfig.Backtest.StartTime = now.AddDate(0, -6, 0).Format("2006-01-02")
|
||||
}
|
||||
if len(userConfig.Backtest.EndTime) == 0 {
|
||||
userConfig.Backtest.EndTime = now.Format("2006-01-02")
|
||||
// userConfig.Backtest.StartTime = now.AddDate(0, -6, 0).Format("2006-01-02")
|
||||
|
||||
if userConfig.Backtest.EndTime != nil {
|
||||
endTime = userConfig.Backtest.EndTime.Time()
|
||||
} else {
|
||||
endTime = now
|
||||
}
|
||||
_ = endTime
|
||||
|
||||
if len(userConfig.CrossExchangeStrategies) > 0 {
|
||||
log.Warnf("backtest does not support CrossExchangeStrategy, strategies won't be added.")
|
||||
}
|
||||
|
||||
startTime, err := userConfig.Backtest.ParseStartTime()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
log.Infof("starting backtest with startTime %s", startTime.Format(time.ANSIC))
|
||||
|
||||
environ := bbgo.NewEnvironment()
|
||||
|
|
|
@ -6,6 +6,8 @@ import (
|
|||
"fmt"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"github.com/c9s/bbgo/pkg/util"
|
||||
)
|
||||
|
||||
type NanosecondTimestamp time.Time
|
||||
|
@ -198,3 +200,43 @@ func (t *Time) Scan(src interface{}) error {
|
|||
|
||||
return fmt.Errorf("datatype.Time scan error, type: %T is not supported, value; %+v", src, src)
|
||||
}
|
||||
|
||||
var looseTimeFormats = []string{
|
||||
time.RFC3339,
|
||||
time.RFC822,
|
||||
"2006-01-02T15:04:05",
|
||||
"2006-01-02",
|
||||
}
|
||||
|
||||
// LooseFormatTime parses date time string with a wide range of formats.
|
||||
type LooseFormatTime time.Time
|
||||
|
||||
func (t *LooseFormatTime) UnmarshalYAML(unmarshal func(interface{}) error) error {
|
||||
var str string
|
||||
if err := unmarshal(&str); err == nil {
|
||||
return t.UnmarshalJSON([]byte(str))
|
||||
}
|
||||
|
||||
var bin []byte
|
||||
err := unmarshal(&bin)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return t.UnmarshalJSON(bin)
|
||||
}
|
||||
|
||||
func (t *LooseFormatTime) UnmarshalJSON(data []byte) error {
|
||||
tv, err := util.ParseTimeWithFormats(string(data), looseTimeFormats)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
*t = LooseFormatTime(tv)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (t LooseFormatTime) Time() time.Time {
|
||||
return time.Time(t)
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
package util
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
@ -21,4 +22,18 @@ func Over24Hours(since time.Time) bool {
|
|||
|
||||
func UnixMilli() int64 {
|
||||
return time.Now().UnixNano() / int64(time.Millisecond)
|
||||
}
|
||||
}
|
||||
|
||||
func ParseTimeWithFormats(strTime string, formats []string) (time.Time, error) {
|
||||
for _, format := range formats {
|
||||
tt, err := time.Parse(format, strTime)
|
||||
if err == nil {
|
||||
return tt, nil
|
||||
}
|
||||
}
|
||||
return time.Time{}, fmt.Errorf("failed to parse time %s, valid formats are %+v", strTime, formats)
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue
Block a user