improve parsing for one or more string slice

This commit is contained in:
c9s 2020-10-23 13:50:17 +08:00
parent 3786792214
commit 9127913370
3 changed files with 89 additions and 29 deletions

View File

@ -11,6 +11,15 @@ reportTrades:
"bnbusdt": "bbgo-bnbusdt" "bnbusdt": "bbgo-bnbusdt"
"sxpusdt": "bbgo-sxpusdt" "sxpusdt": "bbgo-sxpusdt"
reportPnL:
- averageCostBySymbols:
- "BTCUSDT"
- "BNBUSDT"
of: binance
when:
- @daily
- @hourly
sessions: sessions:
max: max:
exchange: max exchange: max
@ -22,9 +31,9 @@ sessions:
secretVar: BINANCE_API_SECRET secretVar: BINANCE_API_SECRET
exchangeStrategies: exchangeStrategies:
- on: binance - on: binance
buyandhold: buyandhold:
symbol: "BTCUSDT" symbol: "BTCUSDT"
interval: "1m" interval: "1m"
baseQuantity: 0.1 baseQuantity: 0.1
minDropPercentage: -0.05 minDropPercentage: -0.05

View File

@ -16,9 +16,40 @@ type SingleExchangeStrategyConfig struct {
Strategy bbgo.SingleExchangeStrategy Strategy bbgo.SingleExchangeStrategy
} }
type StringSlice []string
func (s *StringSlice) UnmarshalJSON(b []byte) (err error) {
var a interface{}
err = json.Unmarshal(b, &a)
if err != nil {
return err
}
switch d := a.(type) {
case string:
*s = append(*s, d)
case []string:
*s = append(*s, d...)
default:
err = errors.New("unexpected type for StringSlice")
}
return err
}
type PnLReporter struct {
AverageCostBySymbols StringSlice `json:"averageCostBySymbols"`
Of StringSlice `json:"of" yaml:"of"`
When StringSlice `json:"when" yaml:"when"`
}
type Config struct { type Config struct {
ExchangeStrategies []SingleExchangeStrategyConfig ExchangeStrategies []SingleExchangeStrategyConfig
CrossExchangeStrategies []bbgo.CrossExchangeStrategy CrossExchangeStrategies []bbgo.CrossExchangeStrategy
PnLReporters []PnLReporter `json:"reportPnL"`
} }
type Stash map[string]interface{} type Stash map[string]interface{}
@ -45,38 +76,51 @@ func Load(configFile string) (*Config, error) {
return nil, err return nil, err
} }
strategies, err := loadExchangeStrategies(stash) if err := loadExchangeStrategies(&config, stash); err != nil {
if err != nil {
return nil, err return nil, err
} }
config.ExchangeStrategies = strategies if err := loadCrossExchangeStrategies(&config, stash); err != nil {
crossExchangeStrategies, err := loadCrossExchangeStrategies(stash)
if err != nil {
return nil, err return nil, err
} }
config.CrossExchangeStrategies = crossExchangeStrategies if err := loadReportPnL(&config, stash); err != nil {
return nil, err
}
return &config, nil return &config, nil
} }
func loadCrossExchangeStrategies(stash Stash) (strategies []bbgo.CrossExchangeStrategy, err error) { func loadReportPnL(config *Config, stash Stash) error {
reporterStash, ok := stash["reportPnL"]
if !ok {
return nil
}
reporters, err := reUnmarshal(reporterStash, &config.PnLReporters)
if err != nil {
return err
}
config.PnLReporters = *(reporters.(*[]PnLReporter))
return nil
}
func loadCrossExchangeStrategies(config *Config, stash Stash) (err error) {
exchangeStrategiesConf, ok := stash["crossExchangeStrategies"] exchangeStrategiesConf, ok := stash["crossExchangeStrategies"]
if !ok { if !ok {
return strategies, nil return nil
} }
configList, ok := exchangeStrategiesConf.([]interface{}) configList, ok := exchangeStrategiesConf.([]interface{})
if !ok { if !ok {
return nil, errors.New("expecting list in crossExchangeStrategies") return errors.New("expecting list in crossExchangeStrategies")
} }
for _, entry := range configList { for _, entry := range configList {
configStash, ok := entry.(Stash) configStash, ok := entry.(Stash)
if !ok { if !ok {
return nil, errors.Errorf("strategy config should be a map, given: %T %+v", entry, entry) return errors.Errorf("strategy config should be a map, given: %T %+v", entry, entry)
} }
for id, conf := range configStash { for id, conf := range configStash {
@ -84,34 +128,32 @@ func loadCrossExchangeStrategies(stash Stash) (strategies []bbgo.CrossExchangeSt
if st, ok := bbgo.LoadedExchangeStrategies[id]; ok { if st, ok := bbgo.LoadedExchangeStrategies[id]; ok {
val, err := reUnmarshal(conf, st) val, err := reUnmarshal(conf, st)
if err != nil { if err != nil {
return nil, err return err
} }
strategies = append(strategies, val.(bbgo.CrossExchangeStrategy)) config.CrossExchangeStrategies = append(config.CrossExchangeStrategies, val.(bbgo.CrossExchangeStrategy))
} }
} }
} }
return strategies, nil return nil
} }
func loadExchangeStrategies(stash Stash) (strategies []SingleExchangeStrategyConfig, err error) { func loadExchangeStrategies(config *Config, stash Stash) (err error) {
exchangeStrategiesConf, ok := stash["exchangeStrategies"] exchangeStrategiesConf, ok := stash["exchangeStrategies"]
if !ok { if !ok {
return strategies, nil return nil
// return nil, errors.New("exchangeStrategies is not defined")
} }
configList, ok := exchangeStrategiesConf.([]interface{}) configList, ok := exchangeStrategiesConf.([]interface{})
if !ok { if !ok {
return nil, errors.New("expecting list in exchangeStrategies") return errors.New("expecting list in exchangeStrategies")
} }
for _, entry := range configList { for _, entry := range configList {
configStash, ok := entry.(Stash) configStash, ok := entry.(Stash)
if !ok { if !ok {
return nil, errors.Errorf("strategy config should be a map, given: %T %+v", entry, entry) return errors.Errorf("strategy config should be a map, given: %T %+v", entry, entry)
} }
var mounts []string var mounts []string
@ -128,10 +170,10 @@ func loadExchangeStrategies(stash Stash) (strategies []SingleExchangeStrategyCon
if st, ok := bbgo.LoadedExchangeStrategies[id]; ok { if st, ok := bbgo.LoadedExchangeStrategies[id]; ok {
val, err := reUnmarshal(conf, st) val, err := reUnmarshal(conf, st)
if err != nil { if err != nil {
return nil, err return err
} }
strategies = append(strategies, SingleExchangeStrategyConfig{ config.ExchangeStrategies = append(config.ExchangeStrategies, SingleExchangeStrategyConfig{
Mounts: mounts, Mounts: mounts,
Strategy: val.(bbgo.SingleExchangeStrategy), Strategy: val.(bbgo.SingleExchangeStrategy),
}) })
@ -139,7 +181,7 @@ func loadExchangeStrategies(stash Stash) (strategies []SingleExchangeStrategyCon
} }
} }
return strategies, nil return nil
} }
func reUnmarshal(conf interface{}, tpe interface{}) (interface{}, error) { func reUnmarshal(conf interface{}, tpe interface{}) (interface{}, error) {

View File

@ -15,3 +15,12 @@ exchangeStrategies:
interval: "1m" interval: "1m"
baseQuantity: 0.1 baseQuantity: 0.1
minDropPercentage: -0.05 minDropPercentage: -0.05
reportPnL:
- averageCostBySymbols:
- "BTCUSDT"
- "BNBUSDT"
of: binance
when:
- "@daily"
- "@hourly"