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

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)
}