optimizer: support multi metric value functions

Signed-off-by: c9s <yoanlin93@gmail.com>
This commit is contained in:
c9s 2022-06-20 14:52:40 +08:00
parent 6669db4264
commit 9be38e2421
No known key found for this signature in database
GPG Key ID: 7385E7E464CB0A54
4 changed files with 77 additions and 53 deletions

View File

@ -5,10 +5,10 @@
--- ---
matrix: matrix:
#- type: iterate - type: iterate
# label: interval label: interval
# path: '/exchangeStrategies/0/pivotshort/interval' path: '/exchangeStrategies/0/pivotshort/interval'
# values: [ "5m", "30m" ] values: [ "1m", "5m", "30m" ]
#- type: range #- type: range
# path: '/exchangeStrategies/0/pivotshort/pivotLength' # path: '/exchangeStrategies/0/pivotshort/pivotLength'
@ -17,31 +17,31 @@ matrix:
# max: 200.0 # max: 200.0
# step: 20.0 # step: 20.0
- type: range # - type: range
path: '/exchangeStrategies/0/pivotshort/breakLow/stopEMARange' # path: '/exchangeStrategies/0/pivotshort/breakLow/stopEMARange'
label: stopEMARange # label: stopEMARange
min: 0% # min: 0%
max: 10% # max: 10%
step: 1% # step: 1%
- type: range
path: '/exchangeStrategies/0/pivotshort/exit/roiStopLossPercentage'
label: roiStopLossPercentage
min: 0.5%
max: 2%
step: 0.5%
- type: range
path: '/exchangeStrategies/0/pivotshort/exit/roiTakeProfitPercentage'
label: roiTakeProfitPercentage
min: 10%
max: 50%
step: 5%
- type: range
path: '/exchangeStrategies/0/pivotshort/exit/roiMinTakeProfitPercentage'
label: roiMinTakeProfitPercentage
min: 3%
max: 10%
step: 1%
# - type: range
# path: '/exchangeStrategies/0/pivotshort/exit/roiStopLossPercentage'
# label: roiStopLossPercentage
# min: 0.5%
# max: 2%
# step: 0.5%
#
# - type: range
# path: '/exchangeStrategies/0/pivotshort/exit/roiTakeProfitPercentage'
# label: roiTakeProfitPercentage
# min: 10%
# max: 50%
# step: 5%
#
# - type: range
# path: '/exchangeStrategies/0/pivotshort/exit/roiMinTakeProfitPercentage'
# label: roiMinTakeProfitPercentage
# min: 3%
# max: 10%
# step: 1%
#

View File

@ -104,12 +104,15 @@ var optimizeCmd = &cobra.Command{
// print metrics JSON to stdout // print metrics JSON to stdout
fmt.Println(string(out)) fmt.Println(string(out))
} else { } else {
if len(metrics) > 0 { for n, values := range metrics {
fmt.Printf("%v\n", metrics[0].Labels) if len(values) == 0 {
} continue
}
for _, m := range metrics { fmt.Printf("%v => %s\n", values[0].Labels, n)
fmt.Printf("%v => %v\n", m.Params, m.Value) for _, m := range values {
fmt.Printf("%v => %s %v\n", m.Params, n, m.Value)
}
} }
} }

View File

@ -23,6 +23,18 @@ type Metric struct {
Value fixedpoint.Value `json:"value,omitempty"` Value fixedpoint.Value `json:"value,omitempty"`
} }
func copyParams(params []interface{}) []interface{} {
var c = make([]interface{}, len(params))
copy(c, params)
return c
}
func copyLabels(labels []string) []string {
var c = make([]string, len(labels))
copy(c, labels)
return c
}
type GridOptimizer struct { type GridOptimizer struct {
Config *Config Config *Config
@ -149,10 +161,13 @@ func (o *GridOptimizer) buildOps() []OpFunc {
return ops return ops
} }
func (o *GridOptimizer) Run(executor Executor, configJson []byte) ([]Metric, error) { func (o *GridOptimizer) Run(executor Executor, configJson []byte) (map[string][]Metric, error) {
o.CurrentParams = make([]interface{}, len(o.Config.Matrix)) o.CurrentParams = make([]interface{}, len(o.Config.Matrix))
var metrics []Metric var valueFunctions = map[string]MetricValueFunc{
"totalProfit": TotalProfitMetricValueFunc,
}
var metrics = map[string][]Metric{}
var ops = o.buildOps() var ops = o.buildOps()
var app = func(configJson []byte, next func(configJson []byte) error) error { var app = func(configJson []byte, next func(configJson []byte) error) error {
@ -161,19 +176,20 @@ func (o *GridOptimizer) Run(executor Executor, configJson []byte) ([]Metric, err
return err return err
} }
// TODO: Add more metric value function for metricName, metricFunc := range valueFunctions {
metricValue := TotalProfitMetricValueFunc(summaryReport) var metricValue = metricFunc(summaryReport)
var currentParams = copyParams(o.CurrentParams)
var labels = copyLabels(o.ParamLabels)
var currentParams = make([]interface{}, len(o.CurrentParams)) metrics[metricName] = append(metrics[metricName], Metric{
copy(currentParams, o.CurrentParams) Params: currentParams,
Labels: labels,
Value: metricValue,
})
metrics = append(metrics, Metric{ log.Infof("params: %+v => %s %+v", currentParams, metricName, metricValue)
Params: currentParams, }
Labels: o.ParamLabels,
Value: metricValue,
})
log.Infof("current params: %+v => %+v", currentParams, metricValue)
return nil return nil
} }
@ -193,11 +209,14 @@ func (o *GridOptimizer) Run(executor Executor, configJson []byte) ([]Metric, err
err := wrapper(configJson) err := wrapper(configJson)
sort.Slice(metrics, func(i, j int) bool { for n := range metrics {
a := metrics[i].Value sort.Slice(metrics[n], func(i, j int) bool {
b := metrics[j].Value a := metrics[n][i].Value
return a.Compare(b) > 0 b := metrics[n][j].Value
}) return a.Compare(b) > 0
})
}
return metrics, err return metrics, err
} }

View File

@ -76,6 +76,8 @@ func (e *LocalProcessExecutor) Execute(configJson []byte) (*backtest.SummaryRepo
return e.readReport(output) return e.readReport(output)
} }
// jsonToYamlConfig translate json format config into a YAML format config file
// The generated file is a temp file
func jsonToYamlConfig(dir string, configJson []byte) (*os.File, error) { func jsonToYamlConfig(dir string, configJson []byte) (*os.File, error) {
var o map[string]interface{} var o map[string]interface{}
if err := json.Unmarshal(configJson, &o); err != nil { if err := json.Unmarshal(configJson, &o); err != nil {