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