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.
73 lines
1.6 KiB
73 lines
1.6 KiB
package indicator |
|
|
|
import ( |
|
"sig-pub/pkg/types" |
|
) |
|
|
|
type KDJ struct { |
|
} |
|
|
|
func (c *KDJ) Meta() IndicatorMeta { |
|
return IndicatorMeta{ |
|
Name: "KDJ", |
|
Input: []types.InputArg{ |
|
{Name: "rsvWindow", Type: types.InputTypeUInt, Desc: "周期"}, // 9 |
|
{Name: "kWindow", Type: types.InputTypeUInt, Desc: "K平滑"}, // 3 |
|
{Name: "dWindow", Type: types.InputTypeUInt, Desc: "D平滑"}, // 3 |
|
}, |
|
State: []string{"k", "d", "j"}, |
|
Plots: []Plot{ |
|
{State: "k", Type: PlotLine, Props: PlotProps{"color": ColorBlue}}, |
|
{State: "d", Type: PlotLine, Props: PlotProps{"color": ColorYellow}}, |
|
{State: "j", Type: PlotLine, Props: PlotProps{"color": ColorPurple}}, |
|
}, |
|
} |
|
} |
|
|
|
func (c *KDJ) CandlePeriods(ctx IIndicatorContext) int16 { |
|
return ctx.Input().Int16("rsvWindow") |
|
} |
|
|
|
func (c *KDJ) Calculate(ctx IIndicatorContext) (vector float64) { |
|
rsvWindow := ctx.Input().Int16("rsvWindow") |
|
kWindow := float64(ctx.Input().Int16("kWindow")) |
|
dWindow := float64(ctx.Input().Int16("dWindow")) |
|
|
|
klines := ctx.Series(0, rsvWindow) |
|
if len(klines) < int(rsvWindow) { |
|
return |
|
} |
|
|
|
closePx := klines[0].CloseF64() |
|
low := klines.Low().Min() |
|
high := klines.High().Max() |
|
|
|
var rsv float64 |
|
if high == low { |
|
rsv = 50 |
|
} else { |
|
rsv = (closePx - low) / (high - low) * 100 |
|
} |
|
|
|
// K |
|
prevK, ok := ctx.State().Get("k", 1) |
|
if !ok { |
|
prevK = 50 |
|
} |
|
k := (kWindow-1)/kWindow*prevK + 1/kWindow*rsv |
|
ctx.State().Set("k", k) |
|
|
|
// D |
|
prevD, ok := ctx.State().Get("d", 1) |
|
if !ok { |
|
prevD = 50 |
|
} |
|
d := (dWindow-1)/dWindow*prevD + 1/dWindow*k |
|
ctx.State().Set("d", d) |
|
|
|
// J |
|
j := 3*k - 2*d |
|
ctx.State().Set("j", j) |
|
|
|
return j |
|
}
|
|
|