67 lines
1.4 KiB
Go
67 lines
1.4 KiB
Go
package logic
|
|
|
|
import (
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
var (
|
|
WatchExpireTime = 5 * time.Minute
|
|
WatchReThreshold = 0.61
|
|
|
|
OpenWatch *WatchMu
|
|
PosbuyWatch *WatchMu
|
|
)
|
|
|
|
type dipWatch struct {
|
|
LastClose float64
|
|
ExpiresAt time.Time
|
|
}
|
|
|
|
type WatchMu struct {
|
|
mu *sync.Mutex
|
|
Data map[string]dipWatch
|
|
}
|
|
|
|
func InitWatch() {
|
|
OpenWatch = &WatchMu{
|
|
Data: make(map[string]dipWatch),
|
|
}
|
|
PosbuyWatch = &WatchMu{
|
|
Data: make(map[string]dipWatch),
|
|
}
|
|
}
|
|
|
|
func (w *WatchMu) Triggered(tag, code string, price float64) bool {
|
|
if price <= 0 {
|
|
return false
|
|
}
|
|
w.mu.Lock()
|
|
defer w.mu.Unlock()
|
|
now := time.Now()
|
|
watch, ok := w.Data[code]
|
|
if !ok || now.After(watch.ExpiresAt) || now.Equal(watch.ExpiresAt) {
|
|
w.Data[code] = dipWatch{LastClose: price, ExpiresAt: now.Add(WatchExpireTime)}
|
|
logf("INFO", "[%s-观察] %s 现价=%.2f", tag, code, price)
|
|
return false
|
|
}
|
|
if price < watch.LastClose {
|
|
watch.LastClose = price
|
|
watch.ExpiresAt = now.Add(WatchExpireTime)
|
|
w.Data[code] = watch
|
|
logf("INFO", "[%s-下跌] %s 刷新低点=%.2f", tag, code, price)
|
|
return false
|
|
}
|
|
rebound := (price - watch.LastClose) / watch.LastClose * 100
|
|
if rebound <= 0 {
|
|
return false
|
|
}
|
|
if rebound < WatchReThreshold {
|
|
logf("INFO", "[%s-等待] %s 反弹=%.2f%% 阈值=%.2f%%", tag, code, rebound, WatchReThreshold)
|
|
return false
|
|
}
|
|
delete(w.Data, code)
|
|
logf("INFO", "[%s-触发] %s 反弹=%.2f%% 低点=%.2f", tag, code, rebound, watch.LastClose)
|
|
return true
|
|
}
|