bbgo_origin/pkg/backtest/dumper.go

98 lines
2.1 KiB
Go
Raw Permalink Normal View History

2022-05-09 10:03:03 +00:00
package backtest
import (
"fmt"
"path/filepath"
"strconv"
"time"
"go.uber.org/multierr"
2022-05-16 14:24:15 +00:00
"github.com/c9s/bbgo/pkg/data/tsv"
2022-05-09 10:03:03 +00:00
"github.com/c9s/bbgo/pkg/types"
)
const DateFormat = "2006-01-02T15:04"
type symbolInterval struct {
Symbol string
Interval types.Interval
}
// KLineDumper dumps the received kline data into a folder for the backtest report to load the charts.
type KLineDumper struct {
OutputDirectory string
2022-05-16 14:24:15 +00:00
writers map[symbolInterval]*tsv.Writer
2022-05-09 10:03:03 +00:00
filenames map[symbolInterval]string
}
func NewKLineDumper(outputDirectory string) *KLineDumper {
return &KLineDumper{
OutputDirectory: outputDirectory,
2022-05-16 14:24:15 +00:00
writers: make(map[symbolInterval]*tsv.Writer),
2022-05-09 10:03:03 +00:00
filenames: make(map[symbolInterval]string),
}
}
func (d *KLineDumper) Filenames() map[symbolInterval]string {
return d.filenames
}
func (d *KLineDumper) formatFileName(symbol string, interval types.Interval) string {
2022-05-16 14:24:15 +00:00
return filepath.Join(d.OutputDirectory, fmt.Sprintf("%s-%s.tsv",
2022-05-09 10:03:03 +00:00
symbol,
interval))
}
var csvHeader = []string{"date", "startTime", "endTime", "interval", "open", "high", "low", "close", "volume"}
func (d *KLineDumper) encode(k types.KLine) []string {
return []string{
time.Time(k.StartTime).Format(time.ANSIC), // ANSIC date - for javascript to parse (this works with Date.parse(date_str)
strconv.FormatInt(k.StartTime.Unix(), 10),
strconv.FormatInt(k.EndTime.Unix(), 10),
k.Interval.String(),
k.Open.String(),
k.High.String(),
k.Low.String(),
k.Close.String(),
k.Volume.String(),
}
}
func (d *KLineDumper) Record(k types.KLine) error {
si := symbolInterval{Symbol: k.Symbol, Interval: k.Interval}
w, ok := d.writers[si]
if !ok {
filename := d.formatFileName(k.Symbol, k.Interval)
2022-05-16 14:24:15 +00:00
w2, err := tsv.NewWriterFile(filename)
2022-05-09 10:03:03 +00:00
if err != nil {
return err
}
2022-05-16 14:24:15 +00:00
w = w2
2022-05-09 10:03:03 +00:00
2022-05-16 14:24:15 +00:00
d.writers[si] = w2
2022-05-09 10:03:03 +00:00
d.filenames[si] = filename
2022-05-16 14:24:15 +00:00
if err2 := w2.Write(csvHeader); err2 != nil {
return err2
2022-05-09 10:03:03 +00:00
}
}
2022-05-16 14:24:15 +00:00
return w.Write(d.encode(k))
2022-05-09 10:03:03 +00:00
}
func (d *KLineDumper) Close() error {
2022-05-16 14:24:15 +00:00
var err error = nil
2022-05-09 10:03:03 +00:00
for _, w := range d.writers {
w.Flush()
2022-05-16 14:24:15 +00:00
err2 := w.Close()
2022-05-09 10:03:03 +00:00
if err2 != nil {
err = multierr.Append(err, err2)
}
}
return err
}