mirror of
https://github.com/c9s/bbgo.git
synced 2024-11-26 08:45:16 +00:00
bbgo: improve dynamic injection
This commit is contained in:
parent
db4d8a31bc
commit
fa7bab2c3a
|
@ -219,6 +219,16 @@ func (trader *Trader) RunSingleExchangeStrategy(ctx context.Context, strategy Si
|
|||
return errors.New("strategy object is not a struct")
|
||||
}
|
||||
|
||||
if err := parseStructAndInject(strategy,
|
||||
&trader.Graceful,
|
||||
&trader.logger,
|
||||
trader.environment.Notifiability,
|
||||
trader.environment.TradeService,
|
||||
trader.environment.AccountService,
|
||||
) ; err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := trader.injectCommonServices(rs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
@ -229,36 +239,24 @@ func (trader *Trader) RunSingleExchangeStrategy(ctx context.Context, strategy Si
|
|||
|
||||
if symbol, ok := isSymbolBasedStrategy(rs); ok {
|
||||
log.Infof("found symbol based strategy from %s", rs.Type())
|
||||
if _, ok := hasField(rs, "Market"); ok {
|
||||
if market, ok := session.Market(symbol); ok {
|
||||
// let's make the market object passed by pointer
|
||||
if err := injectField(rs, "Market", &market, false); err != nil {
|
||||
return errors.Wrapf(err, "failed to inject Market on %T", strategy)
|
||||
}
|
||||
}
|
||||
|
||||
market, ok := session.Market(symbol)
|
||||
if !ok {
|
||||
return fmt.Errorf("market of symbol %s not found", symbol)
|
||||
}
|
||||
|
||||
// StandardIndicatorSet
|
||||
if _, ok := hasField(rs, "StandardIndicatorSet"); ok {
|
||||
indicatorSet, ok := session.StandardIndicatorSet(symbol)
|
||||
if !ok {
|
||||
return fmt.Errorf("standardIndicatorSet of symbol %s not found", symbol)
|
||||
}
|
||||
|
||||
if err := injectField(rs, "StandardIndicatorSet", indicatorSet, true); err != nil {
|
||||
return errors.Wrapf(err, "failed to inject StandardIndicatorSet on %T", strategy)
|
||||
}
|
||||
}
|
||||
|
||||
if _, ok := hasField(rs, "MarketDataStore"); ok {
|
||||
store, ok := session.MarketDataStore(symbol)
|
||||
if !ok {
|
||||
return fmt.Errorf("marketDataStore of symbol %s not found", symbol)
|
||||
}
|
||||
|
||||
if err := injectField(rs, "MarketDataStore", store, true); err != nil {
|
||||
return errors.Wrapf(err, "failed to inject MarketDataStore on %T", strategy)
|
||||
}
|
||||
if err := parseStructAndInject(strategy, market, indicatorSet, store) ; err != nil {
|
||||
return errors.Wrapf(err, "failed to inject object into %T", strategy)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -357,30 +355,6 @@ func (trader *Trader) Run(ctx context.Context) error {
|
|||
}
|
||||
|
||||
func (trader *Trader) injectCommonServices(rs reflect.Value) error {
|
||||
if err := injectField(rs, "Graceful", &trader.Graceful, true); err != nil {
|
||||
return errors.Wrap(err, "failed to inject Graceful")
|
||||
}
|
||||
|
||||
if err := injectField(rs, "Logger", &trader.logger, false); err != nil {
|
||||
return errors.Wrap(err, "failed to inject Logger")
|
||||
}
|
||||
|
||||
if err := injectField(rs, "Notifiability", &trader.environment.Notifiability, false); err != nil {
|
||||
return errors.Wrap(err, "failed to inject Notifiability")
|
||||
}
|
||||
|
||||
if trader.environment.TradeService != nil {
|
||||
if err := injectField(rs, "TradeService", trader.environment.TradeService, true); err != nil {
|
||||
return errors.Wrap(err, "failed to inject TradeService")
|
||||
}
|
||||
}
|
||||
|
||||
if trader.environment.AccountService != nil {
|
||||
if err := injectField(rs, "AccountService", trader.environment.AccountService, true); err != nil {
|
||||
return errors.Wrap(err, "failed to inject AccountService")
|
||||
}
|
||||
}
|
||||
|
||||
if field, ok := hasField(rs, "Persistence"); ok {
|
||||
if trader.environment.PersistenceServiceFacade == nil {
|
||||
log.Warnf("strategy has Persistence field but persistence service is not defined")
|
||||
|
@ -439,6 +413,10 @@ func parseStructAndInject(f interface{}, objects ...interface{}) error {
|
|||
case reflect.Ptr, reflect.Struct:
|
||||
for oi := 0; oi < len(objects); oi++ {
|
||||
obj := objects[oi]
|
||||
if obj == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
ot := reflect.TypeOf(obj)
|
||||
if ft.AssignableTo(ot) {
|
||||
if !fv.CanSet() {
|
||||
|
@ -451,6 +429,10 @@ func parseStructAndInject(f interface{}, objects ...interface{}) error {
|
|||
case reflect.Interface:
|
||||
for oi := 0; oi < len(objects); oi++ {
|
||||
obj := objects[oi]
|
||||
if obj == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
objT := reflect.TypeOf(obj)
|
||||
log.Debugln(
|
||||
ft.PkgPath(),
|
||||
|
|
|
@ -10,6 +10,18 @@ import (
|
|||
)
|
||||
|
||||
func Test_parseStructAndInject(t *testing.T) {
|
||||
t.Run("skip nil", func(t *testing.T) {
|
||||
ss := struct {
|
||||
a int
|
||||
Env *Environment
|
||||
}{
|
||||
a: 1,
|
||||
Env: nil,
|
||||
}
|
||||
err := parseStructAndInject(&ss, nil)
|
||||
assert.NoError(t, err)
|
||||
assert.Nil(t, ss.Env)
|
||||
})
|
||||
t.Run("pointer", func(t *testing.T) {
|
||||
ss := struct {
|
||||
a int
|
||||
|
|
Loading…
Reference in New Issue
Block a user