package sig import ( "fmt" "sig-pub/pkg/indicator" "sig-pub/pkg/strategy" "sig-pub/pkg/types" "sig-pub/pkg/utils/collect" ) type StrategyContext struct { strategy.ISingleSigStrategyContext input types.Input kSeries *types.KlineSeries indicatorsReg *indicator.IndicatorRegistry indicatorContextStates IndicatorStates } func NewStrategyContext(input types.Input, kSeries *types.KlineSeries, indicatorsReg *indicator.IndicatorRegistry) *StrategyContext { return &StrategyContext{ input: input, kSeries: kSeries, indicatorsReg: indicatorsReg, indicatorContextStates: NewIndicatorStates(), } } // Input 获取输入参数 func (c *StrategyContext) Input() (in types.Input) { return c.input } func (c *StrategyContext) Get(offset int16) (kline types.Kline) { return c.kSeries.MustGet(offset) } func (c *StrategyContext) Series(offset, count int16) (klines types.Klines) { return c.kSeries.MustSeries(offset, count) } // 获取窗口类型指标 func (c *StrategyContext) Indicator(name string, args ...any) (s indicator.IIndicatorSeries) { indicator, ok := c.indicatorsReg.Indicator(name) if !ok { panic(fmt.Errorf("indicator %s not exists", name)) } input := matchIndicatorArgs(args...) indicatorContext := NewIndicatorContext(indicator, input, c.indicatorContextStates, c.kSeries, c.indicatorsReg) return NewWindowIndicatorSeries(indicator, indicatorContext) } // IntervalStrategyContext 周期策略上下文 type IntervalStrategyContext struct { strategy.IIntervalSigStrategyContext input types.Input intervalKlineSeries *types.IntervalState[*types.KlineSeries] indicatorsReg *indicator.IndicatorRegistry intervalIndicatorContextStates map[types.Interval]IndicatorStates } func NewIntervalStrategyContext(input types.Input, intervalKlineSeries *types.IntervalState[*types.KlineSeries], indicatorsReg *indicator.IndicatorRegistry) *IntervalStrategyContext { return &IntervalStrategyContext{ input: input, intervalKlineSeries: intervalKlineSeries, indicatorsReg: indicatorsReg, intervalIndicatorContextStates: make(map[types.Interval]IndicatorStates), } } // Input 获取输入参数 func (c *IntervalStrategyContext) Input() (in types.Input) { return c.input } func (c *IntervalStrategyContext) getCandleSeries(interval types.Interval) *types.KlineSeries { klineSeries := c.intervalKlineSeries.Get(interval) if klineSeries == nil { panic(fmt.Errorf("interval %s kline series is nil", interval)) } return klineSeries } // Get [0]当前k线 func (c *IntervalStrategyContext) Get(interval types.Interval, offset int16) (kline types.Kline) { ks := c.getCandleSeries(interval) return ks.MustGet(offset) } // Series [offset...end] func (c *IntervalStrategyContext) Series(interval types.Interval, offset, count int16) (klines types.Klines) { cs := c.getCandleSeries(interval) return cs.MustSeries(offset, count) } // 获取窗口类型指标 func (c *IntervalStrategyContext) Indicator(interval types.Interval, name string, args ...any) (series indicator.IIndicatorSeries) { indicator, ok := c.indicatorsReg.Indicator(name) if !ok { panic(fmt.Errorf("indicator %s not exists", name)) } input := matchIndicatorArgs(args...) kSeries := c.getCandleSeries(interval) // 状态传递 state, ok := c.intervalIndicatorContextStates[interval] if !ok { state = NewIndicatorStates() c.intervalIndicatorContextStates[interval] = state } indicatorContext := NewIndicatorContext(indicator, input, state, kSeries, c.indicatorsReg) return NewWindowIndicatorSeries(indicator, indicatorContext) } // InstIntervalStrategyContext 多币种多周期策略上下文 type InstanceIntervalSigStrategyContext struct { strategy.IInstanceIntervalSigStrategyContext input types.Input iiks *types.InstanceIntervalKlineSeries indicatorsReg *indicator.IndicatorRegistry // 指标运行时状态 instanceIntervalIndicatorStates *collect.ConcurrentMap[string, *types.IntervalState[IndicatorStates]] } func NewInstanceIntervalSigStrategyContext(input types.Input, iis *types.InstanceIntervalKlineSeries, indicatorsReg *indicator.IndicatorRegistry) *InstanceIntervalSigStrategyContext { return &InstanceIntervalSigStrategyContext{ input: input, iiks: iis, indicatorsReg: indicatorsReg, instanceIntervalIndicatorStates: collect.NewConcurrentMap[string, *types.IntervalState[IndicatorStates]](4, func(s string) string { return s }), } } // Input 获取输入参数 func (c *InstanceIntervalSigStrategyContext) Input() types.Input { return c.input } // Get [0]当前k线 func (c *InstanceIntervalSigStrategyContext) Get(instId string, interval types.Interval, offset int16) types.Kline { return c.iiks.Get(instId, interval).MustGet(offset) } // Series [offset...end] func (c *InstanceIntervalSigStrategyContext) Series(instId string, interval types.Interval, offset, count int16) (klines types.Klines) { return c.iiks.Get(instId, interval).MustSeries(offset, count) } // 获取窗口类型指标 func (c *InstanceIntervalSigStrategyContext) Indicator(instId string, interval types.Interval, name string, args ...any) indicator.IIndicatorSeries { indicator, ok := c.indicatorsReg.Indicator(name) if !ok { panic(fmt.Errorf("indicator %s not exists", name)) } input := matchIndicatorArgs(args...) kSeries := c.iiks.Get(instId, interval) // 状态传递 intervalIndicatorStates := c.instanceIntervalIndicatorStates.ComputeIfAbsent(instId, func(k string) (iss *types.IntervalState[IndicatorStates]) { iss = types.NewIntervalState[IndicatorStates]() for _, interval := range c.iiks.GetScopeIntervals() { iss.Set(interval, NewIndicatorStates()) } return }) indicatorStates := intervalIndicatorStates.Get(interval) indicatorContext := NewIndicatorContext(indicator, input, indicatorStates, kSeries, c.indicatorsReg) return NewWindowIndicatorSeries(indicator, indicatorContext) }