diff --git a/formula/README.md b/formula/README.md index bb2c3ff1e6370d30a2791d8c4aa82cfaef868504..ed8110333b9c0079826692e7023153e17a8a9b7f 100644 --- a/formula/README.md +++ b/formula/README.md @@ -13,9 +13,9 @@ formula | 0 | IFF | 逻辑判断 | IFF(CLOSE>10,1,2) | [√] | [√] | | 0 | IFN | 逻辑判断 | IFN(CLOSE>10,1,2) | [√] | [√] | | 0 | HHV | 计算N周期内最高 | HHV(HIGH,5) | [√] | [√] | -| 0 | HHVBARS | 求N周期内S最高值到当前周期数, 返回序列 | HHVBARS(HIGH,5) | [x] | [x] | +| 0 | HHVBARS | 求N周期内S最高值到当前周期数, 返回序列 | HHVBARS(HIGH,5) | [√] | [√] | | 0 | LLV | 计算N周期内最低 | LLV(HLOW,5) | [√] | [√] | -| 0 | LLVBARS | 求N周期内S最低值到当前周期数, 返回序列 | LLVBARS(HLOW,5) | [x] | [x] | +| 0 | LLVBARS | 求N周期内S最低值到当前周期数, 返回序列 | LLVBARS(HLOW,5) | [√] | [√] | | 0 | SQRT | 计算S的平方根 | SQRT(CLOSE) | [√] | [√] | | 0 | MAX | 计算AB最大值 | MAX(CLOSE,HIGH) | [√] | [√] | | 0 | MIN | 计算AB最小值 | MIN(CLOSE,HIGH) | [√] | [√] | @@ -34,7 +34,7 @@ formula | 1 | COUNT | COUNT(CLOSE>O,N),最近N天满足S的天数True的天数 | COUNT(CLOSE>LOW,5) | [√] | [√] | | 1 | EVERY | EVERY(CLOSE>O,5),最近N天是否都是True | EVERY(CLOSE>LOW,5) | [X] | [X] | | 1 | EXIST | EXIST(CLOSE>O,5),最近N天是否都是True | EXIST(CLOSE>LOW,5) | [X] | [X] | -| 1 | FILTER | FILTER函数,S满足条件后,将其后N周期内的数据置为0 | FILTER(CLOSE>LOW,5) | [X] | [X] | +| 1 | FILTER | FILTER函数,S满足条件后,将其后N周期内的数据置为0 | FILTER(CLOSE>LOW,5) | [√] | [√] | | 1 | BARSLAST | 上一次条件成立到当前的周期数 | BARSLAST(X) | [√] | [√] | | 1 | BARSLASTCOUNT | 统计连续满足S条件的周期数 | BARSLASTCOUNT(X) | [√] | [ ] | | 1 | BARSSINCEN | N周期内第一次S条件成立到现在的周期数 | BARSSINCEN(S,N) | [√] | [√] | diff --git a/formula/filter.go b/formula/filter.go new file mode 100644 index 0000000000000000000000000000000000000000..18fc92f5e027417f79f2532d0de1b97defb4dda5 --- /dev/null +++ b/formula/filter.go @@ -0,0 +1,43 @@ +package formula + +import ( + "gitee.com/quant1x/pandas/exception" + "gitee.com/quant1x/pandas/stat" +) + +// FILTER 过滤连续出现的信号 +// +// 用法: +// FILTER(X,N):X满足条件后,将其后N周期内的数据置为0,N为常量. +// 例如: +// FILTER(CLOSE>OPEN,5)查找阳线,5天内再次出现的阳线不被记录在内 +func FILTER(S stat.Series, N any) stat.Series { + var W []stat.DType + switch v := N.(type) { + case int: + W = stat.Repeat[stat.DType](stat.DType(v), S.Len()) + case stat.Series: + vs := v.DTypes() + W = stat.Align(vs, stat.DTypeNaN, S.Len()) + default: + panic(exception.New(1, "error window")) + } + length := S.Len() + x := S.DTypes() + for i := 0; i < length; i++ { + if x[i] != 0 { + start := i + 1 + if start >= length { + continue + } + end := i + 1 + int(W[i]) + if end >= length { + end = length + } + for j := start; j < end; j++ { + x[j] = 0 + } + } + } + return stat.NDArray[stat.DType](x) +} diff --git a/formula/filter_test.go b/formula/filter_test.go new file mode 100644 index 0000000000000000000000000000000000000000..27e6567bbf606bf374d4b87522e76f86a13eb74e --- /dev/null +++ b/formula/filter_test.go @@ -0,0 +1,24 @@ +package formula + +import ( + "fmt" + "gitee.com/quant1x/pandas/stat" + "testing" +) + +func TestFILTER(t *testing.T) { + n1 := []float32{1, 0, 1, 1, 1, 1, 1, 1, 1, 1} + fmt.Println(n1) + s1 := stat.NewSeries[float32](n1...) + fmt.Println(FILTER(s1, 5)) + + //w := 2 + //for i := 0; i < len(n1); i++ { + // if n1[i] != 0 { + // for j := i + 1; j < i+1+w; j++ { + // n1[j] = 0 + // } + // } + //} + //fmt.Println(n1) +} diff --git a/stat/repeat.go b/stat/repeat.go index 3d15c1cb3798624cd8a03fbb8b53052e5237a453..bb66cb8549bae388fcb3ec97f22763cb5f9de192 100644 --- a/stat/repeat.go +++ b/stat/repeat.go @@ -26,6 +26,22 @@ func Repeat[T BaseType](f T, n int) []T { return d.([]T) } +// RepeatInto 替换n长度的f的泛型切片 +func RepeatInto[T BaseType](s []T, f T, n int) []T { + switch fs := any(s).(type) { + case []float32: + vek32.Repeat_Into(fs, any(f).(float32), n) + case []float64: + vek.Repeat_Into(fs, any(f).(float64), n) + default: + // 剩下非float32和float64, 循环吧 + for i := 0; i < n; i++ { + s[i] = f + } + } + return s[:n] +} + // Range 产生从0到n-1的数组 func Range[T Number](n int) []T { var dest any