diff --git a/formula/hhv.go b/formula/hhv.go index d68826838b6124218f3712a9416f581aea9ff2a6..385c92275b2af2a3b60a0c9359d2a63dd727f010 100644 --- a/formula/hhv.go +++ b/formula/hhv.go @@ -2,10 +2,7 @@ package formula import "gitee.com/quant1x/pandas" -type InputType interface { - ~int | ~[]float32 | ~[]float64 -} - +// HHV 最近N周期的S最大值 func HHV(S pandas.Series, N any) pandas.Series { return S.Rolling2(N).Max() } diff --git a/formula/llv.go b/formula/llv.go new file mode 100644 index 0000000000000000000000000000000000000000..734996db4dc97be8eb84873f152ade211e3202b9 --- /dev/null +++ b/formula/llv.go @@ -0,0 +1,8 @@ +package formula + +import "gitee.com/quant1x/pandas" + +// LLV 最近N周期的S最小值 +func LLV(S pandas.Series, N any) pandas.Series { + return S.Rolling2(N).Min() +} diff --git a/formula/llv_test.go b/formula/llv_test.go new file mode 100644 index 0000000000000000000000000000000000000000..16db3db5a4351c48a7f55c507d0910f739e016e2 --- /dev/null +++ b/formula/llv_test.go @@ -0,0 +1,49 @@ +package formula + +import ( + "fmt" + "gitee.com/quant1x/pandas" + "testing" +) + +func TestLLV(t *testing.T) { + type testStruct struct { + A string + B int + C bool + D float32 + } + data := []testStruct{ + {"a", 1, true, 0.0}, + {"b", 2, false, 0.5}, + } + df1 := pandas.LoadStructs(data) + fmt.Println(df1) + // 修改列名 + _ = df1.SetNames("a", "b", "c", "d") + // 增加1列 + s_e := pandas.GenericSeries[string]("", "a0", "a1", "a2", "a3") + df2 := df1.Join(s_e) + fmt.Println(df2) + A := df2.Col("a") + B := df2.Col("b") + C := df2.Col("c") + D := df2.Col("d") + + r2 := LLV(D, 2) + fmt.Println(r2) + + r2 = LLV(A, 2) + fmt.Println(r2) + + r2 = LLV(df2.Col("X0"), 2) + fmt.Println(r2) + + r2 = LLV(C, 2) + fmt.Println(r2) + + _ = A + _ = B + _ = C + _ = D +} diff --git a/generic_max.go b/generic_max.go index da8c1662bb25229fe2ff8061d282c23848e9b167..81f1e0b01003640868552f67c3bef18a84afbac0 100644 --- a/generic_max.go +++ b/generic_max.go @@ -68,6 +68,9 @@ func (self *NDFrame) Max() any { // } // return Nil2Float32 case []float32: + if self.Len() == 0 { + return Nil2Float32 + } return stat.Max(rows) //case []float64: // max := float64(0) @@ -87,6 +90,9 @@ func (self *NDFrame) Max() any { // } // return Nil2Float64 case []float64: + if self.Len() == 0 { + return Nil2Float64 + } return stat.Max(rows) default: panic(ErrUnsupportedType) diff --git a/generic_min.go b/generic_min.go index a3da84f3b1791e8ddc25e427c24251f75d6bbd19..43f93854df5ffb9cbba595a2db593fec35a84912 100644 --- a/generic_min.go +++ b/generic_min.go @@ -1,8 +1,24 @@ package pandas +import "gitee.com/quant1x/pandas/stat" + func (self *NDFrame) Min() any { values := self.Values() switch rows := values.(type) { + case []bool: + min := true + i := 0 + for idx, iv := range rows { + if !iv && min { + min = iv + i += 1 + } + _ = idx + } + if i > 0 { + return min + } + return false case []string: min := "" i := 0 @@ -40,26 +56,16 @@ func (self *NDFrame) Min() any { _ = idx } return min - case []float64: - min := float64(0) - i := 0 - for idx, iv := range rows { - if Float64IsNaN(iv) { - continue - } else if i < 1 { - min = iv - i += 1 - } - if iv < min { - min = iv - i += 1 - } - _ = idx + case []float32: + if self.Len() == 0 { + return Nil2Float32 } - if i > 0 { - return min + return stat.Min(rows) + case []float64: + if self.Len() == 0 { + return Nil2Float64 } - return Nil2Float64 + return stat.Min(rows) } return Nil2Float64 } diff --git a/rolling_max.go b/rolling_max.go index bac9f1a5207fcd315c1b031fe5f7b1319b5d8234..5a13c854ba89f6aa4180914fa42e42cef96bdcc9 100644 --- a/rolling_max.go +++ b/rolling_max.go @@ -1,21 +1,19 @@ package pandas -import "sort" - func (r RollingAndExpandingMixin) Max() (s Series) { s = r.series.Empty() for _, block := range r.getBlocks() { - // 1. 排序处理方式 - if block.Len() == 0 { - s.Append(s.NaN()) - continue - } - sort.Sort(block) - r := RangeFinite(-1) - _s := block.Select(r) - s.Append(_s.Values()) + //// 1. 排序处理方式 + //if block.Len() == 0 { + // s.Append(s.NaN()) + // continue + //} + //sort.Sort(block) + //r := RangeFinite(-1) + //_s := block.Select(r) + //s.Append(_s.Values()) // 2. Series.Max方法 - //s.Append(block.Max()) + s.Append(block.Max()) } return } diff --git a/rolling_min.go b/rolling_min.go new file mode 100644 index 0000000000000000000000000000000000000000..5bc79d62cef634db9bc337f6234a01f01614513b --- /dev/null +++ b/rolling_min.go @@ -0,0 +1,19 @@ +package pandas + +func (r RollingAndExpandingMixin) Min() (s Series) { + s = r.series.Empty() + for _, block := range r.getBlocks() { + //// 1. 排序处理方式 + //if block.Len() == 0 { + // s.Append(s.NaN()) + // continue + //} + //sort.Sort(block) + //r := RangeFinite(0, 1) + //_s := block.Select(r) + //s.Append(_s.Values()) + // 2. Series.Max方法 + s.Append(block.Min()) + } + return +} diff --git a/stat/min.go b/stat/min.go new file mode 100644 index 0000000000000000000000000000000000000000..264fd2a39f56ce7a052ac1a1ab56c6685e672ff4 --- /dev/null +++ b/stat/min.go @@ -0,0 +1,27 @@ +package stat + +import ( + "github.com/viterin/vek" + "github.com/viterin/vek/vek32" + "unsafe" +) + +// Min 计算最小值 +func Min[T Float](f []T) T { + if len(f) == 0 { + return T(0) + } + var d any + var s any + s = f + bitSize := unsafe.Sizeof(f[0]) + if bitSize == 4 { + d = vek32.Min(s.([]float32)) + } else if bitSize == 8 { + d = vek.Min(s.([]float64)) + } else { + // 应该不会走到这里 + d = T(0) + } + return d.(T) +}