You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
171 lines
6.0 KiB
171 lines
6.0 KiB
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) |
|
}
|
|
|