package logic import ( "big-qmt/go-client/config" "sync" "time" ) type dipWatch struct { LastClose float64 ExpiresAt time.Time } var openDip = struct { mu sync.Mutex store map[string]dipWatch }{store: map[string]dipWatch{}} var posDip = struct { mu sync.Mutex store map[string]dipWatch }{store: map[string]dipWatch{}} func dipTriggered(mu *sync.Mutex, store map[string]dipWatch, tag, code string, price float64) bool { if price <= 0 { return false } mu.Lock() defer mu.Unlock() now := time.Now() watch, ok := store[code] if !ok || now.After(watch.ExpiresAt) || now.Equal(watch.ExpiresAt) { store[code] = dipWatch{LastClose: price, ExpiresAt: now.Add(time.Duration(config.Account.WatchTimeoutSec) * time.Second)} logf("INFO", "[%s-观察] %s 现价=%.2f", tag, code, price) return false } if price < watch.LastClose { watch.LastClose = price watch.ExpiresAt = now.Add(time.Duration(config.Account.WatchTimeoutSec) * time.Second) store[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 < config.Account.ReboundThreshold { logf("INFO", "[%s-等待] %s 反弹=%.2f%% 阈值=%.2f%%", tag, code, rebound, config.Account.ReboundThreshold) return false } delete(store, code) logf("INFO", "[%s-触发] %s 反弹=%.2f%% 低点=%.2f", tag, code, rebound, watch.LastClose) return true }