25 changed files with 360 additions and 228 deletions
@ -0,0 +1,35 @@ |
|||||||
|
package indicator |
||||||
|
|
||||||
|
import ( |
||||||
|
"sig-pub/pkg/types" |
||||||
|
) |
||||||
|
|
||||||
|
// EMA stateful indicator
|
||||||
|
type EMA struct { |
||||||
|
} |
||||||
|
|
||||||
|
func (c *EMA) Name() string { |
||||||
|
return "ema" |
||||||
|
} |
||||||
|
|
||||||
|
func (c *EMA) RequiredSeries(window int16, in types.Input) int16 { |
||||||
|
return window + 1 |
||||||
|
} |
||||||
|
|
||||||
|
// Calculate 计算单根k线sma指标
|
||||||
|
func (c *EMA) Calculate(ctx IIndicatorContext, window int16) (vector float64) { |
||||||
|
alpha := 2.0 / float64(window+1) |
||||||
|
|
||||||
|
close := ctx.Get(0).CloseF64() |
||||||
|
prevSMA := ctx.Series(1, window).Close().Avg() |
||||||
|
|
||||||
|
vector = ((close - prevSMA) * alpha) + prevSMA |
||||||
|
|
||||||
|
// ctx.GetSelf(0) // 自己计算的上一个值
|
||||||
|
|
||||||
|
// 计算eam
|
||||||
|
// closeSeries := ctx.Series(0, window).Close().Reverse()
|
||||||
|
// ema := talib.Ema(closeSeries, int(window))
|
||||||
|
// vector = ema[len(ema)-1]
|
||||||
|
return |
||||||
|
} |
||||||
@ -0,0 +1,34 @@ |
|||||||
|
package indicator |
||||||
|
|
||||||
|
import ( |
||||||
|
"sig-pub/pkg/types" |
||||||
|
|
||||||
|
"github.com/markcheno/go-talib" |
||||||
|
) |
||||||
|
|
||||||
|
// todo macdSignal(信号线) macdHist(柱状图)
|
||||||
|
type MACD struct { |
||||||
|
} |
||||||
|
|
||||||
|
func (c *MACD) Name() string { |
||||||
|
return "macd" |
||||||
|
} |
||||||
|
|
||||||
|
func (c *MACD) RequiredSeries(window int16, in types.Input) int16 { |
||||||
|
return window |
||||||
|
} |
||||||
|
|
||||||
|
// Calculate 计算单根k线sma指标
|
||||||
|
func (c *MACD) Calculate(ctx IIndicatorContext, window int16) (vector float64) { |
||||||
|
fast := ctx.Input().Int("fast") |
||||||
|
slow := ctx.Input().Int("slow") |
||||||
|
|
||||||
|
// 计算eam
|
||||||
|
closeSeries := ctx.Series(0, window).Close().Reverse() |
||||||
|
|
||||||
|
aa, bb, cc := talib.Macd(closeSeries, fast, slow, int(window)) |
||||||
|
_, _, _ = aa, bb, cc |
||||||
|
|
||||||
|
vector = 0 |
||||||
|
return |
||||||
|
} |
||||||
@ -0,0 +1,85 @@ |
|||||||
|
package types |
||||||
|
|
||||||
|
import ( |
||||||
|
"fmt" |
||||||
|
|
||||||
|
"github.com/spf13/cast" |
||||||
|
) |
||||||
|
|
||||||
|
const ( |
||||||
|
inputCacheKey = "__$cache__" |
||||||
|
) |
||||||
|
|
||||||
|
type Input map[string]any |
||||||
|
|
||||||
|
// getCache 避免多线程读写cache map
|
||||||
|
func (in Input) getCache(k string) (r any, ok bool) { |
||||||
|
if in == nil { |
||||||
|
return |
||||||
|
} |
||||||
|
c, ok := in[inputCacheKey] |
||||||
|
if !ok { |
||||||
|
return |
||||||
|
} |
||||||
|
r, ok = c.(map[string]any)[k] |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
func (in Input) setCache(k string, v any) { |
||||||
|
if in == nil { |
||||||
|
return |
||||||
|
} |
||||||
|
c, ok := in[inputCacheKey] |
||||||
|
if !ok { |
||||||
|
c = make(map[string]any, 4) |
||||||
|
in[inputCacheKey] = c |
||||||
|
} |
||||||
|
c.(map[string]any)[k] = v |
||||||
|
} |
||||||
|
|
||||||
|
func (in Input) get(k string, t string) (r any) { |
||||||
|
if in == nil { |
||||||
|
panic(fmt.Errorf("input %s type %s not provide", k, t)) |
||||||
|
} |
||||||
|
r, ok := in[k] |
||||||
|
if !ok { |
||||||
|
panic(fmt.Errorf("input %s type %s not provide", k, t)) |
||||||
|
} |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
func (in Input) Float(k string) (v float64) { |
||||||
|
if r, ok := in.getCache(k); ok { |
||||||
|
return r.(float64) |
||||||
|
} |
||||||
|
v, err := cast.ToFloat64E(in.get(k, "float")) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Errorf("input float parse error: %s", k)) |
||||||
|
} |
||||||
|
in.setCache(k, v) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
func (in Input) Int(k string) (v int) { |
||||||
|
if r, ok := in.getCache(k); ok { |
||||||
|
return r.(int) |
||||||
|
} |
||||||
|
v, err := cast.ToIntE(in.get(k, "int")) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Errorf("input int parse error: %s", k)) |
||||||
|
} |
||||||
|
in.setCache(k, v) |
||||||
|
return |
||||||
|
} |
||||||
|
|
||||||
|
func (in Input) Int16(k string) (v int16) { |
||||||
|
if r, ok := in.getCache(k); ok { |
||||||
|
return r.(int16) |
||||||
|
} |
||||||
|
v, err := cast.ToInt16E(in.get(k, "int16")) |
||||||
|
if err != nil { |
||||||
|
panic(fmt.Errorf("input int16 parse error: %s", k)) |
||||||
|
} |
||||||
|
in.setCache(k, v) |
||||||
|
return |
||||||
|
} |
||||||
Loading…
Reference in new issue