init
This commit is contained in:
135
com/exm.go
Normal file
135
com/exm.go
Normal file
@@ -0,0 +1,135 @@
|
||||
package com
|
||||
|
||||
import (
|
||||
"math"
|
||||
"slices"
|
||||
)
|
||||
|
||||
type ExmItem struct {
|
||||
BarNum int
|
||||
TimeMS int64
|
||||
Value float64
|
||||
Valid bool
|
||||
}
|
||||
|
||||
type ExmTrace struct {
|
||||
Hist []*ExmItem
|
||||
Expect int // 1寻找极大值,-1寻找极小值
|
||||
PrevVals []float64 // 前一个值
|
||||
PrevDist float64 // 前两个极值的距离
|
||||
distList []float64 // 前面极值距离,保留最近3个
|
||||
}
|
||||
|
||||
/*
|
||||
Update
|
||||
val: 当前指标值
|
||||
pNum: 前一个索引
|
||||
ptime:前一个时间戳
|
||||
*/
|
||||
func (m *ExmTrace) Update(val float64, pNum int, ptime int64) bool {
|
||||
if math.IsNaN(val) {
|
||||
return false
|
||||
}
|
||||
if len(m.PrevVals) < 2 {
|
||||
// 至少积累2个
|
||||
if len(m.PrevVals) > 0 && m.PrevVals[len(m.PrevVals)-1] == val {
|
||||
// 和前一个值相同,跳过
|
||||
return false
|
||||
}
|
||||
m.PrevVals = append(m.PrevVals, val)
|
||||
return false
|
||||
}
|
||||
// 前1个,前2个
|
||||
p1, p2 := m.PrevVals[1], m.PrevVals[0]
|
||||
if p1 == val {
|
||||
// 当前值无效
|
||||
return false
|
||||
}
|
||||
// 更新
|
||||
m.PrevVals = append(m.PrevVals, val)
|
||||
m.PrevVals = m.PrevVals[len(m.PrevVals)-2:]
|
||||
pSub := p1 - p2
|
||||
sub := p1 - val
|
||||
var last *ExmItem
|
||||
if len(m.Hist) > 0 {
|
||||
last = m.Hist[len(m.Hist)-1]
|
||||
}
|
||||
getMinDist := func() float64 {
|
||||
if last == nil {
|
||||
return math.Abs(p1) * 0.3
|
||||
}
|
||||
if m.PrevDist != 0 {
|
||||
return m.PrevDist * 0.3
|
||||
}
|
||||
return max(math.Abs(last.Value), math.Abs(p1)) * 0.3
|
||||
}
|
||||
if pSub*sub <= 0 {
|
||||
// 非极大值或极小值
|
||||
if last != nil && !last.Valid && (val-last.Value)*float64(m.Expect) > getMinDist() {
|
||||
// 检查最后一个是否有效
|
||||
last.Valid = true
|
||||
if len(m.Hist) > 1 {
|
||||
dist := math.Abs(m.Hist[len(m.Hist)-2].Value - m.Hist[len(m.Hist)-1].Value)
|
||||
m.distList = append(m.distList, dist)
|
||||
if len(m.distList) > 3 {
|
||||
m.distList = m.distList[len(m.distList)-3:]
|
||||
}
|
||||
m.PrevDist = slices.Max(m.distList)
|
||||
}
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
valid := 0
|
||||
if sub > 0 {
|
||||
if m.Expect == 0 || m.Expect == 1 {
|
||||
// 新增极大值
|
||||
if last == nil || p1-last.Value >= getMinDist() {
|
||||
valid = -1
|
||||
}
|
||||
} else if p1 > last.Value {
|
||||
// 更新极大值
|
||||
valid = -1
|
||||
}
|
||||
} else if sub < 0 {
|
||||
if m.Expect == 0 || m.Expect == -1 {
|
||||
// 新增极小值
|
||||
if last == nil || last.Value-p1 >= getMinDist() {
|
||||
valid = 1
|
||||
}
|
||||
} else if p1 < last.Value {
|
||||
// 更新极小值
|
||||
valid = 1
|
||||
}
|
||||
}
|
||||
if valid != 0 {
|
||||
exm := &ExmItem{
|
||||
TimeMS: ptime,
|
||||
BarNum: pNum,
|
||||
Value: p1,
|
||||
}
|
||||
if m.Expect != valid {
|
||||
m.Hist = append(m.Hist, exm)
|
||||
//log.Info("add exm", zap.String("date", btime.ToDateStr(ptime, "")),
|
||||
// zap.Float64("val", p1))
|
||||
} else {
|
||||
m.Hist[len(m.Hist)-1] = exm
|
||||
//log.Info("update exm", zap.String("date", btime.ToDateStr(ptime, "")),
|
||||
// zap.Float64("val", p1))
|
||||
}
|
||||
if len(m.Hist) > 2 {
|
||||
dist := math.Abs(m.Hist[len(m.Hist)-3].Value - m.Hist[len(m.Hist)-2].Value)
|
||||
if len(m.distList) == 0 || dist != m.distList[len(m.distList)-1] {
|
||||
m.distList = append(m.distList, dist)
|
||||
if len(m.distList) > 3 {
|
||||
m.distList = m.distList[len(m.distList)-3:]
|
||||
}
|
||||
m.PrevDist = slices.Max(m.distList)
|
||||
}
|
||||
}
|
||||
m.Expect = valid
|
||||
m.PrevVals = nil
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
Reference in New Issue
Block a user