Skip to content

Commit

Permalink
add fixedpoint json marshaling
Browse files Browse the repository at this point in the history
  • Loading branch information
c9s committed Dec 7, 2020
1 parent f8dc707 commit 9eaf693
Show file tree
Hide file tree
Showing 5 changed files with 137 additions and 17 deletions.
43 changes: 35 additions & 8 deletions pkg/bbgo/redis_persistence.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ type PersistenceService interface {
type Store interface {
Load(val interface{}) error
Save(val interface{}) error
Reset() error
}

type MemoryService struct {
Expand Down Expand Up @@ -54,10 +55,17 @@ func (store *MemoryStore) Load(val interface{}) error {
v := reflect.ValueOf(val)
if data, ok := store.memory.Slots[store.Key]; ok {
v.Elem().Set(reflect.ValueOf(data).Elem())
} else {
return os.ErrNotExist
}
return nil
}

func (store *MemoryStore) Reset() error {
delete(store.memory.Slots, store.Key)
return nil
}

type JsonPersistenceService struct {
Directory string
}
Expand All @@ -74,6 +82,19 @@ type JsonStore struct {
Directory string
}

func (store JsonStore) Reset() error {
if _, err := os.Stat(store.Directory); os.IsNotExist(err) {
return nil
}

p := filepath.Join(store.Directory, store.ID) + ".json"
if _, err := os.Stat(p); os.IsNotExist(err) {
return nil
}

return os.Remove(p)
}

func (store JsonStore) Load(val interface{}) error {
if _, err := os.Stat(store.Directory); os.IsNotExist(err) {
if err2 := os.Mkdir(store.Directory, 0777); err2 != nil {
Expand All @@ -82,13 +103,18 @@ func (store JsonStore) Load(val interface{}) error {
}

p := filepath.Join(store.Directory, store.ID) + ".json"

if _, err := os.Stat(p); os.IsNotExist(err) {
return os.ErrNotExist
}

data, err := ioutil.ReadFile(p)
if err != nil {
return err
}

if len(data) == 0 {
return nil
return os.ErrNotExist
}

return json.Unmarshal(data, val)
Expand Down Expand Up @@ -149,21 +175,17 @@ func (store *RedisStore) Load(val interface{}) error {
data, err := cmd.Result()
if err != nil {
if err == redis.Nil {
return nil
return os.ErrNotExist
}

return err
}

if len(data) == 0 {
return nil
}

if err := json.Unmarshal([]byte(data), val); err != nil {
return err
return os.ErrNotExist
}

return nil
return json.Unmarshal([]byte(data), val)
}

func (store *RedisStore) Save(val interface{}) error {
Expand All @@ -176,3 +198,8 @@ func (store *RedisStore) Save(val interface{}) error {
_, err = cmd.Result()
return err
}

func (store *RedisStore) Reset() error {
_, err := store.redis.Del(context.Background(), store.ID).Result()
return err
}
69 changes: 69 additions & 0 deletions pkg/bbgo/redis_persistence_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
package bbgo

import (
"os"
"testing"

"github.com/stretchr/testify/assert"

"github.com/c9s/bbgo/pkg/fixedpoint"
)

func TestRedisPersistentService(t *testing.T) {
redisService := NewRedisPersistenceService(&RedisPersistenceConfig{
Host: "127.0.0.1",
Port: "6379",
DB: 0,
})
assert.NotNil(t, redisService)

store := redisService.NewStore("bbgo", "test")
assert.NotNil(t, store)

err := store.Reset()
assert.NoError(t, err)

var fp fixedpoint.Value
err = store.Load(fp)
assert.Error(t, err)
assert.EqualError(t, os.ErrNotExist, err.Error())

fp = fixedpoint.NewFromFloat(3.1415)
err = store.Save(&fp)
assert.NoError(t, err, "should store value without error")

var fp2 fixedpoint.Value
err = store.Load(&fp2)
assert.NoError(t, err, "should load value without error")
assert.Equal(t, fp, fp2)

err = store.Reset()
assert.NoError(t, err)
}

func TestMemoryService(t *testing.T) {
t.Run("load_empty", func(t *testing.T) {
service := NewMemoryService()
store := service.NewStore("test")

j := 0
err := store.Load(&j)
assert.Error(t, err)
})

t.Run("save_and_load", func(t *testing.T) {
service := NewMemoryService()
store := service.NewStore("test")

i := 3
err := store.Save(&i)

assert.NoError(t, err)

var j = 0
err = store.Load(&j)
assert.NoError(t, err)
assert.Equal(t, i, j)
})
}

6 changes: 6 additions & 0 deletions pkg/fixedpoint/convert.go
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,12 @@ func (v *Value) UnmarshalYAML(unmarshal func(a interface{}) error) (err error) {
return err
}

func (v Value) MarshalJSON() ([]byte, error) {
f := float64(v) / DefaultPow
o := fmt.Sprintf("%f", f)
return []byte(o), nil
}

func (v *Value) UnmarshalJSON(data []byte) error {
var a interface{}
var err = json.Unmarshal(data, &a)
Expand Down
4 changes: 2 additions & 2 deletions pkg/indicator/ewma.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,13 @@ func (inc *EWMA) calculateAndUpdate(allKLines []types.KLine) {
}

v1 := math.Floor(inc.Values[len(inc.Values)-1]*100.0) / 100.0
v2 := math.Floor(CalculateKLineEWMA(allKLines, priceF, inc.Window)*100.0) / 100.0
v2 := math.Floor(CalculateKLinesEMA(allKLines, priceF, inc.Window)*100.0) / 100.0
if v1 != v2 {
log.Warnf("ACCUMULATED %s EMA (%d) %f != EMA %f", inc.Interval, inc.Window, v1, v2)
}
}

func CalculateKLineEWMA(allKLines []types.KLine, priceF KLinePriceMapper, window int) float64 {
func CalculateKLinesEMA(allKLines []types.KLine, priceF KLinePriceMapper, window int) float64 {
var multiplier = 2.0 / (float64(window) + 1)
return ewma(MapKLinePrice(allKLines, priceF), multiplier)
}
Expand Down
32 changes: 25 additions & 7 deletions pkg/indicator/ewma_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1025,7 +1025,7 @@ func buildKLines(prices []float64) (klines []types.KLine) {
func Test_calculateEWMA(t *testing.T) {
type args struct {
allKLines []types.KLine
priceF KLinePriceMapper
priceF KLinePriceMapper
window int
}
tests := []struct {
Expand All @@ -1034,21 +1034,39 @@ func Test_calculateEWMA(t *testing.T) {
want float64
}{
{
name: "ethusdt ewma 7",
name: "ETHUSDT EMA 7",
args: args{
allKLines: buildKLines(ethusdt5m),
priceF: KLineClosePriceMapper,
priceF: KLineClosePriceMapper,
window: 7,
},
want: 571.72, // with open price, binance disktop returns 571.45, trading view returns 570.8957, for close price, binance mobile returns 571.72
want: 571.72, // with open price, binance desktop returns 571.45, trading view returns 570.8957, for close price, binance mobile returns 571.72
},
{
name: "ETHUSDT EMA 25",
args: args{
allKLines: buildKLines(ethusdt5m),
priceF: KLineClosePriceMapper,
window: 25,
},
want: 571.30,
},
{
name: "ETHUSDT EMA 99",
args: args{
allKLines: buildKLines(ethusdt5m),
priceF: KLineClosePriceMapper,
window: 99,
},
want: 577.62, // binance mobile uses 577.58
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got := CalculateKLineEWMA(tt.args.allKLines, tt.args.priceF, tt.args.window)
got = math.Trunc(got * 100.0) / 100.0
got := CalculateKLinesEMA(tt.args.allKLines, tt.args.priceF, tt.args.window)
got = math.Trunc(got*100.0) / 100.0
if got != tt.want {
t.Errorf("CalculateKLineEWMA() = %v, want %v", got, tt.want)
t.Errorf("CalculateKLinesEMA() = %v, want %v", got, tt.want)
}
})
}
Expand Down

0 comments on commit 9eaf693

Please sign in to comment.