You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
156 lines
3.1 KiB
156 lines
3.1 KiB
package strategy |
|
|
|
import ( |
|
"fmt" |
|
"sig-pub/pkg/types" |
|
|
|
"github.com/spf13/cast" |
|
) |
|
|
|
// 参数类型 |
|
type ParamType int8 |
|
|
|
const ( |
|
_ ParamType = iota |
|
ParamTypeBool |
|
ParamTypeFloat |
|
ParamTypeUFloat |
|
ParamTypeInt |
|
ParamTypeUInt |
|
ParamTypeString |
|
ParamTypeSelect // 单选 |
|
ParamTypeCheckBox // 多选 |
|
) |
|
|
|
type Param struct { |
|
Name string `json:"name"` |
|
Desc string `json:"desc"` |
|
Type ParamType `json:"type"` // 参数类型 |
|
Options []ParamOption `json:"options"` // 单选/多选选项列表 |
|
} |
|
|
|
type ParamOption struct { |
|
Name string `json:"name"` |
|
Desc string `json:"desc"` |
|
} |
|
|
|
// CastValidate 数据类型校验 |
|
func (t Param) TypeValidate(v string) bool { |
|
switch t.Type { |
|
default: |
|
return false |
|
case ParamTypeBool: |
|
if _, e := cast.ToBoolE(v); e != nil { |
|
return false |
|
} |
|
return true |
|
case ParamTypeString: |
|
return true |
|
case ParamTypeInt: |
|
fallthrough |
|
case ParamTypeUInt: |
|
if r, e := cast.ToIntE(v); e != nil { |
|
return false |
|
} else if t.Type == ParamTypeUInt { |
|
return r >= 0 |
|
} |
|
return true |
|
case ParamTypeFloat: |
|
fallthrough |
|
case ParamTypeUFloat: |
|
if r, e := cast.ToFloat64E(v); e != nil { |
|
return false |
|
} else if t.Type == ParamTypeUFloat { |
|
return r >= 0 |
|
} |
|
return true |
|
} |
|
} |
|
|
|
// 策略默认参数 |
|
type ISigStrategyDefaultParam interface { |
|
DefaultParam() map[string]string |
|
} |
|
|
|
// todo Meta 策略调参, 回测引擎自动调参回测(最佳参数) argGenerator.next() (arg, ok) |
|
// argA range -> [1,...,5], argB:=[0.1,...,0.7], argC:=[true,false] |
|
// 可变参数组合 argValidate(argA, ArgB, argC...) bool(true则使用该组合进行回测,记录组合参数回测结果) |
|
type ISigStrategyParamGenerator interface { |
|
NextParam(map[string]string) (map[string]string, bool) // 根据当前策略参数, 返回下一批策略参数(并行回测 stateless) |
|
} |
|
|
|
type IntervalStrategyParam struct { |
|
Interval types.Interval `json:"interval"` // 策略驱动周期 |
|
Param StrategyParam `json:"param"` // 策略执行参数 |
|
} |
|
|
|
type StrategyParam map[string]string |
|
|
|
func (s *StrategyParam) Get(key string) (v string, ok bool) { |
|
if len(*s) == 0 { |
|
return |
|
} |
|
v, ok = (*s)[key] |
|
return |
|
} |
|
|
|
func (s *StrategyParam) GetE(key string) (v string, err error) { |
|
if len(*s) == 0 { |
|
return |
|
} |
|
v, ok := (*s)[key] |
|
if !ok { |
|
err = fmt.Errorf("param %s not provided", key) |
|
return |
|
} |
|
return |
|
} |
|
|
|
func (s *StrategyParam) GetInt(key string) (r int, ok bool) { |
|
v, ok := s.Get(key) |
|
if !ok { |
|
return |
|
} |
|
r, err := cast.ToIntE(v) |
|
if ok = err == nil; !ok { |
|
return |
|
} |
|
return |
|
} |
|
|
|
func (s *StrategyParam) GetInt16E(key string) (r int16, err error) { |
|
v, err := s.GetE(key) |
|
if err != nil { |
|
return |
|
} |
|
r, err = cast.ToInt16E(v) |
|
return |
|
} |
|
|
|
func (s *StrategyParam) GetFloat64(key string) (r float64, ok bool) { |
|
r, err := s.GetFloat64E(key) |
|
if err != nil { |
|
return |
|
} |
|
return r, true |
|
} |
|
func (s *StrategyParam) GetFloat64E(key string) (r float64, err error) { |
|
v, err := s.GetE(key) |
|
if err != nil { |
|
return |
|
} |
|
r, err = cast.ToFloat64E(v) |
|
return |
|
} |
|
|
|
func (s *StrategyParam) GetBool(key string) (r bool, ok bool) { |
|
v, ok := s.Get(key) |
|
if !ok { |
|
return |
|
} |
|
r, err := cast.ToBoolE(v) |
|
if ok = err == nil; !ok { |
|
return |
|
} |
|
return |
|
}
|
|
|