From b3e04a68daa35c03fa0e204b1fef7688fdb883af Mon Sep 17 00:00:00 2001 From: c9s Date: Wed, 6 Jul 2022 21:50:38 +0800 Subject: [PATCH 1/3] bbgo: fix trailing stop binding --- pkg/bbgo/exit.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/pkg/bbgo/exit.go b/pkg/bbgo/exit.go index 91c0d1b2f..a88e3f44d 100644 --- a/pkg/bbgo/exit.go +++ b/pkg/bbgo/exit.go @@ -75,4 +75,8 @@ func (m *ExitMethod) Bind(session *ExchangeSession, orderExecutor *GeneralOrderE if m.CumulatedVolumeTakeProfit != nil { m.CumulatedVolumeTakeProfit.Bind(session, orderExecutor) } + + if m.TrailingStop != nil { + m.TrailingStop.Bind(session, orderExecutor) + } } From 825022715d5069bae8ad507b7b7dbcacdf0248c1 Mon Sep 17 00:00:00 2001 From: c9s Date: Wed, 6 Jul 2022 21:58:26 +0800 Subject: [PATCH 2/3] dynamic: add IterateFields --- pkg/dynamic/iterate.go | 38 +++++++++++++++++++++++++++++++++++++ pkg/dynamic/iterate_test.go | 25 ++++++++++++++++++++++++ 2 files changed, 63 insertions(+) create mode 100644 pkg/dynamic/iterate_test.go diff --git a/pkg/dynamic/iterate.go b/pkg/dynamic/iterate.go index 12d6e2842..47be50891 100644 --- a/pkg/dynamic/iterate.go +++ b/pkg/dynamic/iterate.go @@ -10,6 +10,44 @@ type StructFieldIterator func(tag string, ft reflect.StructField, fv reflect.Val var ErrCanNotIterateNilPointer = errors.New("can not iterate struct on a nil pointer") +func IterateFields(obj interface{}, cb func(ft reflect.StructField, fv reflect.Value) error) error { + sv := reflect.ValueOf(obj) + st := reflect.TypeOf(obj) + + if st.Kind() != reflect.Ptr { + return fmt.Errorf("f should be a pointer of a struct, %s given", st) + } + + // for pointer, check if it's nil + if sv.IsNil() { + return ErrCanNotIterateNilPointer + } + + // solve the reference + st = st.Elem() + sv = sv.Elem() + + if st.Kind() != reflect.Struct { + return fmt.Errorf("f should be a struct, %s given", st) + } + + for i := 0; i < sv.NumField(); i++ { + fv := sv.Field(i) + ft := st.Field(i) + + // skip unexported fields + if !st.Field(i).IsExported() { + continue + } + + if err := cb(ft, fv) ; err != nil { + return err + } + } + + return nil +} + func IterateFieldsByTag(obj interface{}, tagName string, cb StructFieldIterator) error { sv := reflect.ValueOf(obj) st := reflect.TypeOf(obj) diff --git a/pkg/dynamic/iterate_test.go b/pkg/dynamic/iterate_test.go new file mode 100644 index 000000000..61cdc66cc --- /dev/null +++ b/pkg/dynamic/iterate_test.go @@ -0,0 +1,25 @@ +package dynamic + +import ( + "os" + "reflect" + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestIterateFields(t *testing.T) { + var a = struct { + A int + B float64 + C *os.File + }{} + + cnt := 0 + err := IterateFields(&a, func(ft reflect.StructField, fv reflect.Value) error { + cnt++ + return nil + }) + assert.NoError(t, err) + assert.Equal(t, 3, cnt) +} From 81e05a3f2c9831eafacfd0cab3fb6a66ca6a9d4f Mon Sep 17 00:00:00 2001 From: c9s Date: Wed, 6 Jul 2022 22:01:35 +0800 Subject: [PATCH 3/3] add more struct field tests --- pkg/dynamic/iterate.go | 4 ++++ pkg/dynamic/iterate_test.go | 41 +++++++++++++++++++++++++++---------- 2 files changed, 34 insertions(+), 11 deletions(-) diff --git a/pkg/dynamic/iterate.go b/pkg/dynamic/iterate.go index 47be50891..765616392 100644 --- a/pkg/dynamic/iterate.go +++ b/pkg/dynamic/iterate.go @@ -11,6 +11,10 @@ type StructFieldIterator func(tag string, ft reflect.StructField, fv reflect.Val var ErrCanNotIterateNilPointer = errors.New("can not iterate struct on a nil pointer") func IterateFields(obj interface{}, cb func(ft reflect.StructField, fv reflect.Value) error) error { + if obj == nil { + return errors.New("can not iterate field, given object is nil") + } + sv := reflect.ValueOf(obj) st := reflect.TypeOf(obj) diff --git a/pkg/dynamic/iterate_test.go b/pkg/dynamic/iterate_test.go index 61cdc66cc..b15b74bf8 100644 --- a/pkg/dynamic/iterate_test.go +++ b/pkg/dynamic/iterate_test.go @@ -9,17 +9,36 @@ import ( ) func TestIterateFields(t *testing.T) { - var a = struct { - A int - B float64 - C *os.File - }{} - cnt := 0 - err := IterateFields(&a, func(ft reflect.StructField, fv reflect.Value) error { - cnt++ - return nil + t.Run("basic", func(t *testing.T) { + var a = struct { + A int + B float64 + C *os.File + }{} + + cnt := 0 + err := IterateFields(&a, func(ft reflect.StructField, fv reflect.Value) error { + cnt++ + return nil + }) + assert.NoError(t, err) + assert.Equal(t, 3, cnt) }) - assert.NoError(t, err) - assert.Equal(t, 3, cnt) + + t.Run("non-ptr", func(t *testing.T) { + err := IterateFields(struct{}{}, func(ft reflect.StructField, fv reflect.Value) error { + return nil + }) + assert.Error(t, err) + }) + + t.Run("nil", func(t *testing.T) { + err := IterateFields(nil, func(ft reflect.StructField, fv reflect.Value) error { + return nil + }) + assert.Error(t, err) + }) + + }