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.
66 lines
1.6 KiB
66 lines
1.6 KiB
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 |
|
}
|
|
|