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.
92 lines
2.1 KiB
92 lines
2.1 KiB
package indicator |
|
|
|
import ( |
|
"sig-pub/pkg/types" |
|
) |
|
|
|
// RVI Relative Vigor Index |
|
// RVI = SMA(Num, N) / SMA(Denom, N) |
|
// Num = (Close-Open) + 2*(Close_1-Open_1) + 2*(Close_2-Open_2) + (Close_3-Open_3) |
|
// Denom = (High-Low) + 2*(High_1-Low_1) + 2*(High_2-Low_2) + (High_3-Low_3) |
|
// Signal = (RVI + 2*RVI_1 + 2*RVI_2 + RVI_3) / 6 |
|
type RVI struct { |
|
} |
|
|
|
func (c *RVI) Meta() IndicatorMeta { |
|
return IndicatorMeta{ |
|
Name: "RVI", |
|
Input: []types.InputArg{ |
|
{Name: "window", Type: types.InputTypeUInt, Desc: "窗口大小", Default: 10}, |
|
}, |
|
State: []string{"sig"}, |
|
Plots: []Plot{ |
|
{Name: "RVI", State: "vector", Type: PlotLine, Props: PlotProps{"color": ColorGreen}}, |
|
{Name: "Signal", State: "sig", Type: PlotLine, Props: PlotProps{"color": ColorRed}}, |
|
}, |
|
} |
|
} |
|
|
|
func (c *RVI) CandlePeriods(ctx IIndicatorContext) int16 { |
|
return ctx.Input().Int16("window") + 3 |
|
} |
|
|
|
func (c *RVI) Calculate(ctx IIndicatorContext) (vector float64) { |
|
window := ctx.Input().Int16("window") |
|
|
|
count := window + 3 |
|
klines := ctx.Series(0, count) |
|
|
|
if len(klines) < int(count) { |
|
return |
|
} |
|
|
|
var numSum, denomSum float64 |
|
|
|
for i := int16(0); i < window; i++ { |
|
k0 := klines[i] |
|
k1 := klines[i+1] |
|
k2 := klines[i+2] |
|
k3 := klines[i+3] |
|
|
|
// CO = Close - Open |
|
co0 := k0.CloseF64() - k0.OpenF64() |
|
co1 := k1.CloseF64() - k1.OpenF64() |
|
co2 := k2.CloseF64() - k2.OpenF64() |
|
co3 := k3.CloseF64() - k3.OpenF64() |
|
|
|
// HL = High - Low |
|
hl0 := k0.HighF64() - k0.LowF64() |
|
hl1 := k1.HighF64() - k1.LowF64() |
|
hl2 := k2.HighF64() - k2.LowF64() |
|
hl3 := k3.HighF64() - k3.LowF64() |
|
|
|
val1 := (co0 + 2*co1 + 2*co2 + co3) / 6.0 |
|
val2 := (hl0 + 2*hl1 + 2*hl2 + hl3) / 6.0 |
|
|
|
numSum += val1 |
|
denomSum += val2 |
|
} |
|
|
|
var rvi float64 |
|
if denomSum != 0 { |
|
rvi = numSum / denomSum |
|
} |
|
|
|
ctx.State().Set("rvi", rvi) |
|
|
|
// Calculate Signal |
|
// Signal = (RVI + 2*RVI_1 + 2*RVI_2 + RVI_3) / 6 |
|
rvi1, ok1 := ctx.State().Get("rvi", 1) |
|
rvi2, ok2 := ctx.State().Get("rvi", 2) |
|
rvi3, ok3 := ctx.State().Get("rvi", 3) |
|
|
|
var sig float64 |
|
if ok1 && ok2 && ok3 { |
|
sig = (rvi + 2*rvi1 + 2*rvi2 + rvi3) / 6.0 |
|
} else { |
|
sig = rvi |
|
} |
|
ctx.State().Set("sig", sig) |
|
|
|
return rvi |
|
}
|
|
|