2023-11-02 17:03:16 +00:00
|
|
|
package csvsource
|
|
|
|
|
|
|
|
import (
|
|
|
|
"encoding/csv"
|
|
|
|
"strings"
|
|
|
|
"testing"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
"github.com/davecgh/go-spew/spew"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
|
|
|
|
|
|
"github.com/c9s/bbgo/pkg/fixedpoint"
|
|
|
|
. "github.com/c9s/bbgo/pkg/testing/testhelper"
|
|
|
|
"github.com/c9s/bbgo/pkg/types"
|
|
|
|
)
|
|
|
|
|
|
|
|
func assertKLineEq(t *testing.T, exp, act types.KLine, name string) {
|
2023-12-14 07:56:49 +00:00
|
|
|
assert.True(t, exp.StartTime.Equal(act.StartTime.Time()), name)
|
2023-11-02 17:03:16 +00:00
|
|
|
assert.Equal(t, 0, exp.Open.Compare(act.Open), name)
|
|
|
|
assert.Equal(t, 0, exp.High.Compare(act.High), name)
|
|
|
|
assert.Equal(t, 0, exp.Low.Compare(act.Low), name)
|
|
|
|
assert.Equal(t, 0, exp.Close.Compare(act.Close), name)
|
|
|
|
assert.Equal(t, 0, exp.Volume.Compare(act.Volume), name)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCSVKLineReader_ReadWithBinanceDecoder(t *testing.T) {
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
give string
|
|
|
|
want types.KLine
|
|
|
|
err error
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "Read DOHLCV",
|
|
|
|
give: "1609459200000,28923.63000000,29031.34000000,28690.17000000,28995.13000000,2311.81144500",
|
|
|
|
want: types.KLine{
|
|
|
|
StartTime: types.NewTimeFromUnix(1609459200, 0),
|
|
|
|
Open: Number(28923.63),
|
|
|
|
High: Number(29031.34),
|
|
|
|
Low: Number(28690.17),
|
|
|
|
Close: Number(28995.13),
|
|
|
|
// todo this should never happen >>
|
|
|
|
// mustNewFromString and NewFromFloat have different values after parse
|
|
|
|
Volume: fixedpoint.MustNewFromString("2311.81144500")},
|
|
|
|
err: nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Read DOHLC",
|
|
|
|
give: "1609459200000,28923.63000000,29031.34000000,28690.17000000,28995.13000000",
|
|
|
|
want: types.KLine{
|
|
|
|
StartTime: types.NewTimeFromUnix(1609459200, 0),
|
|
|
|
Open: Number(28923.63),
|
|
|
|
High: Number(29031.34),
|
|
|
|
Low: Number(28690.17),
|
|
|
|
Close: Number(28995.13),
|
|
|
|
Volume: Number(0)},
|
|
|
|
err: nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Not enough columns",
|
|
|
|
give: "1609459200000,28923.63000000,29031.34000000",
|
|
|
|
want: types.KLine{},
|
|
|
|
err: ErrNotEnoughColumns,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Invalid time format",
|
|
|
|
give: "23/12/2021,28923.63000000,29031.34000000,28690.17000000,28995.13000000",
|
|
|
|
want: types.KLine{},
|
|
|
|
err: ErrInvalidTimeFormat,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Invalid price format",
|
|
|
|
give: "1609459200000,sixty,29031.34000000,28690.17000000,28995.13000000",
|
|
|
|
want: types.KLine{},
|
|
|
|
err: ErrInvalidPriceFormat,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Invalid volume format",
|
|
|
|
give: "1609459200000,28923.63000000,29031.34000000,28690.17000000,28995.13000000,vol",
|
|
|
|
want: types.KLine{},
|
|
|
|
err: ErrInvalidVolumeFormat,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
reader := NewBinanceCSVKLineReader(csv.NewReader(strings.NewReader(tt.give)))
|
|
|
|
kline, err := reader.Read(time.Hour)
|
|
|
|
assert.Equal(t, tt.err, err)
|
|
|
|
if err == nil {
|
|
|
|
spew.Dump(tt.want)
|
|
|
|
spew.Dump(kline)
|
|
|
|
assertKLineEq(t, tt.want, kline, tt.name)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCSVKLineReader_ReadAllWithDefaultDecoder(t *testing.T) {
|
|
|
|
records := []string{
|
|
|
|
"1609459200000,28923.63000000,29031.34000000,28690.17000000,28995.13000000,2311.81144500",
|
|
|
|
"1609459300000,28928.63000000,30031.34000000,22690.17000000,28495.13000000,3000.00",
|
|
|
|
}
|
|
|
|
reader := NewCSVKLineReader(csv.NewReader(strings.NewReader(strings.Join(records, "\n"))))
|
|
|
|
klines, err := reader.ReadAll(time.Hour)
|
|
|
|
assert.NoError(t, err)
|
|
|
|
assert.Len(t, klines, 2)
|
|
|
|
}
|
|
|
|
|
|
|
|
func TestCSVKLineReader_ReadWithMetaTraderDecoder(t *testing.T) {
|
|
|
|
|
|
|
|
tests := []struct {
|
|
|
|
name string
|
|
|
|
give string
|
|
|
|
want types.KLine
|
|
|
|
err error
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
name: "Read DOHLCV",
|
|
|
|
give: "11/12/2008;16:00;779.527679;780.964756;777.527679;779.964756;5",
|
|
|
|
want: types.KLine{
|
|
|
|
StartTime: types.NewTimeFromUnix(time.Date(2008, 12, 11, 16, 0, 0, 0, time.UTC).Unix(), 0),
|
|
|
|
Open: Number(779.527679),
|
|
|
|
High: Number(780.964756),
|
|
|
|
Low: Number(777.527679),
|
|
|
|
Close: Number(779.964756),
|
|
|
|
Volume: Number(5)},
|
|
|
|
err: nil,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Not enough columns",
|
|
|
|
give: "1609459200000;28923.63000000;29031.34000000",
|
|
|
|
want: types.KLine{},
|
|
|
|
err: ErrNotEnoughColumns,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Invalid time format",
|
|
|
|
give: "23/12/2021;t;28923.63000000;29031.34000000;28690.17000000;28995.13000000",
|
|
|
|
want: types.KLine{},
|
|
|
|
err: ErrInvalidTimeFormat,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Invalid price format",
|
|
|
|
give: "11/12/2008;00:00;sixty;29031.34000000;28690.17000000;28995.13000000",
|
|
|
|
want: types.KLine{},
|
|
|
|
err: ErrInvalidPriceFormat,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
name: "Invalid volume format",
|
|
|
|
give: "11/12/2008;00:00;779.527679;780.964756;777.527679;779.964756;vol",
|
|
|
|
want: types.KLine{},
|
|
|
|
err: ErrInvalidVolumeFormat,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
for _, tt := range tests {
|
|
|
|
t.Run(tt.name, func(t *testing.T) {
|
|
|
|
reader := NewMetaTraderCSVKLineReader(csv.NewReader(strings.NewReader(tt.give)))
|
|
|
|
kline, err := reader.Read(time.Hour)
|
|
|
|
assert.Equal(t, tt.err, err)
|
|
|
|
assertKLineEq(t, tt.want, kline, tt.name)
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|