diff --git a/pkg/optimizer/local.go b/pkg/optimizer/local.go index cc3023955..7882a0426 100644 --- a/pkg/optimizer/local.go +++ b/pkg/optimizer/local.go @@ -18,6 +18,12 @@ type Executor interface { Execute(configJson []byte) (*backtest.SummaryReport, error) } +type AsyncHandle struct { + Error error + Report *backtest.SummaryReport + Done chan struct{} +} + type LocalProcessExecutor struct { Bin string WorkDir string @@ -25,30 +31,27 @@ type LocalProcessExecutor struct { OutputDir string } +func (e *LocalProcessExecutor) ExecuteAsync(configJson []byte) *AsyncHandle { + handle := &AsyncHandle{ + Done: make(chan struct{}), + } + + go func() { + report, err := e.Execute(configJson) + handle.Error = err + handle.Report = report + close(handle.Done) + }() + + return handle +} + func (e *LocalProcessExecutor) Execute(configJson []byte) (*backtest.SummaryReport, error) { - var o map[string]interface{} - if err := json.Unmarshal(configJson, &o); err != nil { - return nil, err - } - - yamlConfig, err := yaml.Marshal(o) + tf, err := jsonToYamlConfig(e.ConfigDir, configJson) if err != nil { return nil, err } - tf, err := os.CreateTemp(e.ConfigDir, "bbgo-*.yaml") - if err != nil { - return nil, err - } - - if _, err = tf.Write(yamlConfig); err != nil { - return nil, err - } - - if err := tf.Close(); err != nil { - return nil, err - } - c := exec.Command(e.Bin, "backtest", "--config", tf.Name(), "--output", e.OutputDir, "--subdir") output, err := c.Output() if err != nil { @@ -68,3 +71,30 @@ func (e *LocalProcessExecutor) Execute(configJson []byte) (*backtest.SummaryRepo return summaryReport, nil } + +func jsonToYamlConfig(dir string, configJson []byte) (*os.File, error) { + var o map[string]interface{} + if err := json.Unmarshal(configJson, &o); err != nil { + return nil, err + } + + yamlConfig, err := yaml.Marshal(o) + if err != nil { + return nil, err + } + + tf, err := os.CreateTemp(dir, "bbgo-*.yaml") + if err != nil { + return nil, err + } + + if _, err = tf.Write(yamlConfig); err != nil { + return nil, err + } + + if err := tf.Close(); err != nil { + return nil, err + } + + return tf, nil +} diff --git a/pkg/optimizer/local_test.go b/pkg/optimizer/local_test.go new file mode 100644 index 000000000..1c0298fb7 --- /dev/null +++ b/pkg/optimizer/local_test.go @@ -0,0 +1,21 @@ +package optimizer + +import ( + "os" + "testing" + + "github.com/stretchr/testify/assert" +) + +func Test_jsonToYamlConfig(t *testing.T) { + err := os.Mkdir(".tmpconfig", 0755) + assert.NoError(t, err) + + tf, err := jsonToYamlConfig(".tmpconfig", []byte(`{ + }`)) + assert.NoError(t, err) + assert.NotNil(t, tf) + assert.NotEmpty(t, tf.Name()) + + _ = os.RemoveAll(".tmpconfig") +}