package indicator import ( "fmt" "sig-pub/api/pb" "sig-pub/pkg/types" ) // RSI stateless indicator type RSI struct { // types.IntervalWindow window int // 窗口大小 kliner IKlineSeries } // New indicator interface // 依赖注入 // 指标参数注入 func (c RSI) New(klineAccesser IKlineSeries) *RSI { return &RSI{ kliner: klineAccesser, } } // indicator interface func (c *RSI) IntervalWindow(window int) { c.window = window } // Calculate 计算单根k线rsi指标 func (c *RSI) Calculate() (vector float64) { // kline := c.kliner.Get(0) // if kline.Close == kline.High { // // emit buy/sell // } // 读k线, 计算 klineSeries := c.kliner.Series(0, int16(c.window)) // 7根 closeSeries := klineSeries.Close() closeDiff := closeSeries.Diff() avgGain := closeDiff.PositiveValuesOrZero().Abs().Sum() / float64(c.window) avgLoss := closeDiff.NegativeValuesOrZero().Abs().Sum() / float64(c.window) rs := avgGain / avgLoss rsi := 100 - (100 / (1 + rs)) return rsi } func (c *RSI) QueryRange(exchange pb.ExchangeType, instId string, interval types.Interval, rsi int) (query string, err error) { var r types.MeticMatrix _ = r intervalAdder, ok := types.SupportedIntervals[interval] if !ok { err = fmt.Errorf("unsupport interval %s", interval) return } minutes := intervalAdder(0, int64(rsi)) / 1000 / 60 query = fmt.Sprintf(` 100 - 100 / (1 + ( avg_over_time(clamp_min(delta(%s{kind="close", interval="%s", exchange="%s"}), 0)[%dm]) / avg_over_time(abs(clamp_max(delta(%s{kind="close", interval="%s", exchange="%s"}), 0))[%dm]) )) `, instId, interval, exchange, minutes, instId, interval, exchange, minutes) return }