improve pv slice parsing

This commit is contained in:
c9s 2024-07-02 14:45:58 +08:00
parent 3007fa7ed7
commit 0a6d24195b
No known key found for this signature in database
GPG Key ID: 7385E7E464CB0A54
2 changed files with 47 additions and 2 deletions

View File

@ -1,6 +1,7 @@
package types
import (
"bytes"
"encoding/json"
"fmt"
"sort"
@ -180,6 +181,22 @@ func (slice *PriceVolumeSlice) UnmarshalJSON(b []byte) error {
return nil
}
func ParsePriceVolumeKvSliceJSON(b []byte) (PriceVolumeSlice, error) {
type S PriceVolumeSlice
var ts S
err := json.Unmarshal(b, &ts)
if err != nil {
return nil, err
}
if len(ts) > 0 && ts[0].Price.IsZero() {
return nil, fmt.Errorf("unable to parse price volume slice correctly, input given: %s", string(b))
}
return PriceVolumeSlice(ts), nil
}
// ParsePriceVolumeSliceJSON tries to parse a 2 dimensional string array into a PriceVolumeSlice
//
// [["9000", "10"], ["9900", "10"], ... ]
@ -188,7 +205,12 @@ func ParsePriceVolumeSliceJSON(b []byte) (slice PriceVolumeSlice, err error) {
err = json.Unmarshal(b, &as)
if err != nil {
return slice, err
// fallback unmarshalling: if the prefix looks like an object array
if bytes.HasPrefix(b, []byte(`[{`)) {
return ParsePriceVolumeKvSliceJSON(b)
}
return nil, err
}
for _, a := range as {

View File

@ -3,10 +3,33 @@ package types
import (
"testing"
"github.com/c9s/bbgo/pkg/fixedpoint"
"github.com/stretchr/testify/assert"
"github.com/c9s/bbgo/pkg/fixedpoint"
)
func TestPriceVolumeSlice_UnmarshalJSON(t *testing.T) {
t.Run("array of array", func(t *testing.T) {
input := []byte(`[["19000.0","3.0"],["19111.0","2.0"]]`)
slice, err := ParsePriceVolumeSliceJSON(input)
if assert.NoError(t, err) {
assert.Len(t, slice, 2)
assert.Equal(t, "19000", slice[0].Price.String())
assert.Equal(t, "3", slice[0].Volume.String())
}
})
t.Run("array of object", func(t *testing.T) {
input := []byte(`[{ "Price": "19000.0", "Volume":"3.0"},{"Price": "19111.0","Volume": "2.0" }]`)
slice, err := ParsePriceVolumeSliceJSON(input)
if assert.NoError(t, err) {
assert.Len(t, slice, 2)
assert.Equal(t, "19000", slice[0].Price.String())
assert.Equal(t, "3", slice[0].Volume.String())
}
})
}
func TestPriceVolumeSlice_Remove(t *testing.T) {
for _, descending := range []bool{true, false} {
slice := PriceVolumeSlice{}